platform: apq8084: Add support for CE clocks

CRs-Fixed: 586343
Change-Id: I1e4630a08ac47d7a2afa64d7bde37373ba0a0b65
diff --git a/platform/apq8084/acpuclock.c b/platform/apq8084/acpuclock.c
index 873eeda..0cd1d8d 100644
--- a/platform/apq8084/acpuclock.c
+++ b/platform/apq8084/acpuclock.c
@@ -217,14 +217,110 @@
  */
 static void ce_async_reset(uint8_t instance)
 {
+	if (instance == 1)
+	{
+		/* Start the block reset for CE */
+		writel(1, GCC_CE1_BCR);
+
+		udelay(2);
+
+		/* Take CE block out of reset */
+		writel(0, GCC_CE1_BCR);
+
+		udelay(2);
+	}
+	else if (instance == 2)
+	{
+		/* Start the block reset for CE */
+		writel(1, GCC_CE2_BCR);
+
+		udelay(2);
+
+		/* Take CE block out of reset */
+		writel(0, GCC_CE2_BCR);
+
+		udelay(2);
+	}
+	else
+	{
+		dprintf(CRITICAL, "CE instance not supported instance = %d", instance);
+		ASSERT(0);
+	}
 }
 
 void clock_ce_enable(uint8_t instance)
 {
+	int ret;
+	char clk_name[64];
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_src_clk", instance);
+	ret = clk_get_set_enable(clk_name, 100000000, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set %s ret = %d\n", clk_name, ret);
+		ASSERT(0);
+	}
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_core_clk", instance);
+	ret = clk_get_set_enable(clk_name, 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set %s ret = %d\n", clk_name, ret);
+		ASSERT(0);
+	}
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_ahb_clk", instance);
+	ret = clk_get_set_enable(clk_name, 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set %s ret = %d\n", clk_name, ret);
+		ASSERT(0);
+	}
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_axi_clk", instance);
+	ret = clk_get_set_enable(clk_name, 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set %s ret = %d\n", clk_name, ret);
+		ASSERT(0);
+	}
+
+	/* Wait for 48 * #pipes cycles.
+	 * This is necessary as immediately after an access control reset (boot up)
+	 * or a debug re-enable, the Crypto core sequentially clears its internal
+	 * pipe key storage memory. If pipe key initialization writes are attempted
+	 * during this time, they may be overwritten by the internal clearing logic.
+	 */
+	udelay(1);
 }
 
 void clock_ce_disable(uint8_t instance)
 {
+	struct clk *ahb_clk;
+	struct clk *cclk;
+	struct clk *axi_clk;
+	struct clk *src_clk;
+	char clk_name[64];
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_src_clk", instance);
+	src_clk = clk_get(clk_name);
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_ahb_clk", instance);
+	ahb_clk = clk_get(clk_name);
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_axi_clk", instance);
+	axi_clk = clk_get(clk_name);
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_core_clk", instance);
+	cclk    = clk_get(clk_name);
+
+	clk_disable(ahb_clk);
+	clk_disable(axi_clk);
+	clk_disable(cclk);
+	clk_disable(src_clk);
+
+	/* Some delay for the clocks to stabalize. */
+	udelay(1);
 }
 
 void clock_config_ce(uint8_t instance)
diff --git a/platform/apq8084/apq8084-clock.c b/platform/apq8084/apq8084-clock.c
index cedafec..1b5504c 100644
--- a/platform/apq8084/apq8084-clock.c
+++ b/platform/apq8084/apq8084-clock.c
@@ -396,6 +396,111 @@
 	},
 };
 
+/* CE Clocks */
+static struct clk_freq_tbl ftbl_gcc_ce2_clk[] = {
+	F( 50000000,  gpll0,  12,   0,   0),
+	F(100000000,  gpll0,   6,   0,   0),
+	F_END
+};
+
+static struct rcg_clk ce2_clk_src = {
+	.cmd_reg      = (uint32_t *) GCC_CE2_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) GCC_CE2_CFG_RCGR,
+	.set_rate     = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl     = ftbl_gcc_ce2_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "ce2_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
+static struct vote_clk gcc_ce2_clk = {
+	.cbcr_reg = (uint32_t *) GCC_CE2_CBCR,
+	.vote_reg = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask  = BIT(2),
+
+	.c = {
+		.dbg_name = "gcc_ce2_clk",
+		.ops      = &clk_ops_vote,
+	},
+};
+
+static struct vote_clk gcc_ce2_ahb_clk = {
+	.cbcr_reg = (uint32_t *) GCC_CE2_AHB_CBCR,
+	.vote_reg = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask  = BIT(0),
+
+	.c = {
+		.dbg_name = "gcc_ce2_ahb_clk",
+		.ops      = &clk_ops_vote,
+	},
+};
+
+static struct vote_clk gcc_ce2_axi_clk = {
+	.cbcr_reg = (uint32_t *) GCC_CE2_AXI_CBCR,
+	.vote_reg = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask  = BIT(1),
+
+	.c = {
+		.dbg_name = "gcc_ce2_axi_clk",
+		.ops      = &clk_ops_vote,
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_ce1_clk[] = {
+	F( 50000000,  gpll0,  12,   0,   0),
+	F(100000000,  gpll0,   6,   0,   0),
+	F_END
+};
+
+static struct rcg_clk ce1_clk_src = {
+	.cmd_reg      = (uint32_t *) GCC_CE1_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) GCC_CE1_CFG_RCGR,
+	.set_rate     = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl     = ftbl_gcc_ce1_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "ce1_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
+static struct vote_clk gcc_ce1_clk = {
+	.cbcr_reg = (uint32_t *) GCC_CE1_CBCR,
+	.vote_reg = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask  = BIT(5),
+
+	.c = {
+		.dbg_name = "gcc_ce1_clk",
+		.ops      = &clk_ops_vote,
+	},
+};
+
+static struct vote_clk gcc_ce1_ahb_clk = {
+	.cbcr_reg = (uint32_t *) GCC_CE1_AHB_CBCR,
+	.vote_reg = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask  = BIT(3),
+
+	.c = {
+		.dbg_name = "gcc_ce1_ahb_clk",
+		.ops      = &clk_ops_vote,
+	},
+};
+
+static struct vote_clk gcc_ce1_axi_clk = {
+	.cbcr_reg = (uint32_t *) GCC_CE1_AXI_CBCR,
+	.vote_reg = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask  = BIT(4),
+
+	.c = {
+		.dbg_name = "gcc_ce1_axi_clk",
+		.ops      = &clk_ops_vote,
+	},
+};
+
 /* Display clocks */
 static struct clk_freq_tbl ftbl_mdss_esc0_1_clk[] = {
 	F_MM(19200000,    cxo,   1,   0,   0),
@@ -621,6 +726,16 @@
 	CLK_LOOKUP("usb_iface_clk",  gcc_usb_hs_ahb_clk.c),
 	CLK_LOOKUP("usb_core_clk",   gcc_usb_hs_system_clk.c),
 
+	CLK_LOOKUP("ce2_ahb_clk",  gcc_ce2_ahb_clk.c),
+	CLK_LOOKUP("ce2_axi_clk",  gcc_ce2_axi_clk.c),
+	CLK_LOOKUP("ce2_core_clk", gcc_ce2_clk.c),
+	CLK_LOOKUP("ce2_src_clk",  ce2_clk_src.c),
+
+	CLK_LOOKUP("ce1_ahb_clk",  gcc_ce1_ahb_clk.c),
+	CLK_LOOKUP("ce1_axi_clk",  gcc_ce1_axi_clk.c),
+	CLK_LOOKUP("ce1_core_clk", gcc_ce1_clk.c),
+	CLK_LOOKUP("ce1_src_clk",  ce1_clk_src.c),
+
 	/* USB 3.0 */
 	CLK_LOOKUP("usb30_iface_clk",  gcc_sys_noc_usb30_axi_clk.c),
 	CLK_LOOKUP("usb30_master_clk", gcc_usb30_master_clk.c),
diff --git a/platform/apq8084/include/platform/iomap.h b/platform/apq8084/include/platform/iomap.h
index b09e214..b5218e4 100644
--- a/platform/apq8084/include/platform/iomap.h
+++ b/platform/apq8084/include/platform/iomap.h
@@ -74,6 +74,22 @@
 
 #define CLK_CTL_BASE                0xFC400000
 
+/* CE 1 */
+#define  GCC_CE1_BCR                (CLK_CTL_BASE + 0x1040)
+#define  GCC_CE1_CMD_RCGR           (CLK_CTL_BASE + 0x1050)
+#define  GCC_CE1_CFG_RCGR           (CLK_CTL_BASE + 0x1054)
+#define  GCC_CE1_CBCR               (CLK_CTL_BASE + 0x1044)
+#define  GCC_CE1_AXI_CBCR           (CLK_CTL_BASE + 0x1048)
+#define  GCC_CE1_AHB_CBCR           (CLK_CTL_BASE + 0x104C)
+
+/* CE 2 */
+#define  GCC_CE2_BCR                (CLK_CTL_BASE + 0x1080)
+#define  GCC_CE2_CMD_RCGR           (CLK_CTL_BASE + 0x1090)
+#define  GCC_CE2_CFG_RCGR           (CLK_CTL_BASE + 0x1094)
+#define  GCC_CE2_CBCR               (CLK_CTL_BASE + 0x1084)
+#define  GCC_CE2_AXI_CBCR           (CLK_CTL_BASE + 0x1088)
+#define  GCC_CE2_AHB_CBCR           (CLK_CTL_BASE + 0x108C)
+
 /* GPLL */
 #define GPLL0_STATUS                (CLK_CTL_BASE + 0x001C)
 #define APCS_GPLL_ENA_VOTE          (CLK_CTL_BASE + 0x1480)