platform: msmtitanium: add support for display clocks

Update the titanium clock header file with display related clock
register offsets. Update titanium clock driver with the required
display clock structures and register the clocks. Add DSI
clocks, MDP clocks, BUS clocks and GDSC clock enable/disable
APIs for msmtitanium target.

Change-Id: Ic54f24a743bb0ef47f053e2418816ba835705528
diff --git a/platform/msmtitanium/acpuclock.c b/platform/msmtitanium/acpuclock.c
index 58fc686..6b72ac9 100755
--- a/platform/msmtitanium/acpuclock.c
+++ b/platform/msmtitanium/acpuclock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -205,6 +205,93 @@
 	}
 }
 
+/* Control the MDSS GDSC */
+void mdp_gdsc_ctrl(uint8_t enable)
+{
+	uint32_t reg = 0;
+	reg = readl(MDP_GDSCR);
+	if (enable) {
+		if (!(reg & GDSC_POWER_ON_BIT)) {
+			reg &=  ~(BIT(0) | GDSC_EN_FEW_WAIT_MASK);
+			reg |= GDSC_EN_FEW_WAIT_256_MASK;
+			writel(reg, MDP_GDSCR);
+			while(!(readl(MDP_GDSCR) & (GDSC_POWER_ON_BIT)));
+		} else {
+			dprintf(SPEW, "MDP GDSC already enabled\n");
+		}
+	} else {
+		reg |= BIT(0);
+		writel(reg, MDP_GDSCR);
+		while(readl(MDP_GDSCR) & (GDSC_POWER_ON_BIT));
+	}
+}
+
+/* Enable all the MDP branch clocks */
+void mdp_clock_enable(void)
+{
+	int ret;
+
+	ret = clk_get_set_enable("mdp_ahb_clk", 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set mdp_ahb_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	/* Set MDP clock to 320MHz */
+	ret = clk_get_set_enable("mdss_mdp_clk_src", 320000000, 1);
+
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set mdp_clk_src ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable("mdss_vsync_clk", 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set mdss vsync clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable("mdss_mdp_clk", 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set mdp_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+}
+
+/* Disable all the MDP branch clocks */
+void mdp_clock_disable(void)
+{
+	clk_disable(clk_get("mdss_vsync_clk"));
+	clk_disable(clk_get("mdss_mdp_clk"));
+	clk_disable(clk_get("mdss_mdp_clk_src"));
+	clk_disable(clk_get("mdp_ahb_clk"));
+}
+
+/* Disable all the bus clocks needed by MDSS */
+void mdss_bus_clocks_disable(void)
+{
+	/* Disable MDSS AXI clock */
+	clk_disable(clk_get("mdss_axi_clk"));
+}
+
+/* Enable all the bus clocks needed by MDSS */
+void mdss_bus_clocks_enable(void)
+{
+	int ret;
+
+	/* Configure AXI clock */
+	ret = clk_get_set_enable("mdss_axi_clk", 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set mdss_axi_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+}
+
 /* Function to asynchronously reset CE.
  * Function assumes that all the CE clocks are off.
  */
@@ -380,3 +467,103 @@
 		return;
 	}
 }
+
+static void rcg_update_config(uint32_t reg)
+{
+	int i;
+
+	for (i = 0; i < MAX_LOOPS; i++) {
+		if (!(readl(reg) & BIT(0)))
+			return;
+		udelay(1);
+	}
+
+	dprintf(CRITICAL, "failed to update rcg config for reg = 0x%x\n", reg);
+	ASSERT(0);
+}
+
+static void branch_clk_halt_check(uint32_t reg)
+{
+	int i;
+
+	for (i = 0; i < MAX_LOOPS; i++) {
+		if (!(readl(reg) & BIT(31)))
+			return;
+		udelay(1);
+	}
+
+	dprintf(CRITICAL, "failed to enable branch for reg = 0x%x\n", reg);
+	ASSERT(0);
+}
+
+void mmss_dsi_clock_enable(uint32_t cfg_rcgr, uint32_t flags,
+		uint8_t pclk0_m, uint8_t pclk0_n, uint8_t pclk0_d)
+{
+	int ret;
+
+	if (flags & MMSS_DSI_CLKS_FLAG_DSI0) {
+		/* Enable DSI0 branch clocks */
+
+		writel(cfg_rcgr, DSI_BYTE0_CFG_RCGR);
+		writel(0x1, DSI_BYTE0_CMD_RCGR);
+		rcg_update_config(DSI_BYTE0_CMD_RCGR);
+		writel(0x1, DSI_BYTE0_CBCR);
+		branch_clk_halt_check(DSI_BYTE0_CBCR);
+
+		writel(cfg_rcgr, DSI_PIXEL0_CFG_RCGR);
+		writel(pclk0_m, DSI_PIXEL0_M);
+		writel(pclk0_n, DSI_PIXEL0_N);
+		writel(pclk0_d, DSI_PIXEL0_D);
+		writel(0x1, DSI_PIXEL0_CMD_RCGR);
+		rcg_update_config(DSI_PIXEL0_CMD_RCGR);
+		writel(0x1, DSI_PIXEL0_CBCR);
+		branch_clk_halt_check(DSI_PIXEL0_CBCR);
+
+		ret = clk_get_set_enable("mdss_esc0_clk", 0, 1);
+		if(ret)
+		{
+			dprintf(CRITICAL, "failed to set esc0_clk ret = %d\n", ret);
+			ASSERT(0);
+		}
+	}
+
+	if (flags & MMSS_DSI_CLKS_FLAG_DSI1) {
+		/* Enable DSI1 branch clocks */
+		writel(cfg_rcgr, DSI_BYTE1_CFG_RCGR);
+		writel(0x1, DSI_BYTE1_CMD_RCGR);
+		rcg_update_config(DSI_BYTE1_CMD_RCGR);
+		writel(0x1, DSI_BYTE1_CBCR);
+		branch_clk_halt_check(DSI_BYTE1_CBCR);
+
+		writel(cfg_rcgr, DSI_PIXEL1_CFG_RCGR);
+		writel(pclk0_m, DSI_PIXEL1_M);
+		writel(pclk0_n, DSI_PIXEL1_N);
+		writel(pclk0_d, DSI_PIXEL1_D);
+		writel(0x1, DSI_PIXEL1_CMD_RCGR);
+		rcg_update_config(DSI_PIXEL1_CMD_RCGR);
+		writel(0x1, DSI_PIXEL1_CBCR);
+		branch_clk_halt_check(DSI_PIXEL1_CBCR);
+
+		ret = clk_get_set_enable("mdss_esc1_clk", 0, 1);
+		if(ret)
+		{
+			dprintf(CRITICAL, "failed to set esc1_clk ret = %d\n", ret);
+			ASSERT(0);
+		}
+	}
+}
+
+void mmss_dsi_clock_disable(uint32_t flags)
+{
+	if (flags & MMSS_DSI_CLKS_FLAG_DSI0) {
+		clk_disable(clk_get("mdss_esc0_clk"));
+		writel(0x0, DSI_BYTE0_CBCR);
+		writel(0x0, DSI_PIXEL0_CBCR);
+	}
+
+	if (flags & MMSS_DSI_CLKS_FLAG_DSI1) {
+		clk_disable(clk_get("mdss_esc1_clk"));
+		writel(0x0, DSI_BYTE1_CBCR);
+		writel(0x0, DSI_PIXEL1_CBCR);
+	}
+}
diff --git a/platform/msmtitanium/include/platform/clock.h b/platform/msmtitanium/include/platform/clock.h
index 86d1f9b..9743c08 100755
--- a/platform/msmtitanium/include/platform/clock.h
+++ b/platform/msmtitanium/include/platform/clock.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -34,6 +34,57 @@
 
 #define UART_DM_CLK_RX_TX_BIT_RATE 0xCC
 
+#define REG_MM(off)                     (CLK_CTL_BASE + (off))
+
+#define MDP_GDSCR                       REG_MM(0x4D078)
+#define GDSC_POWER_ON_BIT               BIT(31)
+#define GDSC_POWER_ON_STATUS_BIT        BIT(29)
+#define GDSC_EN_FEW_WAIT_MASK           (0x0F << 16)
+#define GDSC_EN_FEW_WAIT_256_MASK       BIT(19)
+
+#define VSYNC_CMD_RCGR                  REG_MM(0x4D02C)
+#define VSYNC_CFG_RCGR                  REG_MM(0x4D030)
+#define MDSS_VSYNC_CBCR                 REG_MM(0x4D090)
+
+#define MDP_CMD_RCGR                    REG_MM(0x4D014)
+#define MDP_CFG_RCGR                    REG_MM(0x4D018)
+#define MDP_CBCR                        REG_MM(0x4D088)
+#define MDP_AHB_CBCR                    REG_MM(0x4D07C)
+#define MDP_AXI_CBCR                    REG_MM(0x4D080)
+
+#define DSI_BYTE0_CMD_RCGR              REG_MM(0x4D044)
+#define DSI_BYTE0_CFG_RCGR              REG_MM(0x4D048)
+#define DSI_BYTE0_CBCR                  REG_MM(0x4D094)
+#define DSI_ESC0_CMD_RCGR               REG_MM(0x4D05C)
+#define DSI_ESC0_CFG_RCGR               REG_MM(0x4D060)
+#define DSI_ESC0_CBCR                   REG_MM(0x4D098)
+#define DSI_PIXEL0_CMD_RCGR             REG_MM(0x4D000)
+#define DSI_PIXEL0_CFG_RCGR             REG_MM(0x4D004)
+#define DSI_PIXEL0_CBCR                 REG_MM(0x4D084)
+#define DSI_PIXEL0_M                    REG_MM(0x4D008)
+#define DSI_PIXEL0_N                    REG_MM(0x4D00C)
+#define DSI_PIXEL0_D                    REG_MM(0x4D010)
+
+#define DSI0_PHY_PLL_OUT                BIT(8)
+#define DSI1_PHY_PLL_OUT                BIT(9)
+#define PIXEL_SRC_DIV_1_5               BIT(1)
+
+#define DSI_BYTE1_CMD_RCGR              REG_MM(0x4D0B0)
+#define DSI_BYTE1_CFG_RCGR              REG_MM(0x4D0B4)
+#define DSI_BYTE1_CBCR                  REG_MM(0x4D0A0)
+#define DSI_ESC1_CMD_RCGR               REG_MM(0x4D0A8)
+#define DSI_ESC1_CFG_RCGR               REG_MM(0x4D0AC)
+#define DSI_ESC1_CBCR                   REG_MM(0x4D09C)
+#define DSI_PIXEL1_CMD_RCGR             REG_MM(0x4D0B8)
+#define DSI_PIXEL1_CFG_RCGR             REG_MM(0x4D0BC)
+#define DSI_PIXEL1_CBCR                 REG_MM(0x4D0A4)
+#define DSI_PIXEL1_M                    REG_MM(0x4D0C0)
+#define DSI_PIXEL1_N                    REG_MM(0x4D0C4)
+#define DSI_PIXEL1_D                    REG_MM(0x4D0C8)
+
+#define MMSS_DSI_CLKS_FLAG_DSI0         BIT(0)
+#define MMSS_DSI_CLKS_FLAG_DSI1         BIT(1)
+
 void platform_clock_init(void);
 
 void clock_init_mmc(uint32_t interface);
@@ -43,6 +94,14 @@
 void clock_config_ce(uint8_t instance);
 void clock_ce_enable(uint8_t instance);
 void clock_ce_disable(uint8_t instance);
+void mdp_gdsc_ctrl(uint8_t enable);
+void mdss_bus_clocks_enable(void);
+void mdss_bus_clocks_disable(void);
+void mdp_clock_enable(void);
+void mdp_clock_disable(void);
+void mmss_dsi_clock_enable(uint32_t cfg_rcgr, uint32_t dual_dsi,
+		uint8_t pclk0_m, uint8_t pclk0_n, uint8_t pclk0_d);
+void mmss_dsi_clock_disable(uint32_t dual_dsi);
 void clock_usb30_init(void);
 void clock_reset_usb_phy();
 #endif
diff --git a/platform/msmtitanium/msmtitanium-clock.c b/platform/msmtitanium/msmtitanium-clock.c
index ff1e313..5401eb1 100755
--- a/platform/msmtitanium/msmtitanium-clock.c
+++ b/platform/msmtitanium/msmtitanium-clock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -476,6 +476,115 @@
 	},
 };
 
+/* Display clocks */
+static struct clk_freq_tbl ftbl_mdss_esc0_1_clk[] = {
+	F_MM(19200000,    cxo,   1,   0,   0),
+	F_END
+};
+
+static struct clk_freq_tbl ftbl_mdp_clk[] = {
+	F( 200000000,           gpll0,    4,    0,     0),
+	F( 266670000,           gpll0,    3,    0,     0),
+	F( 320000000,           gpll0,  2.5,    0,     0),
+	F( 400000000,           gpll0,    2,    0,     0),
+	F_END
+};
+
+static struct rcg_clk dsi_esc0_clk_src = {
+	.cmd_reg  = (uint32_t *) DSI_ESC0_CMD_RCGR,
+	.cfg_reg  = (uint32_t *) DSI_ESC0_CFG_RCGR,
+	.set_rate = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl = ftbl_mdss_esc0_1_clk,
+
+	.c        = {
+		.dbg_name = "dsi_esc0_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_vsync_clk[] = {
+	F_MM(19200000,    cxo,   1,   0,   0),
+	F_END
+};
+
+static struct rcg_clk vsync_clk_src = {
+	.cmd_reg  = (uint32_t *) VSYNC_CMD_RCGR,
+	.cfg_reg  = (uint32_t *) VSYNC_CFG_RCGR,
+	.set_rate = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl = ftbl_mdss_vsync_clk,
+
+	.c        = {
+		.dbg_name = "vsync_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
+static struct branch_clk mdss_esc0_clk = {
+	.cbcr_reg    = (uint32_t *) DSI_ESC0_CBCR,
+	.parent      = &dsi_esc0_clk_src.c,
+	.has_sibling = 0,
+
+	.c           = {
+		.dbg_name = "mdss_esc0_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk mdss_axi_clk = {
+	.cbcr_reg    = (uint32_t *) MDP_AXI_CBCR,
+	.has_sibling = 1,
+
+	.c           = {
+		.dbg_name = "mdss_axi_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk mdp_ahb_clk = {
+	.cbcr_reg    = (uint32_t *) MDP_AHB_CBCR,
+	.has_sibling = 1,
+
+	.c           = {
+		.dbg_name = "mdp_ahb_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct rcg_clk mdss_mdp_clk_src = {
+	.cmd_reg      = (uint32_t *) MDP_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) MDP_CFG_RCGR,
+	.set_rate     = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl     = ftbl_mdp_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c            = {
+		.dbg_name = "mdss_mdp_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
+static struct branch_clk mdss_mdp_clk = {
+	.cbcr_reg    = (uint32_t *) MDP_CBCR,
+	.parent      = &mdss_mdp_clk_src.c,
+	.has_sibling = 0,
+
+	.c           = {
+		.dbg_name = "mdss_mdp_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk mdss_vsync_clk = {
+	.cbcr_reg    = (uint32_t *) MDSS_VSYNC_CBCR,
+	.parent      = &vsync_clk_src.c,
+	.has_sibling = 0,
+
+	.c           = {
+		.dbg_name = "mdss_vsync_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 static struct clk_freq_tbl ftbl_gcc_ce1_clk[] = {
 	F(160000000,  gpll0,   5,   0,   0),
 	F_END
@@ -600,6 +709,13 @@
 	CLK_LOOKUP("usb_phy_cfg_ahb_clk", gcc_usb_phy_cfg_ahb_clk.c),
 	CLK_LOOKUP("usb30_sleep_clk", gcc_usb30_sleep_clk.c),
 
+	CLK_LOOKUP("mdp_ahb_clk",          mdp_ahb_clk.c),
+	CLK_LOOKUP("mdss_esc0_clk",        mdss_esc0_clk.c),
+	CLK_LOOKUP("mdss_axi_clk",         mdss_axi_clk.c),
+	CLK_LOOKUP("mdss_vsync_clk",       mdss_vsync_clk.c),
+	CLK_LOOKUP("mdss_mdp_clk_src",     mdss_mdp_clk_src.c),
+	CLK_LOOKUP("mdss_mdp_clk",         mdss_mdp_clk.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),