Clock: Add clock driver in LK.

Change-Id: Ia46807498607b61670953e7f7510e9a169f00622
diff --git a/platform/msm8960/acpuclock.c b/platform/msm8960/acpuclock.c
index 0301de8..66eaf0b 100644
--- a/platform/msm8960/acpuclock.c
+++ b/platform/msm8960/acpuclock.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -33,9 +33,10 @@
 #include <uart_dm.h>
 #include <gsbi.h>
 #include <mmc.h>
+#include <clock.h>
 
 /* Set rate and enable the clock */
-void clock_config(uint32_t ns, uint32_t md, uint32_t ns_addr, uint32_t md_addr)
+static void clock_config(uint32_t ns, uint32_t md, uint32_t ns_addr, uint32_t md_addr)
 {
 	unsigned int val = 0;
 
@@ -105,120 +106,65 @@
 	writel(val, cc_addr);
 }
 
-void pll8_enable(void)
-{
-	unsigned int curr_value = 0;
-
-	/* Vote for PLL8 to be enabled */
-	curr_value = readl(MSM_BOOT_PLL_ENABLE_SC0);
-	curr_value |= (1 << 8);
-	writel(curr_value, MSM_BOOT_PLL_ENABLE_SC0);
-
-	/* Proceed only after PLL is enabled */
-	while (!(readl(MSM_BOOT_PLL8_STATUS) & (1 << 16))) ;
-}
-
 void hsusb_clock_init(void)
 {
-	/* TODO: Enable pll8 here */
-	/* Setup USB AHB clock */
-
-	/* Setup XCVR clock */
-	clock_config(USB_XCVR_CLK_NS,
-		     USB_XCVR_CLK_MD,
-		     USB_HS1_XCVR_FS_CLK_NS, USB_HS1_XCVR_FS_CLK_MD);
+	clk_get_set_enable("usb_hs_clk", 60000000, 1);
 }
 
 /* Configure UART clock - based on the gsbi id */
 void clock_config_uart_dm(uint8_t id)
 {
-	/* Enable gsbi_uart_clk */
-	clock_config(UART_DM_CLK_NS_115200,
-		     UART_DM_CLK_MD_115200,
-		     GSBIn_UART_APPS_NS(id), GSBIn_UART_APPS_MD(id));
+	char gsbi_uart_clk_id[64];
+	char gsbi_p_clk_id[64];
 
-	/* Enable gsbi_pclk */
-	writel(GSBI_HCLK_CTL_CLK_ENA << GSBI_HCLK_CTL_S, GSBIn_HCLK_CTL(id));
+	snprintf(gsbi_uart_clk_id, 64,"gsbi%u_uart_clk", id);
+	clk_get_set_enable(gsbi_uart_clk_id, 1843200, 1);
+
+	snprintf(gsbi_p_clk_id, 64,"gsbi%u_pclk", id);
+	clk_get_set_enable(gsbi_p_clk_id, 0, 1);
 }
 
 /* Configure i2c clock */
 void clock_config_i2c(uint8_t id, uint32_t freq)
 {
-	uint32_t ns;
-	uint32_t md;
+	char gsbi_qup_clk_id[64];
+	char gsbi_p_clk_id[64];
 
-	switch (freq) {
-	case 24000000:
-		ns = I2C_CLK_NS_24MHz;
-		md = I2C_CLK_MD_24MHz;
-		break;
-	default:
-		ASSERT(0);
-	}
+	snprintf(gsbi_qup_clk_id, 64,"gsbi%u_qup_clk", id);
+	clk_get_set_enable(gsbi_qup_clk_id, 24000000, 1);
 
-	clock_config(ns, md, GSBIn_QUP_APPS_NS(id), GSBIn_QUP_APPS_MD(id));
-
-	/* Enable the GSBI HCLK */
-	writel(GSBI_HCLK_CTL_CLK_ENA << GSBI_HCLK_CTL_S, GSBIn_HCLK_CTL(id));
-}
-
-void pll1_enable(void)
-{
-	uint32_t val = 0;
-
-	/* Reset MND divider */
-	val |= (1 << 2);
-	writel(val, MM_PLL1_MODE_REG);
-
-	/* Use PLL -- Disable Bypass */
-	val |= (1 << 1);
-	writel(val, MM_PLL1_MODE_REG);
-
-	/* Activate PLL out control */
-	val |= 1;
-	writel(val, MM_PLL1_MODE_REG);
-
-	while (!readl(MM_PLL1_STATUS_REG)) ;
-}
-
-void config_mdp_lut_clk(void)
-{
-	/* Force on */
-	writel(MDP_LUT_VAL, MDP_LUT_CC_REG);
+	snprintf(gsbi_p_clk_id, 64,"gsbi%u_pclk", id);
+	clk_get_set_enable(gsbi_p_clk_id, 0, 1);
 }
 
 /* Turn on MDP related clocks and pll's for MDP */
 void mdp_clock_init(void)
 {
-	/* Turn on the PLL1, as source for  MDP clock */
-	pll1_enable();
-
-	/* Turn on MDP clk */
-	config_mmss_clk(MDP_NS_VAL, MDP_MD_VAL,
-			MDP_CC_VAL, MDP_NS_REG, MDP_MD_REG, MDP_CC_REG);
+	/* Set MDP clock to 200MHz */
+	clk_get_set_enable("mdp_clk", 200000000, 1);
 
 	/* Seems to lose pixels without this from status 0x051E0048 */
-	config_mdp_lut_clk();
+	clk_get_set_enable("lut_mdp", 0, 1);
 }
 
 /* Initialize all clocks needed by Display */
 void mmss_clock_init(void)
 {
 	/* Configure Pixel clock */
-	config_mmss_clk(PIXEL_NS_VAL, PIXEL_MD_VAL, PIXEL_CC_VAL, PIXEL_NS_REG,
-			PIXEL_MD_REG, PIXEL_CC_REG);
+	config_mmss_clk(PIXEL_NS_VAL, PIXEL_MD_VAL, PIXEL_CC_VAL, DSI_PIXEL_NS_REG,
+			DSI_PIXEL_MD_REG, DSI_PIXEL_CC_REG);
 
 	/* Configure DSI clock */
 	config_mmss_clk(DSI_NS_VAL, DSI_MD_VAL, DSI_CC_VAL, DSI_NS_REG,
 			DSI_MD_REG, DSI_CC_REG);
 
 	/* Configure Byte clock */
-	config_mmss_clk(BYTE_NS_VAL, 0x0, BYTE_CC_VAL, BYTE_NS_REG, 0x0,
-			BYTE_CC_REG);
+	config_mmss_clk(BYTE_NS_VAL, 0x0, BYTE_CC_VAL, DSI1_BYTE_NS_REG, 0x0,
+			DSI1_BYTE_CC_REG);
 
 	/* Configure ESC clock */
-	config_mmss_clk(ESC_NS_VAL, 0x0, ESC_CC_VAL, ESC_NS_REG, 0x0,
-			ESC_CC_REG);
+	config_mmss_clk(ESC_NS_VAL, 0x0, ESC_CC_VAL, DSI1_ESC_NS_REG, 0x0,
+			DSI1_ESC_CC_REG);
 }
 
 /* Intialize MMC clock */
@@ -230,24 +176,27 @@
 /* Configure MMC clock */
 void clock_config_mmc(uint32_t interface, uint32_t freq)
 {
+	char sdc_clk[64];
+	unsigned rate;
 	uint32_t reg = 0;
 
-	switch (freq) {
+	snprintf(sdc_clk, 64, "sdc%u_clk", interface);
+
+	switch(freq)
+	{
 	case MMC_CLK_400KHZ:
-		clock_config(SDC_CLK_NS_400KHZ,
-			     SDC_CLK_MD_400KHZ,
-			     SDC_NS(interface), SDC_MD(interface));
+		rate = 400000;
 		break;
 	case MMC_CLK_48MHZ:
-	case MMC_CLK_50MHZ:	/* Max supported is 48MHZ */
-		clock_config(SDC_CLK_NS_48MHZ,
-			     SDC_CLK_MD_48MHZ,
-			     SDC_NS(interface), SDC_MD(interface));
+	case MMC_CLK_50MHZ: /* Max supported is 48MHZ */
+		rate = 48000000;
 		break;
 	default:
 		ASSERT(0);
 
-	}
+	};
+
+	clk_get_set_enable(sdc_clk, rate, 1);
 
 	reg |= MMC_BOOT_MCI_CLK_ENABLE;
 	reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
@@ -258,20 +207,20 @@
 /* Configure crypto engine clock */
 void ce_clock_init(void)
 {
-	/* Enable HCLK for CE1 */
-	writel((1 << 4), CE1_HCLK_CTL);
-	/* Enable core clk for CE1 */
-	writel((1 << 4), CE1_CORE_CLK_CTL);
-	return;
+	/* Enable HCLK for CE */
+	clk_get_set_enable("ce_pclk", 0, 1);
+
+	/* Enable core clk for CE */
+	clk_get_set_enable("ce_clk", 0, 1);
 }
 
 /* Async Reset CE1 */
 void ce_async_reset()
 {
 	/* Enable Async reset bit for HCLK CE1 */
-	writel((1<<7) | (1 << 4), CE1_HCLK_CTL);
+	writel((1<<7) | (1 << 4), CE1_HCLK_CTL_REG);
 	/* Enable Async reset bit for core clk for CE1 */
-	writel((1<<7) | (1 << 4), CE1_CORE_CLK_CTL);
+	writel((1<<7) | (1 << 4), CE1_CORE_CLK_CTL_REG);
 
 	/* Add a small delay between switching the
 	 * async intput from high to low
@@ -279,9 +228,9 @@
 	 udelay(2);
 
 	/* Disable Async reset bit for HCLK for CE1 */
-	writel((1 << 4), CE1_HCLK_CTL);
+	writel((1 << 4), CE1_HCLK_CTL_REG);
 	/* Disable Async reset bit for core clk for CE1 */
-	writel((1 << 4), CE1_CORE_CLK_CTL);
+	writel((1 << 4), CE1_CORE_CLK_CTL_REG);
 
 	return;
 }
diff --git a/platform/msm8960/clock.c b/platform/msm8960/clock.c
new file mode 100644
index 0000000..30aa6b7
--- /dev/null
+++ b/platform/msm8960/clock.c
@@ -0,0 +1,980 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Code Aurora nor
+ *     the names of its contributors may be used to endorse or promote
+ *     products derived from this software without specific prior written
+ *     permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <debug.h>
+#include <reg.h>
+#include <err.h>
+#include <limits.h>
+#include <clock.h>
+#include <clock-local.h>
+#include <bits.h>
+#include <platform/iomap.h>
+#include <platform/clock.h>
+#include <platform/timer.h>
+#include <sys/types.h>
+
+extern void dmb(void);
+
+static int xo_clk_enable(struct clk *clk)
+{
+	/* Assuming pxo already running */
+	return 0;
+}
+
+static void xo_clk_disable(struct clk *clk)
+{
+	/* Do nothing */
+}
+
+static struct clk_ops clk_ops_xo = {
+	.enable = xo_clk_enable,
+	.disable = xo_clk_disable,
+	.get_rate = fixed_clk_get_rate,
+};
+
+static struct fixed_clk pxo_clk = {
+	.rate = 27000000,
+	.c = {
+		.dbg_name = "pxo_clk",
+		.ops = &clk_ops_xo,
+	},
+};
+
+static struct fixed_clk cxo_clk = {
+	.rate = 19200000,
+	.c = {
+		.dbg_name = "cxo_clk",
+		.ops = &clk_ops_xo,
+	},
+};
+
+/*
+ * PLL Clocks
+ */
+static struct pll_clk pll2_clk = {
+	.rate = 800000000,
+	.mode_reg = (void *)MM_PLL1_MODE_REG,
+	.parent = &pxo_clk.c,
+	.c = {
+		.dbg_name = "pll2_clk",
+		.ops = &clk_ops_pll,
+	},
+};
+
+static struct pll_clk pll3_clk = {
+	.rate = 1200000000,
+	.mode_reg = (void *)BB_PLL3_MODE_REG,
+	.parent = &pxo_clk.c,
+	.c = {
+		.dbg_name = "pll3_clk",
+		.ops = &clk_ops_pll,
+	},
+};
+
+static struct pll_vote_clk pll8_clk = {
+	.rate = 384000000,
+	.en_reg = (void *)BB_PLL_ENA_SC0_REG,
+	.en_mask = BIT(8),
+	.status_reg = (void *)BB_PLL8_STATUS_REG,
+	.parent = &pxo_clk.c,
+	.c = {
+		.dbg_name = "pll8_clk",
+		.ops = &clk_ops_pll_vote,
+	},
+};
+
+static struct clk_ops soc_clk_ops_8960 = {
+	.enable = local_clk_enable,
+	.disable = local_clk_disable,
+	.set_rate = local_clk_set_rate,
+	.get_rate = local_clk_get_rate,
+	.is_enabled = local_clk_is_enabled,
+	.round_rate = local_clk_round_rate,
+	.get_parent = local_clk_get_parent,
+};
+
+static struct clk_ops clk_ops_branch = {
+	.enable = branch_clk_enable,
+	.disable = branch_clk_disable,
+	.is_enabled = branch_clk_is_enabled,
+	.get_parent = branch_clk_get_parent,
+	.set_parent = branch_clk_set_parent,
+};
+
+/*
+ * Peripheral Clocks
+ */
+#define CLK_GSBI_UART(i, n, h_r, h_b) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = (void *)GSBIn_UART_APPS_NS_REG(n), \
+			.en_mask = BIT(9), \
+			.reset_reg = (void *)GSBIn_RESET_REG(n), \
+			.reset_mask = BIT(0), \
+			.halt_reg = (void *)h_r, \
+			.halt_bit = h_b, \
+		}, \
+		.ns_reg = (void *)GSBIn_UART_APPS_NS_REG(n), \
+		.md_reg = (void *)GSBIn_UART_APPS_MD_REG(n), \
+		.root_en_mask = BIT(11), \
+		.ns_mask = (BM(31, 16) | BM(6, 0)), \
+		.set_rate = set_rate_mnd, \
+		.freq_tbl = clk_tbl_gsbi_uart, \
+		.current_freq = &local_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &soc_clk_ops_8960, \
+		}, \
+	}
+#define F_GSBI_UART(f, s, d, m, n) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.md_val = MD16(m, n), \
+		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
+		.mnd_en_mask = BIT(8) * !!(n), \
+	}
+static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
+	F_GSBI_UART( 1843200, pll8, 1,  3, 625),
+	F_GSBI_UART( 3686400, pll8, 1,  6, 625),
+	F_GSBI_UART( 7372800, pll8, 1, 12, 625),
+	F_GSBI_UART(14745600, pll8, 1, 24, 625),
+	F_GSBI_UART(16000000, pll8, 4,  1,   6),
+	F_GSBI_UART(24000000, pll8, 4,  1,   4),
+	F_GSBI_UART(32000000, pll8, 4,  1,   3),
+	F_GSBI_UART(40000000, pll8, 1,  5,  48),
+	F_GSBI_UART(46400000, pll8, 1, 29, 240),
+	F_GSBI_UART(48000000, pll8, 4,  1,   2),
+	F_GSBI_UART(51200000, pll8, 1,  2,  15),
+	F_GSBI_UART(56000000, pll8, 1,  7,  48),
+	F_GSBI_UART(58982400, pll8, 1, 96, 625),
+	F_GSBI_UART(64000000, pll8, 2,  1,   3),
+	F_END
+};
+
+static CLK_GSBI_UART(gsbi1_uart,   1, CLK_HALT_CFPB_STATEA_REG, 10);
+static CLK_GSBI_UART(gsbi2_uart,   2, CLK_HALT_CFPB_STATEA_REG,  6);
+static CLK_GSBI_UART(gsbi3_uart,   3, CLK_HALT_CFPB_STATEA_REG,  2);
+static CLK_GSBI_UART(gsbi4_uart,   4, CLK_HALT_CFPB_STATEB_REG, 26);
+static CLK_GSBI_UART(gsbi5_uart,   5, CLK_HALT_CFPB_STATEB_REG, 22);
+static CLK_GSBI_UART(gsbi6_uart,   6, CLK_HALT_CFPB_STATEB_REG, 18);
+static CLK_GSBI_UART(gsbi7_uart,   7, CLK_HALT_CFPB_STATEB_REG, 14);
+static CLK_GSBI_UART(gsbi8_uart,   8, CLK_HALT_CFPB_STATEB_REG, 10);
+static CLK_GSBI_UART(gsbi9_uart,   9, CLK_HALT_CFPB_STATEB_REG,  6);
+static CLK_GSBI_UART(gsbi10_uart, 10, CLK_HALT_CFPB_STATEB_REG,  2);
+static CLK_GSBI_UART(gsbi11_uart, 11, CLK_HALT_CFPB_STATEC_REG, 17);
+static CLK_GSBI_UART(gsbi12_uart, 12, CLK_HALT_CFPB_STATEC_REG, 13);
+
+#define CLK_GSBI_QUP(i, n, h_r, h_b) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = (void *)GSBIn_QUP_APPS_NS_REG(n), \
+			.en_mask = BIT(9), \
+			.reset_reg = (void *)GSBIn_RESET_REG(n), \
+			.reset_mask = BIT(0), \
+			.halt_reg = (void *)h_r, \
+			.halt_bit = h_b, \
+		}, \
+		.ns_reg = (void *)GSBIn_QUP_APPS_NS_REG(n), \
+		.md_reg = (void *)GSBIn_QUP_APPS_MD_REG(n), \
+		.root_en_mask = BIT(11), \
+		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.set_rate = set_rate_mnd, \
+		.freq_tbl = clk_tbl_gsbi_qup, \
+		.current_freq = &local_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &soc_clk_ops_8960, \
+		}, \
+	}
+#define F_GSBI_QUP(f, s, d, m, n) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.md_val = MD8(16, m, 0, n), \
+		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
+		.mnd_en_mask = BIT(8) * !!(n), \
+	}
+static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
+	F_GSBI_QUP( 1100000, pxo,  1, 2, 49),
+	F_GSBI_QUP( 5400000, pxo,  1, 1,  5),
+	F_GSBI_QUP(10800000, pxo,  1, 2,  5),
+	F_GSBI_QUP(15060000, pll8, 1, 2, 51),
+	F_GSBI_QUP(24000000, pll8, 4, 1,  4),
+	F_GSBI_QUP(25600000, pll8, 1, 1, 15),
+	F_GSBI_QUP(27000000, pxo,  1, 0,  0),
+	F_GSBI_QUP(48000000, pll8, 4, 1,  2),
+	F_GSBI_QUP(51200000, pll8, 1, 2, 15),
+	F_END
+};
+
+static CLK_GSBI_QUP(gsbi1_qup,   1, CLK_HALT_CFPB_STATEA_REG,  9);
+static CLK_GSBI_QUP(gsbi2_qup,   2, CLK_HALT_CFPB_STATEA_REG,  4);
+static CLK_GSBI_QUP(gsbi3_qup,   3, CLK_HALT_CFPB_STATEA_REG,  0);
+static CLK_GSBI_QUP(gsbi4_qup,   4, CLK_HALT_CFPB_STATEB_REG, 24);
+static CLK_GSBI_QUP(gsbi5_qup,   5, CLK_HALT_CFPB_STATEB_REG, 20);
+static CLK_GSBI_QUP(gsbi6_qup,   6, CLK_HALT_CFPB_STATEB_REG, 16);
+static CLK_GSBI_QUP(gsbi7_qup,   7, CLK_HALT_CFPB_STATEB_REG, 12);
+static CLK_GSBI_QUP(gsbi8_qup,   8, CLK_HALT_CFPB_STATEB_REG,  8);
+static CLK_GSBI_QUP(gsbi9_qup,   9, CLK_HALT_CFPB_STATEB_REG,  4);
+static CLK_GSBI_QUP(gsbi10_qup, 10, CLK_HALT_CFPB_STATEB_REG,  0);
+static CLK_GSBI_QUP(gsbi11_qup, 11, CLK_HALT_CFPB_STATEC_REG, 15);
+static CLK_GSBI_QUP(gsbi12_qup, 12, CLK_HALT_CFPB_STATEC_REG, 11);
+
+#define F_USB(f, s, d, m, n) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.md_val = MD8(16, m, 0, n), \
+		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
+		.mnd_en_mask = BIT(8) * !!(n), \
+	}
+static struct clk_freq_tbl clk_tbl_usb[] = {
+	F_USB(60000000, pll8, 1, 5, 32),
+	F_END
+};
+
+static struct rcg_clk usb_hs1_xcvr_clk = {
+	.b = {
+		.ctl_reg = (void *)USB_HS1_XCVR_FS_CLK_NS_REG,
+		.en_mask = BIT(9),
+		.reset_reg = (void *)USB_HS1_RESET_REG,
+		.reset_mask = BIT(0),
+		.halt_reg = (void *)CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 0,
+	},
+	.ns_reg = (void *)USB_HS1_XCVR_FS_CLK_NS_REG,
+	.md_reg = (void *)USB_HS1_XCVR_FS_CLK_MD_REG,
+	.root_en_mask = BIT(11),
+	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.set_rate = set_rate_mnd,
+	.freq_tbl = clk_tbl_usb,
+	.current_freq = &local_dummy_freq,
+	.c = {
+		.dbg_name = "usb_hs1_xcvr_clk",
+		.ops = &soc_clk_ops_8960,
+	},
+};
+
+#define CLK_SDC(i, n, h_r, h_c, h_b) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = (void *)SDCn_APPS_CLK_NS_REG(n), \
+			.en_mask = BIT(9), \
+			.reset_reg = (void *)SDCn_RESET_REG(n), \
+			.reset_mask = BIT(0), \
+			.halt_reg = (void *)h_r, \
+			.halt_check = h_c, \
+			.halt_bit = h_b, \
+		}, \
+		.ns_reg = (void *)SDCn_APPS_CLK_NS_REG(n), \
+		.md_reg = (void *)SDCn_APPS_CLK_MD_REG(n), \
+		.root_en_mask = BIT(11), \
+		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.set_rate = set_rate_mnd, \
+		.freq_tbl = clk_tbl_sdc, \
+		.current_freq = &local_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &soc_clk_ops_8960, \
+		}, \
+	}
+#define F_SDC(f, s, d, m, n) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.md_val = MD8(16, m, 0, n), \
+		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
+		.mnd_en_mask = BIT(8) * !!(n), \
+	}
+static struct clk_freq_tbl clk_tbl_sdc[] = {
+	F_SDC(   144000, pxo,   3, 2, 125),
+	F_SDC(   400000, pll8,  4, 1, 240),
+	F_SDC( 16000000, pll8,  4, 1,   6),
+	F_SDC( 17070000, pll8,  1, 2,  45),
+	F_SDC( 20210000, pll8,  1, 1,  19),
+	F_SDC( 24000000, pll8,  4, 1,   4),
+	F_SDC( 48000000, pll8,  4, 1,   2),
+	F_SDC( 64000000, pll8,  3, 1,   2),
+	F_SDC( 96000000, pll8,  4, 0,   0),
+	F_SDC(192000000, pll8,  2, 0,   0),
+	F_END
+};
+
+static CLK_SDC(sdc1, 1, CLK_HALT_DFAB_STATE_REG, HALT, 6);
+static CLK_SDC(sdc2, 2, CLK_HALT_DFAB_STATE_REG, HALT, 5);
+static CLK_SDC(sdc3, 3, CLK_HALT_DFAB_STATE_REG, HALT, 4);
+static CLK_SDC(sdc4, 4, CLK_HALT_DFAB_STATE_REG, HALT, 3);
+static CLK_SDC(sdc5, 5, CLK_HALT_DFAB_STATE_REG, HALT, 2);
+
+static struct branch_clk ce1_core_clk = {
+	.b = {
+		.ctl_reg = (void *)CE1_CORE_CLK_CTL_REG,
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEC_REG,
+		.halt_bit = 27,
+	},
+	.c = {
+		.dbg_name = "ce1_core_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+static struct branch_clk ce1_p_clk = {
+	.b = {
+		.ctl_reg = (void *)CE1_HCLK_CTL_REG,
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEC_REG,
+		.halt_bit = 1,
+	},
+	.c = {
+		.dbg_name = "ce1_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+#define F_CE(f, s, d) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.ns_val = NS_DIVSRC(6, 3, d, 2, 0, s##_to_bb_mux), \
+	}
+static struct clk_freq_tbl clk_tbl_ce3[] = {
+	F_CE( 48000000, pll8,  8),
+	F_CE(100000000, pll3, 12),
+	F_END
+};
+
+static struct rcg_clk ce3_src_clk = {
+	.b = {
+		.ctl_reg = (void *)CE3_CLK_SRC_NS_REG,
+		.en_mask = 0,
+		.halt_check = NOCHECK,
+	},
+	.ns_reg = (void *)CE3_CLK_SRC_NS_REG,
+	.root_en_mask = BIT(7),
+	.ns_mask = BM(6, 0),
+	.set_rate = set_rate_nop,
+	.freq_tbl = clk_tbl_ce3,
+	.current_freq = &local_dummy_freq,
+	.c = {
+		.dbg_name = "ce3_src_clk",
+		.ops = &soc_clk_ops_8960,
+	},
+};
+
+static struct branch_clk ce3_core_clk = {
+	.b = {
+		.ctl_reg = (void *)CE3_CORE_CLK_CTL_REG,
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_GSS_KPSS_MISC_STATE_REG,
+		.halt_bit = 5,
+	},
+	.parent = &ce3_src_clk.c,
+	.c = {
+		.dbg_name = "ce3_core_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk ce3_p_clk = {
+	.b = {
+		.ctl_reg = (void *)CE3_HCLK_CTL_REG,
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_AFAB_SFAB_STATEB_REG,
+		.halt_bit = 16,
+	},
+	.parent = &ce3_src_clk.c,
+	.c = {
+		.dbg_name = "ce3_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi1_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(1),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEA_REG,
+		.halt_bit = 11,
+	},
+	.c = {
+		.dbg_name = "gsbi1_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi2_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(2),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEA_REG,
+		.halt_bit = 7,
+	},
+	.c = {
+		.dbg_name = "gsbi2_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi3_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(3),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEA_REG,
+		.halt_bit = 3,
+	},
+	.c = {
+		.dbg_name = "gsbi3_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi4_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(4),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEB_REG,
+		.halt_bit = 27,
+	},
+	.c = {
+		.dbg_name = "gsbi4_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi5_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(5),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEB_REG,
+		.halt_bit = 23,
+	},
+	.c = {
+		.dbg_name = "gsbi5_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi6_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(6),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEB_REG,
+		.halt_bit = 19,
+	},
+	.c = {
+		.dbg_name = "gsbi6_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi7_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(7),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEB_REG,
+		.halt_bit = 15,
+	},
+	.c = {
+		.dbg_name = "gsbi7_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi8_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(8),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEB_REG,
+		.halt_bit = 11,
+	},
+	.c = {
+		.dbg_name = "gsbi8_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi9_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(9),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEB_REG,
+		.halt_bit = 7,
+	},
+	.c = {
+		.dbg_name = "gsbi9_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi10_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(10),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEB_REG,
+		.halt_bit = 3,
+	},
+	.c = {
+		.dbg_name = "gsbi10_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi11_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(11),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEC_REG,
+		.halt_bit = 18,
+	},
+	.c = {
+		.dbg_name = "gsbi11_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gsbi12_p_clk = {
+	.b = {
+		.ctl_reg = (void *)GSBIn_HCLK_CTL_REG(12),
+		.en_mask = BIT(4),
+		.halt_reg = (void *)CLK_HALT_CFPB_STATEC_REG,
+		.halt_bit = 14,
+	},
+	.c = {
+		.dbg_name = "gsbi12_p_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk mdp_axi_clk = {
+	.b = {
+		.ctl_reg = (void *)MAXI_EN_REG,
+		.en_mask = BIT(23),
+		.reset_reg = (void *)SW_RESET_AXI_REG,
+		.reset_mask = BIT(13),
+		.halt_reg = (void *)DBG_BUS_VEC_E_REG,
+		.halt_bit = 8,
+	},
+	.c = {
+		.dbg_name = "mdp_axi_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+#define F_MDP(f, s, m, n) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.md_val = MD8(8, m, 0, n), \
+		.ns_val = NS_MND_BANKED8(22, 14, n, m, 3, 0, s##_to_mm_mux), \
+		.ctl_val = CC_BANKED(9, 6, n), \
+		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
+	}
+static struct clk_freq_tbl clk_tbl_mdp[] = {
+	F_MDP(  9600000, pll8, 1, 40),
+	F_MDP( 13710000, pll8, 1, 28),
+	F_MDP( 27000000, pxo,  0,  0),
+	F_MDP( 29540000, pll8, 1, 13),
+	F_MDP( 34910000, pll8, 1, 11),
+	F_MDP( 38400000, pll8, 1, 10),
+	F_MDP( 59080000, pll8, 2, 13),
+	F_MDP( 76800000, pll8, 1,  5),
+	F_MDP( 85330000, pll8, 2,  9),
+	F_MDP( 96000000, pll8, 1,  4),
+	F_MDP(128000000, pll8, 1,  3),
+	F_MDP(160000000, pll2, 1,  5),
+	F_MDP(177780000, pll2, 2,  9),
+	F_MDP(200000000, pll2, 1,  4),
+	F_END
+};
+
+static struct bank_masks bmnd_info_mdp = {
+	.bank_sel_mask =		BIT(11),
+	.bank0_mask = {
+			.md_reg =		(void *)MDP_MD0_REG,
+			.ns_mask =		BM(29, 22) | BM(5, 3),
+			.rst_mask =		BIT(31),
+			.mnd_en_mask =		BIT(8),
+			.mode_mask =		BM(10, 9),
+	},
+	.bank1_mask = {
+			.md_reg =		(void *)MDP_MD1_REG,
+			.ns_mask =		BM(21, 14) | BM(2, 0),
+			.rst_mask =		BIT(30),
+			.mnd_en_mask =		BIT(5),
+			.mode_mask =		BM(7, 6),
+	},
+};
+
+static struct rcg_clk mdp_clk = {
+	.b = {
+		.ctl_reg = (void *)MDP_CC_REG,
+		.en_mask = BIT(0),
+		.reset_reg = (void *)SW_RESET_CORE_REG,
+		.reset_mask = BIT(21),
+		.halt_reg = (void *)DBG_BUS_VEC_C_REG,
+		.halt_bit = 10,
+	},
+	.ns_reg = (void *)MDP_NS_REG,
+	.root_en_mask = BIT(2),
+	.set_rate = set_rate_mnd_banked,
+	.freq_tbl = clk_tbl_mdp,
+	.bank_masks = &bmnd_info_mdp,
+	.depends = &mdp_axi_clk.c,
+	.current_freq = &local_dummy_freq,
+	.c = {
+		.dbg_name = "mdp_clk",
+		.ops = &soc_clk_ops_8960,
+	},
+};
+
+static struct branch_clk lut_mdp_clk = {
+	.b = {
+		.ctl_reg = (void *)MDP_LUT_CC_REG,
+		.en_mask = BIT(0),
+		.halt_reg = (void *)DBG_BUS_VEC_I_REG,
+		.halt_bit = 13,
+	},
+	.parent = &mdp_clk.c,
+	.c = {
+		.dbg_name = "lut_mdp_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+#ifdef DEBUG_CLOCK
+struct measure_sel {
+	uint32_t test_vector;
+	struct clk *clk;
+};
+
+static struct measure_sel measure_mux[] = {
+	{ TEST_PER_LS(0x13), &sdc1_clk.c },
+	{ TEST_PER_LS(0x15), &sdc2_clk.c },
+	{ TEST_PER_LS(0x17), &sdc3_clk.c },
+	{ TEST_PER_LS(0x19), &sdc4_clk.c },
+	{ TEST_PER_LS(0x1B), &sdc5_clk.c },
+	{ TEST_PER_LS(0x3D), &gsbi1_p_clk.c },
+	{ TEST_PER_LS(0x3E), &gsbi1_uart_clk.c },
+	{ TEST_PER_LS(0x3F), &gsbi1_qup_clk.c },
+	{ TEST_PER_LS(0x41), &gsbi2_p_clk.c },
+	{ TEST_PER_LS(0x42), &gsbi2_uart_clk.c },
+	{ TEST_PER_LS(0x44), &gsbi2_qup_clk.c },
+	{ TEST_PER_LS(0x45), &gsbi3_p_clk.c },
+	{ TEST_PER_LS(0x46), &gsbi3_uart_clk.c },
+	{ TEST_PER_LS(0x48), &gsbi3_qup_clk.c },
+	{ TEST_PER_LS(0x49), &gsbi4_p_clk.c },
+	{ TEST_PER_LS(0x4A), &gsbi4_uart_clk.c },
+	{ TEST_PER_LS(0x4C), &gsbi4_qup_clk.c },
+	{ TEST_PER_LS(0x4D), &gsbi5_p_clk.c },
+	{ TEST_PER_LS(0x4E), &gsbi5_uart_clk.c },
+	{ TEST_PER_LS(0x50), &gsbi5_qup_clk.c },
+	{ TEST_PER_LS(0x51), &gsbi6_p_clk.c },
+	{ TEST_PER_LS(0x52), &gsbi6_uart_clk.c },
+	{ TEST_PER_LS(0x54), &gsbi6_qup_clk.c },
+	{ TEST_PER_LS(0x55), &gsbi7_p_clk.c },
+	{ TEST_PER_LS(0x56), &gsbi7_uart_clk.c },
+	{ TEST_PER_LS(0x58), &gsbi7_qup_clk.c },
+	{ TEST_PER_LS(0x59), &gsbi8_p_clk.c },
+	{ TEST_PER_LS(0x5A), &gsbi8_uart_clk.c },
+	{ TEST_PER_LS(0x5C), &gsbi8_qup_clk.c },
+	{ TEST_PER_LS(0x5D), &gsbi9_p_clk.c },
+	{ TEST_PER_LS(0x5E), &gsbi9_uart_clk.c },
+	{ TEST_PER_LS(0x60), &gsbi9_qup_clk.c },
+	{ TEST_PER_LS(0x61), &gsbi10_p_clk.c },
+	{ TEST_PER_LS(0x62), &gsbi10_uart_clk.c },
+	{ TEST_PER_LS(0x64), &gsbi10_qup_clk.c },
+	{ TEST_PER_LS(0x65), &gsbi11_p_clk.c },
+	{ TEST_PER_LS(0x66), &gsbi11_uart_clk.c },
+	{ TEST_PER_LS(0x68), &gsbi11_qup_clk.c },
+	{ TEST_PER_LS(0x69), &gsbi12_p_clk.c },
+	{ TEST_PER_LS(0x6A), &gsbi12_uart_clk.c },
+	{ TEST_PER_LS(0x6C), &gsbi12_qup_clk.c },
+	{ TEST_PER_LS(0x85), &usb_hs1_xcvr_clk.c },
+	{ TEST_PER_LS(0x92), &ce1_p_clk.c },
+	{ TEST_PER_LS(0xA4), &ce1_core_clk.c },
+	{ TEST_PER_LS(0x5F), &ce3_p_clk.c },
+	{ TEST_PER_LS(0x60), &ce3_core_clk.c },
+
+	{ TEST_MM_HS(0x15), &mdp_axi_clk.c },
+	{ TEST_MM_HS(0x1A), &mdp_clk.c },
+	{ TEST_MM_HS(0x28), &lut_mdp_clk.c },
+};
+
+static struct measure_sel *find_measure_sel(struct clk *clk)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(measure_mux); i++)
+		if (measure_mux[i].clk == clk)
+			return &measure_mux[i];
+	return NULL;
+}
+
+static int measure_clk_set_parent(struct clk *c, struct clk *parent)
+{
+	int ret = 0;
+	uint32_t clk_sel;
+	struct measure_sel *p;
+	struct measure_clk *clk = to_measure_clk(c);
+
+	if (!parent)
+		return ERR_INVALID_ARGS;
+
+	p = find_measure_sel(parent);
+	if (!p)
+		return ERR_INVALID_ARGS;
+
+	/*
+	 * Program the test vector, measurement period (sample_ticks)
+	 * and scaling multiplier.
+	 */
+	clk->sample_ticks = 0x10000;
+	clk_sel = p->test_vector & TEST_CLK_SEL_MASK;
+	clk->multiplier = 1;
+	switch (p->test_vector >> TEST_TYPE_SHIFT) {
+	case TEST_TYPE_PER_LS:
+		writel_relaxed(0x4030D00|BVAL(7, 0, clk_sel), CLK_TEST_REG);
+		break;
+	case TEST_TYPE_PER_HS:
+		writel_relaxed(0x4020000|BVAL(16, 10, clk_sel), CLK_TEST_REG);
+		break;
+	case TEST_TYPE_MM_LS:
+		writel_relaxed(0x4030D97, CLK_TEST_REG);
+		writel_relaxed(BVAL(6, 1, clk_sel)|BIT(0), DBG_CFG_REG_LS_REG);
+		break;
+	case TEST_TYPE_MM_HS:
+		writel_relaxed(0x402B800, CLK_TEST_REG);
+		writel_relaxed(BVAL(6, 1, clk_sel)|BIT(0), DBG_CFG_REG_HS_REG);
+		break;
+	default:
+		ret = ERR_NOT_SUPPORTED;
+	}
+	/* Make sure test vector is set before starting measurements. */
+	dmb();
+
+	return ret;
+}
+
+/* Sample clock for 'ticks' reference clock ticks. */
+static uint32_t run_measurement(unsigned ticks)
+{
+	/* Stop counters and set the XO4 counter start value. */
+	writel_relaxed(ticks, RINGOSC_TCXO_CTL_REG);
+
+	/* Wait for timer to become ready. */
+	while ((readl_relaxed(RINGOSC_STATUS_REG) & BIT(25)) != 0)
+		dmb();
+
+	/* Run measurement and wait for completion. */
+	writel_relaxed(BIT(20)|ticks, RINGOSC_TCXO_CTL_REG);
+	while ((readl_relaxed(RINGOSC_STATUS_REG) & BIT(25)) == 0)
+		dmb();
+
+	/* Stop counters. */
+	writel_relaxed(0x0, RINGOSC_TCXO_CTL_REG);
+
+	/* Return measured ticks. */
+	return readl_relaxed(RINGOSC_STATUS_REG) & BM(24, 0);
+}
+
+
+/* Perform a hardware rate measurement for a given clock.
+   FOR DEBUG USE ONLY: Measurements take ~15 ms! */
+static unsigned long measure_clk_get_rate(struct clk *c)
+{
+	uint32_t pdm_reg_backup, ringosc_reg_backup;
+	uint64_t raw_count_short, raw_count_full;
+	struct measure_clk *clk = to_measure_clk(c);
+	unsigned ret;
+
+	ret = clk_enable(&cxo_clk.c);
+	if (ret) {
+		dprintf(CRITICAL, "CXO clock failed to enable. Can't measure\n");
+		return 0;
+	}
+
+	/* Enable CXO/4 and RINGOSC branch and root. */
+	pdm_reg_backup = readl_relaxed(PDM_CLK_NS_REG);
+	ringosc_reg_backup = readl_relaxed(RINGOSC_NS_REG);
+	writel_relaxed(0x2898, PDM_CLK_NS_REG);
+	writel_relaxed(0xA00, RINGOSC_NS_REG);
+
+	/*
+	 * The ring oscillator counter will not reset if the measured clock
+	 * is not running.  To detect this, run a short measurement before
+	 * the full measurement.  If the raw results of the two are the same
+	 * then the clock must be off.
+	 */
+
+	/* Run a short measurement. (~1 ms) */
+	raw_count_short = run_measurement(0x1000);
+	/* Run a full measurement. (~14 ms) */
+	raw_count_full = run_measurement(clk->sample_ticks);
+
+	writel_relaxed(ringosc_reg_backup, RINGOSC_NS_REG);
+	writel_relaxed(pdm_reg_backup, PDM_CLK_NS_REG);
+
+	/* Return 0 if the clock is off. */
+	if (raw_count_full == raw_count_short)
+		ret = 0;
+	else {
+		/* Compute rate in Hz. */
+		raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
+		raw_count_full /= ((clk->sample_ticks * 10) + 35);
+		ret = (raw_count_full * clk->multiplier);
+	}
+
+	/* Route dbg_hs_clk to PLLTEST.  300mV single-ended amplitude. */
+	writel_relaxed(0x38F8, PLLTEST_PAD_CFG_REG);
+
+	clk_disable(&cxo_clk.c);
+
+	return ret;
+}
+#else
+static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	return ERR_INVALID_ARGS;
+}
+
+static unsigned long measure_clk_get_rate(struct clk *clk)
+{
+	return 0;
+}
+#endif
+
+static struct clk_ops measure_clk_ops = {
+	.set_parent = measure_clk_set_parent,
+	.get_rate = measure_clk_get_rate,
+};
+
+static struct measure_clk measure_clk = {
+	.c = {
+		.dbg_name = "measure_clk",
+		.ops = &measure_clk_ops,
+	},
+	.multiplier = 1,
+};
+
+static struct clk_lookup msm_clocks_8960[] = {
+	CLK_LOOKUP("gsbi1_uart_clk",	gsbi1_uart_clk.c),
+	CLK_LOOKUP("gsbi2_uart_clk",	gsbi2_uart_clk.c),
+	CLK_LOOKUP("gsbi3_uart_clk",	gsbi3_uart_clk.c),
+	CLK_LOOKUP("gsbi4_uart_clk",	gsbi4_uart_clk.c),
+	CLK_LOOKUP("gsbi5_uart_clk",	gsbi5_uart_clk.c),
+	CLK_LOOKUP("gsbi6_uart_clk",	gsbi6_uart_clk.c),
+	CLK_LOOKUP("gsbi7_uart_clk",	gsbi7_uart_clk.c),
+	CLK_LOOKUP("gsbi8_uart_clk",	gsbi8_uart_clk.c),
+	CLK_LOOKUP("gsbi9_uart_clk",	gsbi9_uart_clk.c),
+	CLK_LOOKUP("gsbi10_uart_clk",	gsbi10_uart_clk.c),
+	CLK_LOOKUP("gsbi11_uart_clk",	gsbi11_uart_clk.c),
+	CLK_LOOKUP("gsbi12_uart_clk",	gsbi12_uart_clk.c),
+	CLK_LOOKUP("gsbi1_qup_clk",		gsbi1_qup_clk.c),
+	CLK_LOOKUP("gsbi2_qup_clk",		gsbi2_qup_clk.c),
+	CLK_LOOKUP("gsbi3_qup_clk",		gsbi3_qup_clk.c),
+	CLK_LOOKUP("gsbi4_qup_clk",		gsbi4_qup_clk.c),
+	CLK_LOOKUP("gsbi5_qup_clk",		gsbi5_qup_clk.c),
+	CLK_LOOKUP("gsbi6_qup_clk",		gsbi6_qup_clk.c),
+	CLK_LOOKUP("gsbi7_qup_clk",		gsbi7_qup_clk.c),
+	CLK_LOOKUP("gsbi8_qup_clk",		gsbi8_qup_clk.c),
+	CLK_LOOKUP("gsbi9_qup_clk",		gsbi9_qup_clk.c),
+	CLK_LOOKUP("gsbi10_qup_clk",	gsbi10_qup_clk.c),
+	CLK_LOOKUP("gsbi11_qup_clk",	gsbi11_qup_clk.c),
+	CLK_LOOKUP("gsbi12_qup_clk",	gsbi12_qup_clk.c),
+	CLK_LOOKUP("gsbi1_pclk",		gsbi1_p_clk.c),
+	CLK_LOOKUP("gsbi2_pclk",		gsbi2_p_clk.c),
+	CLK_LOOKUP("gsbi3_pclk",		gsbi3_p_clk.c),
+	CLK_LOOKUP("gsbi4_pclk",		gsbi4_p_clk.c),
+	CLK_LOOKUP("gsbi5_pclk",		gsbi5_p_clk.c),
+	CLK_LOOKUP("gsbi6_pclk",		gsbi6_p_clk.c),
+	CLK_LOOKUP("gsbi7_pclk",		gsbi7_p_clk.c),
+	CLK_LOOKUP("gsbi8_pclk",		gsbi8_p_clk.c),
+	CLK_LOOKUP("gsbi9_pclk",		gsbi9_p_clk.c),
+	CLK_LOOKUP("gsbi10_pclk",		gsbi10_p_clk.c),
+	CLK_LOOKUP("gsbi11_pclk",		gsbi11_p_clk.c),
+	CLK_LOOKUP("gsbi12_pclk",		gsbi12_p_clk.c),
+	CLK_LOOKUP("usb_hs_clk",		usb_hs1_xcvr_clk.c),
+	CLK_LOOKUP("sdc1_clk",			sdc1_clk.c),
+	CLK_LOOKUP("sdc2_clk",			sdc2_clk.c),
+	CLK_LOOKUP("sdc3_clk",			sdc3_clk.c),
+	CLK_LOOKUP("sdc4_clk",			sdc4_clk.c),
+	CLK_LOOKUP("sdc5_clk",			sdc5_clk.c),
+	CLK_LOOKUP("mdp_axi_clk",		mdp_axi_clk.c),
+	CLK_LOOKUP("mdp_clk",			mdp_clk.c),
+	CLK_LOOKUP("lut_mdp",			lut_mdp_clk.c),
+	CLK_LOOKUP("ce1_pclk",			ce1_p_clk.c),
+	CLK_LOOKUP("ce1_clk",			ce1_core_clk.c),
+	CLK_LOOKUP("ce3_src_clk",		ce3_src_clk.c),
+	CLK_LOOKUP("ce3_pclk",			ce3_p_clk.c),
+	CLK_LOOKUP("ce3_clk",			ce3_core_clk.c),
+	CLK_LOOKUP("measure",			measure_clk.c),
+
+};
+
+static int sr_pll_clk_enable(struct clk *clk)
+{
+	uint32_t mode;
+	struct pll_clk *pll = to_pll_clk(clk);
+
+	mode = readl_relaxed(pll->mode_reg);
+	/* De-assert active-low PLL reset. */
+	mode |= BIT(2);
+	writel_relaxed(mode, pll->mode_reg);
+
+	/*
+	 * H/W requires a 5us delay between disabling the bypass and
+	 * de-asserting the reset. Delay 10us just to be safe.
+	 */
+	dmb();
+	udelay(10);
+
+	/* Disable PLL bypass mode. */
+	mode |= BIT(1);
+	writel_relaxed(mode, pll->mode_reg);
+
+	/* Wait until PLL is locked. */
+	dmb();
+	udelay(60);
+
+	/* Enable PLL output. */
+	mode |= BIT(0);
+	writel_relaxed(mode, pll->mode_reg);
+
+	return 0;
+}
+
+static unsigned msm_num_clocks_8960 = ARRAY_SIZE(msm_clocks_8960);
+
+void msm_clocks_init()
+{
+	clk_ops_pll.enable = sr_pll_clk_enable;
+	clk_init(msm_clocks_8960, msm_num_clocks_8960);
+}
+
diff --git a/platform/msm8960/include/platform/clock.h b/platform/msm8960/include/platform/clock.h
index c723294..2984484 100644
--- a/platform/msm8960/include/platform/clock.h
+++ b/platform/msm8960/include/platform/clock.h
@@ -1,5 +1,5 @@
 /*
- * * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -29,57 +29,279 @@
 #ifndef __PLATFORM_MSM8960_CLOCK_H
 #define __PLATFORM_MSM8960_CLOCK_H
 
-/* GSBI/I2C QUP APPS CLK definitions */
-#define I2C_CLK_MD_24MHz       0x000100FB
-#define I2C_CLK_NS_24MHz       0x00FC005B
-
-/* NS/MD value for USB XCVR */
-#define USB_XCVR_CLK_NS        0x00E400C3
-#define USB_XCVR_CLK_MD        0x000500DF
-
-/* NS/MD value for UART */
-#define UART_DM_CLK_NS_115200  0xFFE40040
-#define UART_DM_CLK_MD_115200  0x0002FFE2
-
 #define UART_DM_CLK_RX_TX_BIT_RATE 0xFF
 
-/* NS/MD value for MMC */
-#define SDC_CLK_NS_400KHZ    0x00440040
-#define SDC_CLK_MD_400KHZ    0x00010043
-
-#define SDC_CLK_NS_48MHZ     0x00FE005B
-#define SDC_CLK_MD_48MHZ     0x000100FD
-
-void hsusb_clock_init(void);
-void clock_config_uart_dm(uint8_t id);
-void clock_config_i2c(uint8_t id, uint32_t freq);
-
+#define REG(off)        (MSM_CLK_CTL_BASE + (off))
 #define REG_MM(off)     (MSM_MMSS_CLK_CTL_BASE + (off))
+#define REG_LPA(off)    (MSM_LPASS_CLK_CTL_BASE + (off))
 
-#define MDP_CC_REG              REG_MM(0xC0)
-#define MDP_MD_REG              REG_MM(0xC4)
-#define MDP_NS_REG              REG_MM(0xD0)
-#define ESC_CC_REG              REG_MM(0xCC)
-#define ESC_NS_REG              REG_MM(0x11C)
-#define BYTE_CC_REG             REG_MM(0x90)
-#define BYTE_NS_REG             REG_MM(0xB0)
-#define PIXEL_CC_REG            REG_MM(0x130)
-#define PIXEL_MD_REG            REG_MM(0x134)
-#define PIXEL_NS_REG            REG_MM(0x138)
-#define DSI_NS_REG              REG_MM(0x54)
-#define DSI_MD_REG              REG_MM(0x50)
-#define DSI_CC_REG              REG_MM(0x4C)
-#define MISC_CC2_REG            REG_MM(0x5C)
-#define MDP_LUT_CC_REG          REG_MM(0x016C)
+/* Peripheral clock registers. */
+#define CE1_HCLK_CTL_REG                    REG(0x2720)
+#define CE1_CORE_CLK_CTL_REG                REG(0x2724)
+#define CE3_CLK_SRC_NS_REG                  REG(0x36C0)
+#define CE3_HCLK_CTL_REG                    REG(0x36C4)
+#define CE3_CORE_CLK_CTL_REG                REG(0x36CC)
+#define DMA_BAM_HCLK_CTL                    REG(0x25C0)
+#define CLK_HALT_AFAB_SFAB_STATEB_REG       REG(0x2FC4)
+#define CLK_HALT_CFPB_STATEA_REG            REG(0x2FCC)
+#define CLK_HALT_CFPB_STATEB_REG            REG(0x2FD0)
+#define CLK_HALT_CFPB_STATEC_REG            REG(0x2FD4)
+#define CLK_HALT_GSS_KPSS_MISC_STATE_REG    REG(0x2FDC)
+#define CLK_HALT_DFAB_STATE_REG             REG(0x2FC8)
+#define CLK_HALT_MSS_SMPSS_MISC_STATE_REG   REG(0x2FDC)
+#define CLK_HALT_SFPB_MISC_STATE_REG        REG(0x2FD8)
+#define CLK_TEST_REG                        REG(0x2FA0)
+#define GSBIn_HCLK_CTL_REG(n)               REG(0x29C0+(0x20*((n)-1)))
+#define GSBIn_QUP_APPS_MD_REG(n)            REG(0x29C8+(0x20*((n)-1)))
+#define GSBIn_QUP_APPS_NS_REG(n)            REG(0x29CC+(0x20*((n)-1)))
+#define GSBIn_RESET_REG(n)                  REG(0x29DC+(0x20*((n)-1)))
+#define GSBIn_UART_APPS_MD_REG(n)           REG(0x29D0+(0x20*((n)-1)))
+#define GSBIn_UART_APPS_NS_REG(n)           REG(0x29D4+(0x20*((n)-1)))
+#define LPASS_XO_SRC_CLK_CTL_REG            REG(0x2EC0)
+#define PDM_CLK_NS_REG                      REG(0x2CC0)
+#define BB_PLL_ENA_Q6_SW_REG                REG(0x3500)
+#define BB_PLL_ENA_SC0_REG                  REG(0x34C0)
+#define BB_PLL0_STATUS_REG                  REG(0x30D8)
+#define BB_PLL5_STATUS_REG                  REG(0x30F8)
+#define BB_PLL6_STATUS_REG                  REG(0x3118)
+#define BB_PLL7_STATUS_REG                  REG(0x3138)
+#define BB_PLL8_L_VAL_REG                   REG(0x3144)
+#define BB_PLL8_M_VAL_REG                   REG(0x3148)
+#define BB_PLL8_MODE_REG                    REG(0x3140)
+#define BB_PLL8_N_VAL_REG                   REG(0x314C)
+#define BB_PLL8_STATUS_REG                  REG(0x3158)
+#define BB_PLL8_CONFIG_REG                  REG(0x3154)
+#define BB_PLL8_TEST_CTL_REG                REG(0x3150)
+#define BB_PLL3_MODE_REG                    REG(0x3160)
+#define PLLTEST_PAD_CFG_REG                 REG(0x2FA4)
+#define PMEM_ACLK_CTL_REG                   REG(0x25A0)
+#define RINGOSC_NS_REG                      REG(0x2DC0)
+#define RINGOSC_STATUS_REG                  REG(0x2DCC)
+#define RINGOSC_TCXO_CTL_REG                REG(0x2DC4)
+#define SC0_U_CLK_BRANCH_ENA_VOTE_REG       REG(0x3080)
+#define SDCn_APPS_CLK_MD_REG(n)             REG(0x2828+(0x20*((n)-1)))
+#define SDCn_APPS_CLK_NS_REG(n)             REG(0x282C+(0x20*((n)-1)))
+#define SDCn_HCLK_CTL_REG(n)                REG(0x2820+(0x20*((n)-1)))
+#define SDCn_RESET_REG(n)                   REG(0x2830+(0x20*((n)-1)))
+#define SLIMBUS_XO_SRC_CLK_CTL_REG          REG(0x2628)
+#define TSIF_HCLK_CTL_REG                   REG(0x2700)
+#define TSIF_REF_CLK_MD_REG                 REG(0x270C)
+#define TSIF_REF_CLK_NS_REG                 REG(0x2710)
+#define TSSC_CLK_CTL_REG                    REG(0x2CA0)
+#define USB_FSn_HCLK_CTL_REG(n)             REG(0x2960+(0x20*((n)-1)))
+#define USB_FSn_RESET_REG(n)                REG(0x2974+(0x20*((n)-1)))
+#define USB_FSn_SYSTEM_CLK_CTL_REG(n)       REG(0x296C+(0x20*((n)-1)))
+#define USB_FSn_XCVR_FS_CLK_MD_REG(n)       REG(0x2964+(0x20*((n)-1)))
+#define USB_FSn_XCVR_FS_CLK_NS_REG(n)       REG(0x2968+(0x20*((n)-1)))
+#define USB_HS1_HCLK_CTL_REG                REG(0x2900)
+#define USB_HS1_RESET_REG                   REG(0x2910)
+#define USB_HS1_XCVR_FS_CLK_MD_REG          REG(0x2908)
+#define USB_HS1_XCVR_FS_CLK_NS_REG          REG(0x290C)
+#define USB_PHY0_RESET_REG                  REG(0x2E20)
 
-#define MM_PLL1_MODE_REG        REG_MM(0x031C)
-#define MM_PLL1_STATUS_REG      REG_MM(0x0334)
-#define MM_PLL1_CONFIG_REG      REG_MM(0x032C)
 
-/* Configured for 200MHz */
-#define MDP_NS_VAL            0x3F3FC008
-#define MDP_MD_VAL            0x000001FB
-#define MDP_CC_VAL            0x00000500
+/* Multimedia clock registers. */
+#define AHB_EN_REG                      REG_MM(0x0008)
+#define AHB_EN2_REG                     REG_MM(0x0038)
+#define AHB_NS_REG                      REG_MM(0x0004)
+#define AXI_NS_REG                      REG_MM(0x0014)
+#define CAMCLKn_NS_REG(n)               REG_MM(0x0148+(0x14*(n)))
+#define CAMCLKn_CC_REG(n)               REG_MM(0x0140+(0x14*(n)))
+#define CAMCLKn_MD_REG(n)               REG_MM(0x0144+(0x14*(n)))
+#define CSI0_NS_REG                     REG_MM(0x0048)
+#define CSI0_CC_REG                     REG_MM(0x0040)
+#define CSI0_MD_REG                     REG_MM(0x0044)
+#define CSI1_NS_REG                     REG_MM(0x0010)
+#define CSI1_CC_REG                     REG_MM(0x0024)
+#define CSI1_MD_REG                     REG_MM(0x0028)
+#define CSIPHYTIMER_CC_REG              REG_MM(0x0160)
+#define CSIPHYTIMER_MD_REG              REG_MM(0x0164)
+#define CSIPHYTIMER_NS_REG              REG_MM(0x0168)
+#define DSI1_BYTE_NS_REG                REG_MM(0x00B0)
+#define DSI1_BYTE_CC_REG                REG_MM(0x0090)
+#define DSI2_BYTE_NS_REG                REG_MM(0x00BC)
+#define DSI2_BYTE_CC_REG                REG_MM(0x00B4)
+#define DSI1_ESC_NS_REG                 REG_MM(0x011C)
+#define DSI1_ESC_CC_REG                 REG_MM(0x00CC)
+#define DSI2_ESC_NS_REG                 REG_MM(0x0150)
+#define DSI2_ESC_CC_REG                 REG_MM(0x013C)
+#define DSI_PIXEL_CC_REG                REG_MM(0x0130)
+#define DSI_PIXEL_MD_REG                REG_MM(0x0134)
+#define DSI_PIXEL_NS_REG                REG_MM(0x0138)
+#define DSI2_PIXEL_CC_REG               REG_MM(0x0094)
+#define DSI_NS_REG                      REG_MM(0x54)
+#define DSI_MD_REG                      REG_MM(0x50)
+#define DSI_CC_REG                      REG_MM(0x4C)
+#define DBG_BUS_VEC_A_REG               REG_MM(0x01C8)
+#define DBG_BUS_VEC_B_REG               REG_MM(0x01CC)
+#define DBG_BUS_VEC_C_REG               REG_MM(0x01D0)
+#define DBG_BUS_VEC_D_REG               REG_MM(0x01D4)
+#define DBG_BUS_VEC_E_REG               REG_MM(0x01D8)
+#define DBG_BUS_VEC_F_REG               REG_MM(0x01DC)
+#define DBG_BUS_VEC_G_REG               REG_MM(0x01E0)
+#define DBG_BUS_VEC_H_REG               REG_MM(0x01E4)
+#define DBG_BUS_VEC_I_REG               REG_MM(0x01E8)
+#define DBG_CFG_REG_HS_REG              REG_MM(0x01B4)
+#define DBG_CFG_REG_LS_REG              REG_MM(0x01B8)
+#define GFX2D0_CC_REG                   REG_MM(0x0060)
+#define GFX2D0_MD0_REG                  REG_MM(0x0064)
+#define GFX2D0_MD1_REG                  REG_MM(0x0068)
+#define GFX2D0_NS_REG                   REG_MM(0x0070)
+#define GFX2D1_CC_REG                   REG_MM(0x0074)
+#define GFX2D1_MD0_REG                  REG_MM(0x0078)
+#define GFX2D1_MD1_REG                  REG_MM(0x006C)
+#define GFX2D1_NS_REG                   REG_MM(0x007C)
+#define GFX3D_CC_REG                    REG_MM(0x0080)
+#define GFX3D_MD0_REG                   REG_MM(0x0084)
+#define GFX3D_MD1_REG                   REG_MM(0x0088)
+#define GFX3D_NS_REG                    REG_MM(0x008C)
+#define IJPEG_CC_REG                    REG_MM(0x0098)
+#define IJPEG_MD_REG                    REG_MM(0x009C)
+#define IJPEG_NS_REG                    REG_MM(0x00A0)
+#define JPEGD_CC_REG                    REG_MM(0x00A4)
+#define JPEGD_NS_REG                    REG_MM(0x00AC)
+#define MAXI_EN_REG                     REG_MM(0x0018)
+#define MAXI_EN2_REG                    REG_MM(0x0020)
+#define MAXI_EN3_REG                    REG_MM(0x002C)
+#define MAXI_EN4_REG                    REG_MM(0x0114)
+#define MDP_CC_REG                      REG_MM(0x00C0)
+#define MDP_LUT_CC_REG                  REG_MM(0x016C)
+#define MDP_MD0_REG                     REG_MM(0x00C4)
+#define MDP_MD1_REG                     REG_MM(0x00C8)
+#define MDP_NS_REG                      REG_MM(0x00D0)
+#define MISC_CC_REG                     REG_MM(0x0058)
+#define MISC_CC2_REG                    REG_MM(0x005C)
+#define MM_PLL1_MODE_REG                REG_MM(0x031C)
+#define ROT_CC_REG                      REG_MM(0x00E0)
+#define ROT_NS_REG                      REG_MM(0x00E8)
+#define SAXI_EN_REG                     REG_MM(0x0030)
+#define SW_RESET_AHB_REG                REG_MM(0x020C)
+#define SW_RESET_AHB2_REG               REG_MM(0x0200)
+#define SW_RESET_ALL_REG                REG_MM(0x0204)
+#define SW_RESET_AXI_REG                REG_MM(0x0208)
+#define SW_RESET_CORE_REG               REG_MM(0x0210)
+#define TV_CC_REG                       REG_MM(0x00EC)
+#define TV_CC2_REG                      REG_MM(0x0124)
+#define TV_MD_REG                       REG_MM(0x00F0)
+#define TV_NS_REG                       REG_MM(0x00F4)
+#define VCODEC_CC_REG                   REG_MM(0x00F8)
+#define VCODEC_MD0_REG                  REG_MM(0x00FC)
+#define VCODEC_MD1_REG                  REG_MM(0x0128)
+#define VCODEC_NS_REG                   REG_MM(0x0100)
+#define VFE_CC_REG                      REG_MM(0x0104)
+#define VFE_MD_REG                      REG_MM(0x0108)
+#define VFE_NS_REG                      REG_MM(0x010C)
+#define VPE_CC_REG                      REG_MM(0x0110)
+#define VPE_NS_REG                      REG_MM(0x0118)
+
+/* MUX source input identifiers. */
+#define pxo_to_bb_mux       0
+#define cxo_to_bb_mux       pxo_to_bb_mux
+#define pll0_to_bb_mux      2
+#define pll8_to_bb_mux      3
+#define pll6_to_bb_mux      4
+#define gnd_to_bb_mux       5
+#define pll3_to_bb_mux      6
+#define pxo_to_mm_mux       0
+#define pll1_to_mm_mux      1
+#define pll2_to_mm_mux      1
+#define pll8_to_mm_mux      2
+#define pll0_to_mm_mux      3
+#define gnd_to_mm_mux       4
+#define hdmi_pll_to_mm_mux  3
+#define cxo_to_xo_mux       0
+#define pxo_to_xo_mux       1
+#define gnd_to_xo_mux       3
+#define pxo_to_lpa_mux      0
+#define cxo_to_lpa_mux      1
+#define pll4_to_lpa_mux     2
+#define gnd_to_lpa_mux      6
+
+/* Test Vector Macros */
+#define TEST_TYPE_PER_LS    1
+#define TEST_TYPE_PER_HS    2
+#define TEST_TYPE_MM_LS     3
+#define TEST_TYPE_MM_HS     4
+#define TEST_TYPE_LPA       5
+#define TEST_TYPE_CPUL2     6
+#define TEST_TYPE_LPA_HS    7
+#define TEST_TYPE_SHIFT     24
+#define TEST_CLK_SEL_MASK   BM(23, 0)
+#define TEST_VECTOR(s, t)   (((t) << TEST_TYPE_SHIFT) | BVAL(23, 0, (s)))
+#define TEST_PER_LS(s)      TEST_VECTOR((s), TEST_TYPE_PER_LS)
+#define TEST_PER_HS(s)      TEST_VECTOR((s), TEST_TYPE_PER_HS)
+#define TEST_MM_LS(s)       TEST_VECTOR((s), TEST_TYPE_MM_LS)
+#define TEST_MM_HS(s)       TEST_VECTOR((s), TEST_TYPE_MM_HS)
+#define TEST_LPA(s)         TEST_VECTOR((s), TEST_TYPE_LPA)
+#define TEST_LPA_HS(s)      TEST_VECTOR((s), TEST_TYPE_LPA_HS)
+#define TEST_CPUL2(s)       TEST_VECTOR((s), TEST_TYPE_CPUL2)
+
+#define MN_MODE_DUAL_EDGE 0x2
+
+/* MD Registers */
+#define MD4(m_lsb, m, n_lsb, n) \
+    (BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n)))
+
+#define MD8(m_lsb, m, n_lsb, n) \
+    (BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
+
+#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
+
+/* NS Registers */
+#define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
+    (BVAL(n_msb, n_lsb, ~(n-m)) \
+     | (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \
+     | BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
+
+#define NS_MM(n_msb, n_lsb, n, m, d_msb, d_lsb, d, s_msb, s_lsb, s) \
+    (BVAL(n_msb, n_lsb, ~(n-m)) | BVAL(d_msb, d_lsb, (d-1)) \
+     | BVAL(s_msb, s_lsb, s))
+
+#define NS_DIVSRC(d_msb , d_lsb, d, s_msb, s_lsb, s) \
+    (BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
+
+#define NS_DIV(d_msb , d_lsb, d) \
+    BVAL(d_msb, d_lsb, (d-1))
+
+#define NS_SRC_SEL(s_msb, s_lsb, s) \
+    BVAL(s_msb, s_lsb, s)
+
+#define NS_MND_BANKED4(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
+    (BVAL((n0_lsb+3), n0_lsb, ~(n-m)) \
+     | BVAL((n1_lsb+3), n1_lsb, ~(n-m)) \
+     | BVAL((s0_lsb+2), s0_lsb, s) \
+     | BVAL((s1_lsb+2), s1_lsb, s))
+
+#define NS_MND_BANKED8(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
+    (BVAL((n0_lsb+7), n0_lsb, ~(n-m)) \
+     | BVAL((n1_lsb+7), n1_lsb, ~(n-m)) \
+     | BVAL((s0_lsb+2), s0_lsb, s) \
+     | BVAL((s1_lsb+2), s1_lsb, s))
+
+#define NS_DIVSRC_BANKED(d0_msb, d0_lsb, d1_msb, d1_lsb, d, \
+        s0_msb, s0_lsb, s1_msb, s1_lsb, s) \
+(BVAL(d0_msb, d0_lsb, (d-1)) | BVAL(d1_msb, d1_lsb, (d-1)) \
+ | BVAL(s0_msb, s0_lsb, s) \
+ | BVAL(s1_msb, s1_lsb, s))
+
+/* CC Registers */
+#define CC(mde_lsb, n) (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n))
+#define CC_BANKED(mde0_lsb, mde1_lsb, n) \
+    ((BVAL((mde0_lsb+1), mde0_lsb, MN_MODE_DUAL_EDGE) \
+      | BVAL((mde1_lsb+1), mde1_lsb, MN_MODE_DUAL_EDGE)) \
+     * !!(n))
+
+struct pll_rate {
+    const uint32_t    l_val;
+    const uint32_t    m_val;
+    const uint32_t    n_val;
+    const uint32_t    vco;
+    const uint32_t    post_div;
+    const uint32_t    i_bits;
+};
+#define PLL_RATE(l, m, n, v, d, i) { l, m, n, v, (d>>1), i }
+
+/* DSI specific data */
 
 /* Configured at 13.5 MHz */
 #define ESC_NS_VAL            0x00001000
@@ -96,13 +318,10 @@
 #define DSI_MD_VAL            0x000003FB
 #define DSI_CC_VAL            0x00000080
 
-#define MDP_LUT_VAL           0x00000001
-
 void config_mmss_clk(uint32_t ns,
-		     uint32_t md,
-		     uint32_t cc,
-		     uint32_t ns_addr, uint32_t md_addr, uint32_t cc_addr);
-void pll1_enable(void);
+             uint32_t md,
+             uint32_t cc,
+             uint32_t ns_addr, uint32_t md_addr, uint32_t cc_addr);
 void config_mdp_lut_clk(void);
 void mdp_clock_init(void);
 
diff --git a/platform/msm8960/include/platform/iomap.h b/platform/msm8960/include/platform/iomap.h
index 08f8a4b..9a23103 100644
--- a/platform/msm8960/include/platform/iomap.h
+++ b/platform/msm8960/include/platform/iomap.h
@@ -1,7 +1,7 @@
 /* Copyright (c) 2008, Google Inc.
  * All rights reserved.
  *
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -86,24 +86,8 @@
 #define EBI2_CHIP_SELECT_CFG0   0x1A100000
 #define EBI2_XMEM_CS3_CFG1      0x1A110034
 
-#define CLK_CTL_BASE             0x00900000
-#define SDC_MD(n)               (CLK_CTL_BASE + 0x2828 + (32 * ((n) - 1)))
-#define SDC_NS(n)               (CLK_CTL_BASE + 0x282C + (32 * ((n) - 1)))
-#define USB_HS1_HCLK_CTL        (CLK_CTL_BASE + 0x2900)
-#define USB_HS1_XCVR_FS_CLK_MD  (CLK_CTL_BASE + 0x2908)
-#define USB_HS1_XCVR_FS_CLK_NS  (CLK_CTL_BASE + 0x290C)
-#define GSBIn_HCLK_CTL(n)       (CLK_CTL_BASE + 0x29C0 + (32 * ((n) - 1)))
-#define GSBIn_HCLK_FS(n)        (CLK_CTL_BASE + 0x29C4 + (32 * ((n) - 1)))
-#define GSBIn_QUP_APPS_MD(n)    (CLK_CTL_BASE + 0x29C8 + (32 * ((n) - 1)))
-#define GSBIn_QUP_APPS_NS(n)    (CLK_CTL_BASE + 0x29CC + (32 * ((n) - 1)))
-#define GSBIn_UART_APPS_MD(n)   (CLK_CTL_BASE + 0x29D0 + (32 * ((n) - 1)))
-#define GSBIn_UART_APPS_NS(n)   (CLK_CTL_BASE + 0x29D4 + (32 * ((n) - 1)))
-#define MSM_BOOT_PLL8_STATUS    (CLK_CTL_BASE + 0x3158)
-#define MSM_BOOT_PLL_ENABLE_SC0 (CLK_CTL_BASE + 0x34C0)
-#define CE1_HCLK_CTL            (CLK_CTL_BASE + 0x2720)
-#define CE1_CORE_CLK_CTL        (CLK_CTL_BASE + 0x2724)
-
-#define MSM_MMSS_CLK_CTL_BASE 0x04000000
+#define MSM_CLK_CTL_BASE        0x00900000
+#define MSM_MMSS_CLK_CTL_BASE 	0x04000000
 
 #define MIPI_DSI_BASE                         (0x04700000)
 #define REG_DSI(off)                          (MIPI_DSI_BASE + (off))
diff --git a/platform/msm8960/platform.c b/platform/msm8960/platform.c
index d45b699..c4f339f 100644
--- a/platform/msm8960/platform.c
+++ b/platform/msm8960/platform.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -46,6 +46,7 @@
 extern void mmss_clock_init(void);
 extern struct fbcon_config *mipi_init(void);
 extern void mipi_dsi_shutdown(void);
+extern void msm_clocks_init(void);
 
 static uint32_t ticks_per_sec = 0;
 static uint8_t display_enabled = 0;
@@ -85,6 +86,7 @@
 
 void platform_early_init(void)
 {
+	msm_clocks_init();
 	qgic_init();
 	platform_init_timer();
 }
diff --git a/platform/msm8960/rules.mk b/platform/msm8960/rules.mk
index 9fbaf93..ccc6833 100644
--- a/platform/msm8960/rules.mk
+++ b/platform/msm8960/rules.mk
@@ -20,6 +20,7 @@
 	$(LOCAL_DIR)/platform.o \
 	$(LOCAL_DIR)/acpuclock.o \
 	$(LOCAL_DIR)/gpio.o \
+	$(LOCAL_DIR)/clock.o
 
 LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld
 
diff --git a/platform/msm8x60/acpuclock.c b/platform/msm8x60/acpuclock.c
index 47e6526..c759d90 100644
--- a/platform/msm8x60/acpuclock.c
+++ b/platform/msm8x60/acpuclock.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -409,12 +409,12 @@
 	unsigned long src_sel = 0x3;	// dsi_phy_pll0_src
 	unsigned long pre_div_func = 0x01;	// predivide by 2
 
-	secure_writel(pre_div_func << 12 | src_sel, PIXEL_NS_REG);
+	secure_writel(pre_div_func << 12 | src_sel, DSI_PIXEL_NS_REG);
 
 	mnd_mode = 0;		// Bypass MND
 	root_en = 1;
 	clk_en = 1;
-	secure_writel(mnd_mode << 6, PIXEL_CC_REG);
-	secure_writel(secure_readl(PIXEL_CC_REG) | root_en << 2, PIXEL_CC_REG);
-	secure_writel(secure_readl(PIXEL_CC_REG) | clk_en, PIXEL_CC_REG);
+	secure_writel(mnd_mode << 6, DSI_PIXEL_CC_REG);
+	secure_writel(secure_readl(DSI_PIXEL_CC_REG) | root_en << 2, DSI_PIXEL_CC_REG);
+	secure_writel(secure_readl(DSI_PIXEL_CC_REG) | clk_en, DSI_PIXEL_CC_REG);
 }
diff --git a/platform/msm8x60/include/platform/clock.h b/platform/msm8x60/include/platform/clock.h
index 62b31d4..4ca32c2 100644
--- a/platform/msm8x60/include/platform/clock.h
+++ b/platform/msm8x60/include/platform/clock.h
@@ -1,5 +1,5 @@
 /*
- * * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -73,9 +73,9 @@
 #define MMSS_PIXEL_CC_REG   REG_MM(0xD4)
 
 /* MMSS DSI Pixel Registers not MMSS Pixel */
-#define PIXEL_MD_REG        REG_MM(0x134)
-#define PIXEL_NS_REG        REG_MM(0x138)
-#define PIXEL_CC_REG        REG_MM(0x130)
+#define DSI_PIXEL_MD_REG    REG_MM(0x134)
+#define DSI_PIXEL_NS_REG    REG_MM(0x138)
+#define DSI_PIXEL_CC_REG    REG_MM(0x130)
 
 /* Configured at 200 MHz */
 #define MDP_NS_VAL              0x3F000008
diff --git a/platform/msm_shared/clock-local.c b/platform/msm_shared/clock-local.c
new file mode 100644
index 0000000..9f2d99d
--- /dev/null
+++ b/platform/msm_shared/clock-local.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Code Aurora nor
+ *     the names of its contributors may be used to endorse or promote
+ *     products derived from this software without specific prior written
+ *     permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <debug.h>
+#include <reg.h>
+#include <err.h>
+#include <limits.h>
+#include <bits.h>
+#include <clock.h>
+#include <clock-local.h>
+
+/*
+ * When enabling/disabling a clock, check the halt bit up to this number
+ * number of times (with a 1 us delay in between) before continuing.
+ */
+#define HALT_CHECK_MAX_LOOPS	100
+/* For clock without halt checking, wait this long after enables/disables. */
+#define HALT_CHECK_DELAY_US	10
+
+struct clk_freq_tbl local_dummy_freq = F_END;
+
+/*
+ * Clock enable/disable functions
+ */
+static int branch_clk_is_halted(const struct branch *clk)
+{
+	int invert = (clk->halt_check == ENABLE);
+	int status_bit = readl_relaxed(clk->halt_reg) & BIT(clk->halt_bit);
+	return invert ? !status_bit : status_bit;
+}
+
+static void __branch_clk_enable_reg(const struct branch *clk, const char *name)
+{
+	uint32_t reg_val;
+
+	if (clk->en_mask) {
+		reg_val = readl_relaxed(clk->ctl_reg);
+		reg_val |= clk->en_mask;
+		writel_relaxed(reg_val, clk->ctl_reg);
+	}
+
+	/* Wait for clock to enable before returning. */
+	if (clk->halt_check == DELAY)
+		udelay(HALT_CHECK_DELAY_US);
+	else if (clk->halt_check == ENABLE || clk->halt_check == HALT
+			|| clk->halt_check == ENABLE_VOTED
+			|| clk->halt_check == HALT_VOTED) {
+		int count;
+
+		/* Wait up to HALT_CHECK_MAX_LOOPS for clock to enable. */
+		for (count = HALT_CHECK_MAX_LOOPS; branch_clk_is_halted(clk)
+					&& count > 0; count--)
+			udelay(1);
+	}
+}
+
+/* Perform any register operations required to enable the clock. */
+static void __local_clk_enable_reg(struct rcg_clk *clk)
+{
+	uint32_t reg_val;
+
+	void *const reg = clk->b.ctl_reg;
+
+	if(clk->current_freq == &local_dummy_freq)
+		dprintf(CRITICAL, "Attempting to enable %s before setting its rate.", clk->c.dbg_name);
+	/*
+	 * Program the NS register, if applicable. NS registers are not
+	 * set in the set_rate path because power can be saved by deferring
+	 * the selection of a clocked source until the clock is enabled.
+	 */
+	if (clk->ns_mask) {
+		reg_val = readl_relaxed(clk->ns_reg);
+		reg_val &= ~(clk->ns_mask);
+		reg_val |= (clk->current_freq->ns_val & clk->ns_mask);
+		writel_relaxed(reg_val, clk->ns_reg);
+	}
+
+	/* Enable MN counter, if applicable. */
+	reg_val = readl_relaxed(reg);
+	if (clk->current_freq->mnd_en_mask) {
+		reg_val |= clk->current_freq->mnd_en_mask;
+		writel_relaxed(reg_val, reg);
+	}
+	/* Enable root. */
+	if (clk->root_en_mask) {
+		reg_val |= clk->root_en_mask;
+		writel_relaxed(reg_val, reg);
+	}
+	__branch_clk_enable_reg(&clk->b, clk->c.dbg_name);
+}
+
+/* Enable a clock and any related power rail. */
+int local_clk_enable(struct clk *c)
+{
+	int rc;
+	struct clk_freq_tbl *cf;
+	struct rcg_clk *clk = to_rcg_clk(c);
+
+	cf = clk->current_freq;
+	rc = clk_enable(clk->depends);
+	if (rc)
+		goto err_dep;
+	__local_clk_enable_reg(clk);
+	clk->enabled = true;
+err_dep:
+	return rc;
+}
+
+/* Disable a clock and any related power rail. */
+void local_clk_disable(struct clk *c)
+{
+	/*TODO: Stub function for now.*/
+}
+
+/*
+ * Frequency-related functions
+ */
+
+/* Set a clock's frequency. */
+static int _local_clk_set_rate(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+{
+	struct clk_freq_tbl *cf;
+	int rc = 0;
+
+	/* Check if frequency is actually changed. */
+	cf = clk->current_freq;
+	if (nf == cf)
+		goto unlock;
+
+	if (clk->enabled) {
+		rc = clk_enable(nf->src_clk);
+		if (rc) {
+			goto unlock;
+		}
+	}
+
+	/* Perform clock-specific frequency switch operations. */
+	ASSERT(clk->set_rate);
+	clk->set_rate(clk, nf);
+
+	/*
+	 * Current freq must be updated before __local_clk_enable_reg()
+	 * is called to make sure the MNCNTR_EN bit is set correctly.
+	 */
+	clk->current_freq = nf;
+
+	/* Enable any clocks that were disabled. */
+	if (clk->bank_masks == NULL) {
+		if (clk->enabled)
+			__local_clk_enable_reg(clk);
+	}
+
+unlock:
+	return rc;
+}
+
+/* Set a clock to an exact rate. */
+int local_clk_set_rate(struct clk *c, unsigned rate)
+{
+	struct rcg_clk *clk = to_rcg_clk(c);
+	struct clk_freq_tbl *nf;
+
+	for (nf = clk->freq_tbl; nf->freq_hz != FREQ_END
+			&& nf->freq_hz != rate; nf++)
+		;
+
+	if (nf->freq_hz == FREQ_END)
+		return ERR_INVALID_ARGS;
+
+	return _local_clk_set_rate(clk, nf);
+}
+
+/* Get the currently-set rate of a clock in Hz. */
+unsigned local_clk_get_rate(struct clk *c)
+{
+	/* TODO: Stub function for now. */
+	return 0;
+}
+
+/* Check if a clock is currently enabled. */
+int local_clk_is_enabled(struct clk *clk)
+{
+	return to_rcg_clk(clk)->enabled;
+}
+
+/* Return a supported rate that's at least the specified rate. */
+long local_clk_round_rate(struct clk *c, unsigned rate)
+{
+	struct rcg_clk *clk = to_rcg_clk(c);
+	struct clk_freq_tbl *f;
+
+	for (f = clk->freq_tbl; f->freq_hz != FREQ_END; f++)
+		if (f->freq_hz >= rate)
+			return f->freq_hz;
+
+	return ERR_INVALID_ARGS;
+}
+
+struct clk *local_clk_get_parent(struct clk *clk)
+{
+	return to_rcg_clk(clk)->current_freq->src_clk;
+}
+
+/*
+ * pll_vote_clk functions
+ */
+static int pll_vote_clk_enable(struct clk *clk)
+{
+	uint32_t ena;
+	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+
+	ena = readl_relaxed(pll->en_reg);
+	ena |= pll->en_mask;
+	writel_relaxed(ena, pll->en_reg);
+
+	/* Wait until PLL is enabled */
+	while ((readl_relaxed(pll->status_reg) & BIT(16)) == 0);
+
+	return 0;
+}
+
+static void pll_vote_clk_disable(struct clk *clk)
+{
+	uint32_t ena;
+	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+
+	ena = readl_relaxed(pll->en_reg);
+	ena &= ~(pll->en_mask);
+	writel_relaxed(ena, pll->en_reg);
+}
+
+static unsigned pll_vote_clk_get_rate(struct clk *clk)
+{
+	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+	return pll->rate;
+}
+
+static struct clk *pll_vote_clk_get_parent(struct clk *clk)
+{
+	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+	return pll->parent;
+}
+
+static int pll_vote_clk_is_enabled(struct clk *clk)
+{
+	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+	return !!(readl_relaxed(pll->status_reg) & BIT(16));
+}
+
+struct clk_ops clk_ops_pll_vote = {
+	.enable = pll_vote_clk_enable,
+	.disable = pll_vote_clk_disable,
+	.is_enabled = pll_vote_clk_is_enabled,
+	.get_rate = pll_vote_clk_get_rate,
+	.get_parent = pll_vote_clk_get_parent,
+};
+
+/*
+ * PLLs functions
+ */
+static int pll_clk_enable(struct clk *clk)
+{
+	uint32_t mode;
+	struct pll_clk *pll = to_pll_clk(clk);
+
+	mode = readl_relaxed(pll->mode_reg);
+	/* Disable PLL bypass mode. */
+	mode |= BIT(1);
+	writel_relaxed(mode, pll->mode_reg);
+
+	/*
+	 * H/W requires a 5us delay between disabling the bypass and
+	 * de-asserting the reset. Delay 10us just to be safe.
+	 */
+	udelay(10);
+
+	/* De-assert active-low PLL reset. */
+	mode |= BIT(2);
+	writel_relaxed(mode, pll->mode_reg);
+
+	/* Wait until PLL is locked. */
+	udelay(50);
+
+	/* Enable PLL output. */
+	mode |= BIT(0);
+	writel_relaxed(mode, pll->mode_reg);
+
+	return 0;
+}
+
+static void pll_clk_disable(struct clk *clk)
+{
+	uint32_t mode;
+	struct pll_clk *pll = to_pll_clk(clk);
+
+	/*
+	 * Disable the PLL output, disable test mode, enable
+	 * the bypass mode, and assert the reset.
+	 */
+	mode = readl_relaxed(pll->mode_reg);
+	mode &= ~BM(3, 0);
+	writel_relaxed(mode, pll->mode_reg);
+}
+
+static unsigned pll_clk_get_rate(struct clk *clk)
+{
+	struct pll_clk *pll = to_pll_clk(clk);
+	return pll->rate;
+}
+
+static struct clk *pll_clk_get_parent(struct clk *clk)
+{
+	struct pll_clk *pll = to_pll_clk(clk);
+	return pll->parent;
+}
+
+struct clk_ops clk_ops_pll = {
+	.enable = pll_clk_enable,
+	.disable = pll_clk_disable,
+	.get_rate = pll_clk_get_rate,
+	.get_parent = pll_clk_get_parent,
+};
+
+/*
+ * Branch clocks functions
+ */
+int branch_clk_enable(struct clk *clk)
+{
+	struct branch_clk *branch = to_branch_clk(clk);
+
+	__branch_clk_enable_reg(&branch->b, branch->c.dbg_name);
+	branch->enabled = true;
+
+	return 0;
+}
+
+void branch_clk_disable(struct clk *clk)
+{
+	struct branch_clk *branch = to_branch_clk(clk);
+
+	/* TODO: Stub function for now */
+}
+
+struct clk *branch_clk_get_parent(struct clk *clk)
+{
+	struct branch_clk *branch = to_branch_clk(clk);
+	return branch->parent;
+}
+
+int branch_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	/* This is a stub function. */
+	return 0;
+}
+
+int branch_clk_is_enabled(struct clk *clk)
+{
+	struct branch_clk *branch = to_branch_clk(clk);
+	return branch->enabled;
+}
+
+/**/
+/* For clocks with MND dividers. */
+void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+{
+	uint32_t ns_reg_val, ctl_reg_val;
+
+	/* Assert MND reset. */
+	ns_reg_val = readl_relaxed(clk->ns_reg);
+	ns_reg_val |= BIT(7);
+	writel_relaxed(ns_reg_val, clk->ns_reg);
+
+	/* Program M and D values. */
+	writel_relaxed(nf->md_val, clk->md_reg);
+
+	/* If the clock has a separate CC register, program it. */
+	if (clk->ns_reg != clk->b.ctl_reg) {
+		ctl_reg_val = readl_relaxed(clk->b.ctl_reg);
+		ctl_reg_val &= ~(clk->ctl_mask);
+		ctl_reg_val |= nf->ctl_val;
+		writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+	}
+
+	/* Deassert MND reset. */
+	ns_reg_val &= ~BIT(7);
+	writel_relaxed(ns_reg_val, clk->ns_reg);
+}
+
+void set_rate_mnd_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+{
+	struct bank_masks *banks = clk->bank_masks;
+	const struct bank_mask_info *new_bank_masks;
+	const struct bank_mask_info *old_bank_masks;
+	uint32_t ns_reg_val, ctl_reg_val;
+	uint32_t bank_sel;
+
+	/*
+	 * Determine active bank and program the other one. If the clock is
+	 * off, program the active bank since bank switching won't work if
+	 * both banks aren't running.
+	 */
+	ctl_reg_val = readl_relaxed(clk->b.ctl_reg);
+	bank_sel = !!(ctl_reg_val & banks->bank_sel_mask);
+
+	/* If clock isn't running, don't switch banks. */
+	bank_sel ^= (!clk->enabled || clk->current_freq->freq_hz == 0);
+	if (bank_sel == 0) {
+		new_bank_masks = &banks->bank1_mask;
+		old_bank_masks = &banks->bank0_mask;
+	} else {
+		new_bank_masks = &banks->bank0_mask;
+		old_bank_masks = &banks->bank1_mask;
+	}
+
+	ns_reg_val = readl_relaxed(clk->ns_reg);
+
+	/* Assert bank MND reset. */
+	ns_reg_val |= new_bank_masks->rst_mask;
+	writel_relaxed(ns_reg_val, clk->ns_reg);
+
+	/*
+	 * Program NS only if the clock is enabled, since the NS will be set
+	 * as part of the enable procedure and should remain with a low-power
+	 * MUX input selected until then.
+	 */
+	if (clk->enabled) {
+		ns_reg_val &= ~(new_bank_masks->ns_mask);
+		ns_reg_val |= (nf->ns_val & new_bank_masks->ns_mask);
+		writel_relaxed(ns_reg_val, clk->ns_reg);
+	}
+
+	writel_relaxed(nf->md_val, new_bank_masks->md_reg);
+
+	/* Enable counter only if clock is enabled. */
+	if (clk->enabled)
+		ctl_reg_val |= new_bank_masks->mnd_en_mask;
+	else
+		ctl_reg_val &= ~(new_bank_masks->mnd_en_mask);
+
+	ctl_reg_val &= ~(new_bank_masks->mode_mask);
+	ctl_reg_val |= (nf->ctl_val & new_bank_masks->mode_mask);
+	writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+
+	/* Deassert bank MND reset. */
+	ns_reg_val &= ~(new_bank_masks->rst_mask);
+	writel_relaxed(ns_reg_val, clk->ns_reg);
+
+	/*
+	 * Switch to the new bank if clock is running.  If it isn't, then
+	 * no switch is necessary since we programmed the active bank.
+	 */
+	if (clk->enabled && clk->current_freq->freq_hz) {
+		ctl_reg_val ^= banks->bank_sel_mask;
+		writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+		/*
+		 * Wait at least 6 cycles of slowest bank's clock
+		 * for the glitch-free MUX to fully switch sources.
+		 */
+		udelay(1);
+
+		/* Disable old bank's MN counter. */
+		ctl_reg_val &= ~(old_bank_masks->mnd_en_mask);
+		writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+
+		/* Program old bank to a low-power source and divider. */
+		ns_reg_val &= ~(old_bank_masks->ns_mask);
+		ns_reg_val |= (clk->freq_tbl->ns_val & old_bank_masks->ns_mask);
+		writel_relaxed(ns_reg_val, clk->ns_reg);
+	}
+
+	/*
+	 * If this freq requires the MN counter to be enabled,
+	 * update the enable mask to match the current bank.
+	 */
+	if (nf->mnd_en_mask)
+		nf->mnd_en_mask = new_bank_masks->mnd_en_mask;
+	/* Update the NS mask to match the current bank. */
+	clk->ns_mask = new_bank_masks->ns_mask;
+}
+
+void set_rate_nop(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+{
+	/*
+	 * Nothing to do for fixed-rate or integer-divider clocks. Any settings
+	 * in NS registers are applied in the enable path, since power can be
+	 * saved by leaving an un-clocked or slowly-clocked source selected
+	 * until the clock is enabled.
+	 */
+}
+
diff --git a/platform/msm_shared/clock.c b/platform/msm_shared/clock.c
new file mode 100644
index 0000000..aa66499
--- /dev/null
+++ b/platform/msm_shared/clock.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Code Aurora nor
+ *     the names of its contributors may be used to endorse or promote
+ *     products derived from this software without specific prior written
+ *     permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <debug.h>
+#include <reg.h>
+#include <err.h>
+#include <limits.h>
+#include <bits.h>
+#include <clock.h>
+#include <string.h>
+
+static struct clk_list msm_clk_list;
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (!clk->ops->set_parent)
+		return 0;
+
+	return clk->ops->set_parent(clk, parent);
+}
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (!clk->ops->get_parent)
+		return NULL;
+
+	return clk->ops->get_parent(clk);
+}
+
+/*
+ * Standard clock functions defined in include/clk.h
+ */
+int clk_enable(struct clk *clk)
+{
+	int ret = 0;
+	struct clk *parent;
+
+	if (!clk)
+		return 0;
+
+	if (clk->count == 0) {
+		parent = clk_get_parent(clk);
+		ret = clk_enable(parent);
+		if (ret)
+			goto out;
+
+		if (clk->ops->enable)
+			ret = clk->ops->enable(clk);
+		if (ret) {
+			clk_disable(parent);
+			goto out;
+		}
+	}
+	clk->count++;
+out:
+	return ret;
+}
+
+void clk_disable(struct clk *clk)
+{
+	struct clk *parent;
+
+	if (!clk)
+		return;
+
+	if (clk->count == 0)
+		goto out;
+	if (clk->count == 1) {
+		if (clk->ops->disable)
+			clk->ops->disable(clk);
+		parent = clk_get_parent(clk);
+		clk_disable(parent);
+	}
+	clk->count--;
+out:
+	return;
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (!clk->ops->get_rate)
+		return 0;
+
+	return clk->ops->get_rate(clk);
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk->ops->set_rate)
+		return ERR_NOT_VALID;
+
+	return clk->ops->set_rate(clk, rate);
+}
+
+void clk_init(struct clk_lookup *clist, unsigned num)
+{
+	if(clist && num)
+	{
+		msm_clk_list.clist = (struct clk_lookup *)clist;
+		msm_clk_list.num = num;
+	}
+}
+
+struct clk *clk_get (const char * cid)
+{
+	unsigned i;
+	struct clk_lookup *cl= msm_clk_list.clist;
+	unsigned num = msm_clk_list.num;
+
+	if(!cl || !num)
+	{
+		dprintf (CRITICAL, "Alert!! clock list not defined!\n");
+		return NULL;
+	}
+	for(i=0; i < num; i++, cl++)
+	{
+		if(!strcmp(cl->con_id, cid))
+		{
+			return cl->clk;
+		}
+	}
+
+	dprintf(CRITICAL, "Alert!! Requested clock \"%s\" is not supported!", cid);
+	return NULL;
+}
+
+int clk_get_set_enable(char *id, unsigned long rate, bool enable)
+{
+	int ret = NO_ERROR;
+	struct clk *cp;
+
+	/* Get clk */
+	cp = clk_get(id);
+	if(!cp)
+	{
+		dprintf(CRITICAL, "Can't find clock with id: %s\n", id);
+		ret = ERR_NOT_VALID;
+		goto get_set_enable_error;
+	}
+
+	/* Set rate */
+	if(rate)
+	{
+		ret = clk_set_rate(cp, rate);
+		if(ret)
+		{
+			dprintf(CRITICAL, "Clock set rate failed.\n");
+			goto get_set_enable_error;
+		}
+	}
+
+	/* Enable clock */
+	if(enable)
+	{
+		ret = clk_enable(cp);
+		if(ret)
+		{
+			dprintf(CRITICAL, "Clock enable failed.\n");
+		}
+	}
+
+get_set_enable_error:
+	return ret;
+}
+
+#ifdef DEBUG_CLOCK
+struct clk_list *clk_get_list()
+{
+	return &msm_clk_list;
+}
+#endif
diff --git a/platform/msm_shared/include/clock-local.h b/platform/msm_shared/include/clock-local.h
new file mode 100644
index 0000000..d03135c
--- /dev/null
+++ b/platform/msm_shared/include/clock-local.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Code Aurora nor
+ *     the names of its contributors may be used to endorse or promote
+ *     products derived from this software without specific prior written
+ *     permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CLOCK_LOCAL_H
+#define CLOCK_LOCAL_H
+
+struct clk;
+struct clk_ops;
+
+#define FREQ_END	(UINT_MAX-1)
+#define F_END \
+	{ \
+		.freq_hz = FREQ_END, \
+	}
+
+#define container_of(ptr, type, member) \
+	((type *)((addr_t)(ptr) - offsetof(type, member)))
+
+/*
+ * Bit manipulation macros
+ */
+#define BM(msb, lsb)	(((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
+#define BVAL(msb, lsb, val)	(((val) << lsb) & BM(msb, lsb))
+
+/*
+ * Halt/Status Checking Mode Macros
+ */
+#define HALT            0   /* Bit pol: 1 = halted */
+#define NOCHECK         1   /* No bit to check, do nothing */
+#define HALT_VOTED      2   /* Bit pol: 1 = halted; delay on disable */
+#define ENABLE          3   /* Bit pol: 1 = running */
+#define ENABLE_VOTED    4   /* Bit pol: 1 = running; delay on disable */
+#define DELAY           5   /* No bit to check, just delay */
+
+/*
+ * Variables from clock-local driver
+ */
+extern struct fixed_clk gnd_clk;
+
+/*
+ * Generic frequency-definition structs and macros
+ */
+struct clk_freq_tbl {
+	const uint32_t	freq_hz;
+	struct clk	*src_clk;
+	const uint32_t	md_val;
+	const uint32_t	ns_val;
+	const uint32_t	ctl_val;
+	uint32_t	mnd_en_mask;
+	void		*const extra_freq_data;
+};
+
+extern struct clk_freq_tbl local_dummy_freq;
+
+/* Some clocks have two banks to avoid glitches when switching frequencies.
+ * The unused bank is programmed while running on the other bank, and
+ * switched to afterwards. The following two structs describe the banks. */
+struct bank_mask_info {
+	void *const md_reg;
+	const uint32_t	ns_mask;
+	const uint32_t	rst_mask;
+	const uint32_t	mnd_en_mask;
+	const uint32_t	mode_mask;
+};
+
+struct bank_masks {
+	const uint32_t			bank_sel_mask;
+	const struct bank_mask_info	bank0_mask;
+	const struct bank_mask_info	bank1_mask;
+};
+
+/**
+ * struct branch - branch on/off
+ * @ctl_reg: clock control register
+ * @en_mask: ORed with @ctl_reg to enable the clock
+ * @halt_reg: halt register
+ * @halt_check: type of halt check to perform
+ * @halt_bit: ANDed with @halt_reg to test for clock halted
+ * @reset_reg: reset register
+ * @reset_mask: ORed with @reset_reg to reset the clock domain
+ */
+struct branch {
+	void *const ctl_reg;
+	const uint32_t en_mask;
+
+	void *const halt_reg;
+	const uint16_t halt_check;
+	const uint16_t halt_bit;
+
+	void *const reset_reg;
+	const uint32_t reset_mask;
+};
+
+/*
+ * Generic clock-definition struct and macros
+ */
+struct rcg_clk {
+	bool		enabled;
+	void		*const ns_reg;
+	void		*const md_reg;
+
+	const uint32_t	root_en_mask;
+	uint32_t	ns_mask;
+	const uint32_t	ctl_mask;
+	struct bank_masks *const bank_masks;
+
+	void   (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
+	struct clk_freq_tbl *const freq_tbl;
+	struct clk_freq_tbl *current_freq;
+
+	struct clk *depends;
+	struct branch	b;
+	struct clk	c;
+};
+
+static inline struct rcg_clk *to_rcg_clk(struct clk *clk)
+{
+	return container_of(clk, struct rcg_clk, c);
+}
+
+/**
+ * struct fixed_clk - fixed rate clock (used for crystal oscillators)
+ * @rate: output rate
+ * @c: clk
+ */
+struct fixed_clk {
+	unsigned long rate;
+	struct clk c;
+};
+
+static inline struct fixed_clk *to_fixed_clk(struct clk *clk)
+{
+	return container_of(clk, struct fixed_clk, c);
+}
+
+static inline unsigned fixed_clk_get_rate(struct clk *clk)
+{
+	struct fixed_clk *f = to_fixed_clk(clk);
+	return f->rate;
+}
+
+/**
+ * struct pll_vote_clk - phase locked loop (HW voteable)
+ * @rate: output rate
+ * @en_reg: enable register
+ * @en_mask: ORed with @en_reg to enable the clock
+ * @status_reg: status register
+ * @parent: clock source
+ * @c: clk
+ */
+struct pll_vote_clk {
+	unsigned long rate;
+
+	void *const en_reg;
+	const uint32_t en_mask;
+
+	void *const status_reg;
+
+	struct clk *parent;
+	struct clk c;
+};
+
+extern struct clk_ops clk_ops_pll_vote;
+
+static inline struct pll_vote_clk *to_pll_vote_clk(struct clk *clk)
+{
+	return container_of(clk, struct pll_vote_clk, c);
+}
+
+/**
+ * struct pll_clk - phase locked loop
+ * @rate: output rate
+ * @mode_reg: enable register
+ * @parent: clock source
+ * @c: clk
+ */
+struct pll_clk {
+	unsigned long rate;
+
+	void *const mode_reg;
+
+	struct clk *parent;
+	struct clk c;
+};
+
+extern struct clk_ops clk_ops_pll;
+
+static inline struct pll_clk *to_pll_clk(struct clk *clk)
+{
+	return container_of(clk, struct pll_clk, c);
+}
+
+/**
+ * struct branch_clk - branch
+ * @enabled: true if clock is on, false otherwise
+ * @b: branch
+ * @parent: clock source
+ * @c: clk
+ *
+ * An on/off switch with a rate derived from the parent.
+ */
+struct branch_clk {
+	bool enabled;
+	struct branch b;
+	struct clk *parent;
+	struct clk c;
+};
+
+static inline struct branch_clk *to_branch_clk(struct clk *clk)
+{
+	return container_of(clk, struct branch_clk, c);
+}
+
+int branch_clk_enable(struct clk *clk);
+void branch_clk_disable(struct clk *clk);
+struct clk *branch_clk_get_parent(struct clk *clk);
+int branch_clk_set_parent(struct clk *clk, struct clk *parent);
+int branch_clk_is_enabled(struct clk *clk);
+void branch_clk_auto_off(struct clk *clk);
+int branch_clk_reset(struct clk *c, enum clk_reset_action action);
+
+/**
+ * struct measure_clk - for rate measurement debug use
+ * @sample_ticks: sample period in reference clock ticks
+ * @multiplier: measurement scale-up factor
+ * @divider: measurement scale-down factor
+ * @c: clk
+*/
+struct measure_clk {
+	uint64_t sample_ticks;
+	uint32_t multiplier;
+	uint32_t divider;
+	struct clk c;
+};
+
+extern struct clk_ops clk_ops_measure;
+
+static inline struct measure_clk *to_measure_clk(struct clk *clk)
+{
+	return container_of(clk, struct measure_clk, c);
+}
+
+/*
+ * clk_ops APIs
+ */
+int local_clk_enable(struct clk *c);
+void local_clk_disable(struct clk *c);
+int local_clk_set_rate(struct clk *c, unsigned rate);
+unsigned local_clk_get_rate(struct clk *c);
+int local_clk_is_enabled(struct clk *clk);
+long local_clk_round_rate(struct clk *c, unsigned rate);
+struct clk *local_clk_get_parent(struct clk *clk);
+
+/*
+ * Generic set-rate implementations
+ */
+void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf);
+void set_rate_mnd_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
+void set_rate_nop(struct rcg_clk *clk, struct clk_freq_tbl *nf);
+#endif
diff --git a/platform/msm_shared/include/clock.h b/platform/msm_shared/include/clock.h
new file mode 100644
index 0000000..be17efd
--- /dev/null
+++ b/platform/msm_shared/include/clock.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Code Aurora nor
+ *     the names of its contributors may be used to endorse or promote
+ *     products derived from this software without specific prior written
+ *     permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CLOCK_H
+#define CLOCK_H
+
+#undef readl_relaxed
+#undef writel_relaxed
+
+#ifdef MSM_SECURE_IO
+#define readl_relaxed secure_readl
+#define writel_relaxed secure_writel
+#else
+#define readl_relaxed readl
+#define writel_relaxed writel
+#endif
+
+enum clk_reset_action {
+	CLK_RESET_DEASSERT	= 0,
+	CLK_RESET_ASSERT	= 1
+};
+
+struct clk;
+struct clk_ops {
+	int (*enable)(struct clk *clk);
+	void (*disable)(struct clk *clk);
+	void (*auto_off)(struct clk *clk);
+	int (*reset)(struct clk *clk, enum clk_reset_action action);
+	int (*set_rate)(struct clk *clk, unsigned rate);
+	int (*set_min_rate)(struct clk *clk, unsigned rate);
+	int (*set_max_rate)(struct clk *clk, unsigned rate);
+	int (*set_flags)(struct clk *clk, unsigned flags);
+	unsigned (*get_rate)(struct clk *clk);
+	int (*list_rate)(struct clk *clk, unsigned n);
+	int (*is_enabled)(struct clk *clk);
+	long (*round_rate)(struct clk *clk, unsigned rate);
+	int (*set_parent)(struct clk *clk, struct clk *parent);
+	struct clk *(*get_parent)(struct clk *clk);
+	bool (*is_local)(struct clk *clk);
+};
+
+/**
+ * struct clk
+ * @count: enable refcount
+ * @lock: protects clk_enable()/clk_disable() path and @count
+ */
+struct clk {
+	uint32_t flags;
+	struct clk_ops *ops;
+	const char *dbg_name;
+	unsigned count;
+};
+
+/**
+ * clk_get - lookup and obtain a reference to a clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock comsumer ID
+ *
+ * Returns a struct clk corresponding to the clock producer, or
+ * valid IS_ERR() condition containing errno.  The implementation
+ * uses @dev and @id to determine the clock consumer, and thereby
+ * the clock producer.  (IOW, @id may be identical strings, but
+ * clk_get may return different clock producers depending on @dev.)
+ *
+ * Drivers must assume that the clock source is not enabled.
+ *
+ * clk_get should not be called from within interrupt context.
+ */
+struct clk *clk_get(const char *id);
+
+
+/**
+ * clk_enable - inform the system when the clock source should be running.
+ * @clk: clock source
+ *
+ * If the clock can not be enabled/disabled, this should return success.
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_enable(struct clk *clk);
+
+/**
+ * clk_disable - inform the system when the clock source is no longer required.
+ * @clk: clock source
+ *
+ * Inform the system that a clock source is no longer required by
+ * a driver and may be shut down.
+ *
+ * Implementation detail: if the clock source is shared between
+ * multiple drivers, clk_enable() calls must be balanced by the
+ * same number of clk_disable() calls for the clock source to be
+ * disabled.
+ */
+void clk_disable(struct clk *clk);
+
+/**
+ * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
+ *		  This is only valid once the clock source has been enabled.
+ * @clk: clock source
+ */
+unsigned long clk_get_rate(struct clk *clk);
+
+/**
+ * clk_set_rate - set the clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired clock rate in Hz
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate);
+
+/**
+ * clk_set_parent - set the parent clock source for this clock
+ * @clk: clock source
+ * @parent: parent clock source
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent);
+
+/**
+ * clk_get_parent - get the parent clock source for this clock
+ * @clk: clock source
+ *
+ * Returns struct clk corresponding to parent clock source, or
+ * valid IS_ERR() condition containing errno.
+ */
+struct clk *clk_get_parent(struct clk *clk);
+
+/**
+ * clk_get_set_enable -
+ * -- get the clock.
+ * -- set the rate to @rate if @rate is non-zero
+ * -- enable the clock if @enable = ture;
+ * @id: clock identifier (char *)
+ * @rate: desired clock rate in Hz
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_get_set_enable(char *id, unsigned long rate, bool enable);
+
+struct clk_lookup {
+	const char		*con_id;
+	struct clk		*clk;
+};
+
+struct clk_list {
+	struct clk_lookup *clist;
+	unsigned num;
+};
+
+#define CLK_LOOKUP(con, c) { .con_id = con, .clk = &c }
+
+#ifdef DEBUG_CLOCK
+struct clk_list *clk_get_list(void);
+#endif
+
+#endif
diff --git a/platform/msm_shared/mipi_dsi.c b/platform/msm_shared/mipi_dsi.c
index 795dca7..1ffc144 100644
--- a/platform/msm_shared/mipi_dsi.c
+++ b/platform/msm_shared/mipi_dsi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -688,14 +688,14 @@
 	writel(0x13FF3BFF, DSI_ERR_INT_MASK0);
 #if DISPLAY_MIPI_PANEL_TOSHIBA_MDT61
 	/* Disable branch clocks */
-	writel(0x0, BYTE_CC_REG);
-	writel(0x0, PIXEL_CC_REG);
-	writel(0x0, ESC_CC_REG);
+	writel(0x0, DSI1_BYTE_CC_REG);
+	writel(0x0, DSI_PIXEL_CC_REG);
+	writel(0x0, DSI1_ESC_CC_REG);
 	/* Disable root clock */
 	writel(0x0, DSI_CC_REG);
 #elif (!DISPLAY_MIPI_PANEL_RENESAS)
 	secure_writel(0x0, DSI_CC_REG);
-	secure_writel(0x0, PIXEL_CC_REG);
+	secure_writel(0x0, DSI_PIXEL_CC_REG);
 #endif
 	writel(0, DSI_CLK_CTRL);
 	writel(0, DSI_CTRL);
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index 31b2b0d..a956480 100644
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -46,7 +46,9 @@
 			$(LOCAL_DIR)/certificate.o \
 			$(LOCAL_DIR)/image_verify.o \
 			$(LOCAL_DIR)/scm.o \
-			$(LOCAL_DIR)/interrupts.o
+			$(LOCAL_DIR)/interrupts.o \
+			$(LOCAL_DIR)/clock-local.o \
+			$(LOCAL_DIR)/clock.o
 endif
 
 ifeq ($(PLATFORM),msm7x27a)