msm: clock-9615: Add the MSM9615 clock driver

Signed-off-by: Vikram Mulukutla <markivx@codeaurora.org>
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 6c40fdc..5cd9974 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -203,6 +203,7 @@
 obj-$(CONFIG_MACH_MSM8960_FLUID) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
 obj-$(CONFIG_ARCH_MSM8960) += bms-batterydata.o
 obj-$(CONFIG_ARCH_APQ8064) += board-apq8064.o devices-8064.o board-apq8064-regulator.o
+obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o
 
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 4956f8e..0f7d01b 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4819,41 +4819,6 @@
 	rmwreg(0x2, DSI2_BYTE_NS_REG, 0x7);
 }
 
-static int wr_pll_clk_enable(struct clk *clk)
-{
-	u32 mode;
-	unsigned long flags;
-	struct pll_clk *pll = to_pll_clk(clk);
-
-	spin_lock_irqsave(&local_clock_reg_lock, flags);
-	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.
-	 */
-	mb();
-	udelay(10);
-
-	/* Disable PLL bypass mode. */
-	mode |= BIT(1);
-	writel_relaxed(mode, pll->mode_reg);
-
-	/* Wait until PLL is locked. */
-	mb();
-	udelay(60);
-
-	/* Enable PLL output. */
-	mode |= BIT(0);
-	writel_relaxed(mode, pll->mode_reg);
-
-	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
-	return 0;
-}
-
 struct clock_init_data msm8960_clock_init_data __initdata;
 
 /* Local clock driver initialization. */
@@ -4883,7 +4848,7 @@
 	soc_update_sys_vdd = msm8960_update_sys_vdd;
 	local_vote_sys_vdd(HIGH);
 
-	clk_ops_pll.enable = wr_pll_clk_enable;
+	clk_ops_pll.enable = sr_pll_clk_enable;
 
 	/* Initialize clock registers. */
 	reg_init();
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
new file mode 100644
index 0000000..0103f55
--- /dev/null
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -0,0 +1,1707 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+
+#include <asm/mach-types.h>
+
+#include <mach/msm_iomap.h>
+#include <mach/clk.h>
+#include <mach/msm_xo.h>
+
+#include "clock-local.h"
+#include "clock-voter.h"
+#include "devices.h"
+
+#define REG(off)	(MSM_CLK_CTL_BASE + (off))
+#define REG_LPA(off)	(MSM_LPASS_CLK_CTL_BASE + (off))
+#define REG_GCC(off)	(MSM_APCS_GCC_BASE + (off))
+
+/* Peripheral clock registers. */
+#define CE1_HCLK_CTL_REG			REG(0x2720)
+#define CE1_CORE_CLK_CTL_REG			REG(0x2724)
+#define DMA_BAM_HCLK_CTL			REG(0x25C0)
+#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_DFAB_STATE_REG			REG(0x2FC8)
+
+#define CLK_HALT_MSS_KPSS_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 PDM_CLK_NS_REG				REG(0x2CC0)
+#define BB_PLL_ENA_SC0_REG			REG(0x34C0)
+
+#define BB_PLL0_L_VAL_REG			REG(0x30C4)
+#define BB_PLL0_M_VAL_REG			REG(0x30C8)
+#define BB_PLL0_MODE_REG			REG(0x30C0)
+#define BB_PLL0_N_VAL_REG			REG(0x30CC)
+#define BB_PLL0_STATUS_REG			REG(0x30D8)
+#define BB_PLL0_CONFIG_REG			REG(0x30D4)
+#define BB_PLL0_TEST_CTL_REG			REG(0x30D0)
+
+#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_PLL14_L_VAL_REG			REG(0x31C4)
+#define BB_PLL14_M_VAL_REG			REG(0x31C8)
+#define BB_PLL14_MODE_REG			REG(0x31C0)
+#define BB_PLL14_N_VAL_REG			REG(0x31CC)
+#define BB_PLL14_STATUS_REG			REG(0x31D8)
+#define BB_PLL14_CONFIG_REG			REG(0x31D4)
+#define BB_PLL14_TEST_CTL_REG			REG(0x31D0)
+
+#define SC_PLL0_L_VAL_REG			REG(0x3208)
+#define SC_PLL0_M_VAL_REG			REG(0x320C)
+#define SC_PLL0_MODE_REG			REG(0x3200)
+#define SC_PLL0_N_VAL_REG			REG(0x3210)
+#define SC_PLL0_STATUS_REG			REG(0x321C)
+#define SC_PLL0_CONFIG_REG			REG(0x3204)
+#define SC_PLL0_TEST_CTL_REG			REG(0x3218)
+
+#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 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_HS1_SYS_CLK_MD_REG			REG(0x36A0)
+#define USB_HS1_SYS_CLK_NS_REG			REG(0x36A4)
+#define USB_HSIC_HCLK_CTL_REG			REG(0x2920)
+#define USB_HSIC_XCVR_FS_CLK_MD_REG		REG(0x2924)
+#define USB_HSIC_XCVR_FS_CLK_NS_REG		REG(0x2928)
+#define USB_HSIC_RESET_REG			REG(0x2934)
+#define USB_HSIC_HSIO_CAL_CLK_CTL_REG		REG(0x2B48)
+#define USB_HSIC_CLK_MD_REG			REG(0x2B4C)
+#define USB_HSIC_CLK_NS_REG			REG(0x2B50)
+#define USB_HSIC_SYSTEM_CLK_MD_REG		REG(0x2B54)
+#define USB_HSIC_SYSTEM_CLK_NS_REG		REG(0x2B58)
+#define SLIMBUS_XO_SRC_CLK_CTL_REG		REG(0x2628)
+
+/* Low-power Audio clock registers. */
+#define LCC_CLK_LS_DEBUG_CFG_REG		REG_LPA(0x00A8)
+#define LCC_CODEC_I2S_MIC_MD_REG		REG_LPA(0x0064)
+#define LCC_CODEC_I2S_MIC_NS_REG		REG_LPA(0x0060)
+#define LCC_CODEC_I2S_MIC_STATUS_REG		REG_LPA(0x0068)
+#define LCC_CODEC_I2S_SPKR_MD_REG		REG_LPA(0x0070)
+#define LCC_CODEC_I2S_SPKR_NS_REG		REG_LPA(0x006C)
+#define LCC_CODEC_I2S_SPKR_STATUS_REG		REG_LPA(0x0074)
+#define LCC_MI2S_MD_REG				REG_LPA(0x004C)
+#define LCC_MI2S_NS_REG				REG_LPA(0x0048)
+#define LCC_MI2S_STATUS_REG			REG_LPA(0x0050)
+#define LCC_PCM_MD_REG				REG_LPA(0x0058)
+#define LCC_PCM_NS_REG				REG_LPA(0x0054)
+#define LCC_PCM_STATUS_REG			REG_LPA(0x005C)
+#define LCC_PLL0_STATUS_REG			REG_LPA(0x0018)
+#define LCC_SPARE_I2S_MIC_MD_REG		REG_LPA(0x007C)
+#define LCC_SPARE_I2S_MIC_NS_REG		REG_LPA(0x0078)
+#define LCC_SPARE_I2S_MIC_STATUS_REG		REG_LPA(0x0080)
+#define LCC_SPARE_I2S_SPKR_MD_REG		REG_LPA(0x0088)
+#define LCC_SPARE_I2S_SPKR_NS_REG		REG_LPA(0x0084)
+#define LCC_SPARE_I2S_SPKR_STATUS_REG		REG_LPA(0x008C)
+#define LCC_SLIMBUS_NS_REG			REG_LPA(0x00CC)
+#define LCC_SLIMBUS_MD_REG			REG_LPA(0x00D0)
+#define LCC_SLIMBUS_STATUS_REG			REG_LPA(0x00D4)
+#define LCC_AHBEX_BRANCH_CTL_REG		REG_LPA(0x00E4)
+#define LCC_PRI_PLL_CLK_CTL_REG			REG_LPA(0x00C4)
+
+#define GCC_APCS_CLK_DIAG			REG_GCC(0x001C)
+
+/* MUX source input identifiers. */
+#define cxo_to_bb_mux		0
+#define pll8_to_bb_mux		3
+#define pll14_to_bb_mux		4
+#define gnd_to_bb_mux		6
+#define cxo_to_xo_mux		0
+#define gnd_to_xo_mux		3
+#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_LPA		5
+#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_LPA(s)		TEST_VECTOR((s), TEST_TYPE_LPA)
+
+#define MN_MODE_DUAL_EDGE 0x2
+
+/* MD Registers */
+#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_SRC_SEL(s_msb, s_lsb, s) \
+		BVAL(s_msb, s_lsb, s)
+
+
+/*
+ * Clock Descriptions
+ */
+
+static struct msm_xo_voter *xo_cxo;
+
+static int cxo_clk_enable(struct clk *clk)
+{
+	return msm_xo_mode_vote(xo_cxo, MSM_XO_MODE_ON);
+}
+
+static void cxo_clk_disable(struct clk *clk)
+{
+	msm_xo_mode_vote(xo_cxo, MSM_XO_MODE_OFF);
+}
+
+static struct clk_ops clk_ops_cxo = {
+	.enable = cxo_clk_enable,
+	.disable = cxo_clk_disable,
+	.get_rate = fixed_clk_get_rate,
+	.is_local = local_clk_is_local,
+};
+
+static struct fixed_clk cxo_clk = {
+	.rate = 19200000,
+	.c = {
+		.dbg_name = "cxo_clk",
+		.ops = &clk_ops_cxo,
+		CLK_INIT(cxo_clk.c),
+	},
+};
+
+static struct pll_vote_clk pll0_clk = {
+	.rate = 276000000,
+	.en_reg = BB_PLL_ENA_SC0_REG,
+	.en_mask = BIT(0),
+	.status_reg = BB_PLL0_STATUS_REG,
+	.parent = &cxo_clk.c,
+	.c = {
+		.dbg_name = "pll0_clk",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(pll0_clk.c),
+	},
+};
+
+static struct pll_vote_clk pll4_clk = {
+	.rate = 393216000,
+	.en_reg = BB_PLL_ENA_SC0_REG,
+	.en_mask = BIT(4),
+	.status_reg = LCC_PLL0_STATUS_REG,
+	.parent = &cxo_clk.c,
+	.c = {
+		.dbg_name = "pll4_clk",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(pll4_clk.c),
+	},
+};
+
+static struct pll_vote_clk pll8_clk = {
+	.rate = 384000000,
+	.en_reg = BB_PLL_ENA_SC0_REG,
+	.en_mask = BIT(8),
+	.status_reg = BB_PLL8_STATUS_REG,
+	.parent = &cxo_clk.c,
+	.c = {
+		.dbg_name = "pll8_clk",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(pll8_clk.c),
+	},
+};
+
+static struct pll_vote_clk pll9_clk = {
+	.rate = 440000000,
+	.en_reg = BB_PLL_ENA_SC0_REG,
+	.en_mask = BIT(9),
+	.status_reg = SC_PLL0_STATUS_REG,
+	.parent = &cxo_clk.c,
+	.c = {
+		.dbg_name = "pll9_clk",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(pll9_clk.c),
+	},
+};
+
+static struct pll_vote_clk pll14_clk = {
+	.rate = 480000000,
+	.en_reg = BB_PLL_ENA_SC0_REG,
+	.en_mask = BIT(11),
+	.status_reg = BB_PLL14_STATUS_REG,
+	.parent = &cxo_clk.c,
+	.c = {
+		.dbg_name = "pll14_clk",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(pll14_clk.c),
+	},
+};
+
+/*
+ * SoC-specific functions required by clock-local driver
+ */
+
+/* TODO: Update these voltages when info becomes available. */
+/* Update the sys_vdd voltage given a level. */
+static int msm9615_update_sys_vdd(enum sys_vdd_level level)
+{
+	/* TODO: Implement when rpm-regulator is ready.
+	static const int vdd_uv[] = {
+		[NONE...LOW] =  945000,
+		[NOMINAL]    = 1050000,
+		[HIGH]       = 1150000,
+	};
+
+	return rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S3, RPM_VREG_VOTER3,
+				    vdd_uv[level], vdd_uv[HIGH], 1);
+	*/
+	return 0;
+}
+
+static int soc_clk_reset(struct clk *clk, enum clk_reset_action action)
+{
+	return branch_reset(&to_rcg_clk(clk)->b, action);
+}
+
+static struct clk_ops clk_ops_rcg_9615 = {
+	.enable = rcg_clk_enable,
+	.disable = rcg_clk_disable,
+	.auto_off = rcg_clk_auto_off,
+	.set_rate = rcg_clk_set_rate,
+	.set_min_rate = rcg_clk_set_min_rate,
+	.get_rate = rcg_clk_get_rate,
+	.list_rate = rcg_clk_list_rate,
+	.is_enabled = rcg_clk_is_enabled,
+	.round_rate = rcg_clk_round_rate,
+	.reset = soc_clk_reset,
+	.is_local = local_clk_is_local,
+	.get_parent = rcg_clk_get_parent,
+};
+
+static struct clk_ops clk_ops_branch = {
+	.enable = branch_clk_enable,
+	.disable = branch_clk_disable,
+	.auto_off = branch_clk_auto_off,
+	.is_enabled = branch_clk_is_enabled,
+	.reset = branch_clk_reset,
+	.is_local = local_clk_is_local,
+	.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 = GSBIn_UART_APPS_NS_REG(n), \
+			.en_mask = BIT(9), \
+			.reset_reg = GSBIn_RESET_REG(n), \
+			.reset_mask = BIT(0), \
+			.halt_reg = h_r, \
+			.halt_bit = h_b, \
+		}, \
+		.ns_reg = GSBIn_UART_APPS_NS_REG(n), \
+		.md_reg = 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 = &rcg_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &clk_ops_rcg_9615, \
+			CLK_INIT(i##_clk.c), \
+		}, \
+	}
+#define F_GSBI_UART(f, s, d, m, n, v) \
+	{ \
+		.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), \
+		.sys_vdd = v, \
+	}
+static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
+	F_GSBI_UART(       0, gnd,  1,  0,   0, NONE),
+	F_GSBI_UART( 3686400, pll8, 1,  6, 625, LOW),
+	F_GSBI_UART( 7372800, pll8, 1, 12, 625, LOW),
+	F_GSBI_UART(14745600, pll8, 1, 24, 625, LOW),
+	F_GSBI_UART(16000000, pll8, 4,  1,   6, LOW),
+	F_GSBI_UART(24000000, pll8, 4,  1,   4, LOW),
+	F_GSBI_UART(32000000, pll8, 4,  1,   3, LOW),
+	F_GSBI_UART(40000000, pll8, 1,  5,  48, NOMINAL),
+	F_GSBI_UART(46400000, pll8, 1, 29, 240, NOMINAL),
+	F_GSBI_UART(48000000, pll8, 4,  1,   2, NOMINAL),
+	F_GSBI_UART(51200000, pll8, 1,  2,  15, NOMINAL),
+	F_GSBI_UART(56000000, pll8, 1,  7,  48, NOMINAL),
+	F_GSBI_UART(58982400, pll8, 1, 96, 625, NOMINAL),
+	F_GSBI_UART(64000000, pll8, 2,  1,   3, NOMINAL),
+	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);
+
+#define CLK_GSBI_QUP(i, n, h_r, h_b) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = GSBIn_QUP_APPS_NS_REG(n), \
+			.en_mask = BIT(9), \
+			.reset_reg = GSBIn_RESET_REG(n), \
+			.reset_mask = BIT(0), \
+			.halt_reg = h_r, \
+			.halt_bit = h_b, \
+		}, \
+		.ns_reg = GSBIn_QUP_APPS_NS_REG(n), \
+		.md_reg = 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 = &rcg_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &clk_ops_rcg_9615, \
+			CLK_INIT(i##_clk.c), \
+		}, \
+	}
+#define F_GSBI_QUP(f, s, d, m, n, v) \
+	{ \
+		.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), \
+		.sys_vdd = v, \
+	}
+static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
+	F_GSBI_QUP(       0, gnd,  1, 0,  0, NONE),
+	F_GSBI_QUP(  960000, cxo,  4, 1,  5, LOW),
+	F_GSBI_QUP( 4800000, cxo,  4, 0,  1, LOW),
+	F_GSBI_QUP( 9600000, cxo,  2, 0,  1, LOW),
+	F_GSBI_QUP(15058800, pll8, 1, 2, 51, LOW),
+	F_GSBI_QUP(24000000, pll8, 4, 1,  4, LOW),
+	F_GSBI_QUP(25600000, pll8, 1, 1, 15, NOMINAL),
+	F_GSBI_QUP(48000000, pll8, 4, 1,  2, NOMINAL),
+	F_GSBI_QUP(51200000, pll8, 1, 2, 15, NOMINAL),
+	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);
+
+#define F_PDM(f, s, d, v) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.ns_val = NS_SRC_SEL(1, 0, s##_to_xo_mux), \
+		.sys_vdd = v, \
+	}
+static struct clk_freq_tbl clk_tbl_pdm[] = {
+	F_PDM(       0, gnd, 1, NONE),
+	F_PDM(19200000, cxo, 1, LOW),
+	F_END
+};
+
+static struct rcg_clk pdm_clk = {
+	.b = {
+		.ctl_reg = PDM_CLK_NS_REG,
+		.en_mask = BIT(9),
+		.reset_reg = PDM_CLK_NS_REG,
+		.reset_mask = BIT(12),
+		.halt_reg = CLK_HALT_CFPB_STATEC_REG,
+		.halt_bit = 3,
+	},
+	.ns_reg = PDM_CLK_NS_REG,
+	.root_en_mask = BIT(11),
+	.ns_mask = BM(1, 0),
+	.set_rate = set_rate_nop,
+	.freq_tbl = clk_tbl_pdm,
+	.current_freq = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "pdm_clk",
+		.ops = &clk_ops_rcg_9615,
+		CLK_INIT(pdm_clk.c),
+	},
+};
+
+static struct branch_clk pmem_clk = {
+	.b = {
+		.ctl_reg = PMEM_ACLK_CTL_REG,
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 20,
+	},
+	.c = {
+		.dbg_name = "pmem_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(pmem_clk.c),
+	},
+};
+
+#define F_PRNG(f, s, v) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.sys_vdd = v, \
+	}
+static struct clk_freq_tbl clk_tbl_prng[] = {
+	F_PRNG(32000000, pll8, LOW),
+	F_END
+};
+
+static struct rcg_clk prng_clk = {
+	.b = {
+		.ctl_reg = SC0_U_CLK_BRANCH_ENA_VOTE_REG,
+		.en_mask = BIT(10),
+		.halt_reg = CLK_HALT_SFPB_MISC_STATE_REG,
+		.halt_check = HALT_VOTED,
+		.halt_bit = 10,
+	},
+	.set_rate = set_rate_nop,
+	.freq_tbl = clk_tbl_prng,
+	.current_freq = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "prng_clk",
+		.ops = &clk_ops_rcg_9615,
+		CLK_INIT(prng_clk.c),
+	},
+};
+
+#define CLK_SDC(name, n, h_b, f_table) \
+	struct rcg_clk name = { \
+		.b = { \
+			.ctl_reg = SDCn_APPS_CLK_NS_REG(n), \
+			.en_mask = BIT(9), \
+			.reset_reg = SDCn_RESET_REG(n), \
+			.reset_mask = BIT(0), \
+			.halt_reg = CLK_HALT_DFAB_STATE_REG, \
+			.halt_bit = h_b, \
+		}, \
+		.ns_reg = SDCn_APPS_CLK_NS_REG(n), \
+		.md_reg = 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 = f_table, \
+		.current_freq = &rcg_dummy_freq, \
+		.c = { \
+			.dbg_name = #name, \
+			.ops = &clk_ops_rcg_9615, \
+			CLK_INIT(name.c), \
+		}, \
+	}
+#define F_SDC(f, s, d, m, n, v) \
+	{ \
+		.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), \
+		.sys_vdd = v, \
+	}
+static struct clk_freq_tbl clk_tbl_sdc1_2[] = {
+	F_SDC(        0, gnd,   1, 0,   0, NONE),
+	F_SDC(   144300, cxo,   1, 1, 133, LOW),
+	F_SDC(   400000, pll8,  4, 1, 240, LOW),
+	F_SDC( 16000000, pll8,  4, 1,   6, LOW),
+	F_SDC( 17070000, pll8,  1, 2,  45, LOW),
+	F_SDC( 20210000, pll8,  1, 1,  19, LOW),
+	F_SDC( 24000000, pll8,  4, 1,   4, LOW),
+	F_SDC( 48000000, pll8,  4, 1,   2, NOMINAL),
+	F_END
+};
+
+static CLK_SDC(sdc1_clk, 1, 6, clk_tbl_sdc1_2);
+static CLK_SDC(sdc2_clk, 2, 5, clk_tbl_sdc1_2);
+
+#define F_USB(f, s, d, m, n, v) \
+	{ \
+		.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), \
+		.sys_vdd = v, \
+	}
+static struct clk_freq_tbl clk_tbl_usb[] = {
+	F_USB(       0, gnd,  1, 0,  0, NONE),
+	F_USB(60000000, pll8, 1, 5, 32, NOMINAL),
+	F_END
+};
+
+static struct rcg_clk usb_hs1_xcvr_clk = {
+	.b = {
+		.ctl_reg = USB_HS1_XCVR_FS_CLK_NS_REG,
+		.en_mask = BIT(9),
+		.reset_reg = USB_HS1_RESET_REG,
+		.reset_mask = BIT(0),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 0,
+	},
+	.ns_reg = USB_HS1_XCVR_FS_CLK_NS_REG,
+	.md_reg = 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 = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "usb_hs1_xcvr_clk",
+		.ops = &clk_ops_rcg_9615,
+		CLK_INIT(usb_hs1_xcvr_clk.c),
+	},
+};
+
+static struct rcg_clk usb_hs1_sys_clk = {
+	.b = {
+		.ctl_reg = USB_HS1_SYS_CLK_NS_REG,
+		.en_mask = BIT(9),
+		.reset_reg = USB_HS1_RESET_REG,
+		.reset_mask = BIT(0),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 4,
+	},
+	.ns_reg = USB_HS1_SYS_CLK_NS_REG,
+	.md_reg = USB_HS1_SYS_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 = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "usb_hs1_sys_clk",
+		.ops = &clk_ops_rcg_9615,
+		CLK_INIT(usb_hs1_sys_clk.c),
+	},
+};
+
+static struct rcg_clk usb_hsic_xcvr_clk = {
+	.b = {
+		.ctl_reg = USB_HSIC_XCVR_FS_CLK_NS_REG,
+		.en_mask = BIT(9),
+		.reset_reg = USB_HSIC_RESET_REG,
+		.reset_mask = BIT(0),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 9,
+	},
+	.ns_reg = USB_HSIC_XCVR_FS_CLK_NS_REG,
+	.md_reg = USB_HSIC_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 = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "usb_hsic_xcvr_clk",
+		.ops = &clk_ops_rcg_9615,
+		CLK_INIT(usb_hsic_xcvr_clk.c),
+	},
+};
+
+static struct rcg_clk usb_hsic_sys_clk = {
+	.b = {
+		.ctl_reg = USB_HSIC_SYSTEM_CLK_NS_REG,
+		.en_mask = BIT(9),
+		.reset_reg = USB_HSIC_RESET_REG,
+		.reset_mask = BIT(0),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 7,
+	},
+	.ns_reg = USB_HSIC_SYSTEM_CLK_NS_REG,
+	.md_reg = USB_HSIC_SYSTEM_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 = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "usb_hsic_sys_clk",
+		.ops = &clk_ops_rcg_9615,
+		CLK_INIT(usb_hsic_sys_clk.c),
+	},
+};
+
+static struct clk_freq_tbl clk_tbl_usb_hsic[] = {
+	F_USB(        0, gnd,   1, 0, 0, NONE),
+	F_USB(480000000, pll14, 1, 0, 1, NOMINAL),
+	F_END
+};
+
+static struct rcg_clk usb_hsic_clk = {
+	.b = {
+		.ctl_reg = USB_HSIC_CLK_NS_REG,
+		.en_mask = BIT(9),
+		.reset_reg = USB_HSIC_RESET_REG,
+		.reset_mask = BIT(0),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 7,
+	},
+	.ns_reg = USB_HSIC_CLK_NS_REG,
+	.md_reg = USB_HSIC_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_hsic,
+	.current_freq = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "usb_hsic_clk",
+		.ops = &clk_ops_rcg_9615,
+		CLK_INIT(usb_hsic_clk.c),
+	},
+};
+
+static struct branch_clk usb_hsic_hsio_cal_clk = {
+	.b = {
+		.ctl_reg = USB_HSIC_HSIO_CAL_CLK_CTL_REG,
+		.en_mask = BIT(0),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 8,
+	},
+	.parent = &cxo_clk.c,
+	.c = {
+		.dbg_name = "usb_hsic_hsio_cal_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(usb_hsic_hsio_cal_clk.c),
+	},
+};
+
+/* Fast Peripheral Bus Clocks */
+static struct branch_clk ce1_core_clk = {
+	.b = {
+		.ctl_reg = CE1_CORE_CLK_CTL_REG,
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_CFPB_STATEC_REG,
+		.halt_bit = 27,
+	},
+	.c = {
+		.dbg_name = "ce1_core_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(ce1_core_clk.c),
+	},
+};
+static struct branch_clk ce1_p_clk = {
+	.b = {
+		.ctl_reg = CE1_HCLK_CTL_REG,
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_CFPB_STATEC_REG,
+		.halt_bit = 1,
+	},
+	.c = {
+		.dbg_name = "ce1_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(ce1_p_clk.c),
+	},
+};
+
+static struct branch_clk dma_bam_p_clk = {
+	.b = {
+		.ctl_reg = DMA_BAM_HCLK_CTL,
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 12,
+	},
+	.c = {
+		.dbg_name = "dma_bam_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(dma_bam_p_clk.c),
+	},
+};
+
+static struct branch_clk gsbi1_p_clk = {
+	.b = {
+		.ctl_reg = GSBIn_HCLK_CTL_REG(1),
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_CFPB_STATEA_REG,
+		.halt_bit = 11,
+	},
+	.c = {
+		.dbg_name = "gsbi1_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gsbi1_p_clk.c),
+	},
+};
+
+static struct branch_clk gsbi2_p_clk = {
+	.b = {
+		.ctl_reg = GSBIn_HCLK_CTL_REG(2),
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_CFPB_STATEA_REG,
+		.halt_bit = 7,
+	},
+	.c = {
+		.dbg_name = "gsbi2_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gsbi2_p_clk.c),
+	},
+};
+
+static struct branch_clk gsbi3_p_clk = {
+	.b = {
+		.ctl_reg = GSBIn_HCLK_CTL_REG(3),
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_CFPB_STATEA_REG,
+		.halt_bit = 3,
+	},
+	.c = {
+		.dbg_name = "gsbi3_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gsbi3_p_clk.c),
+	},
+};
+
+static struct branch_clk gsbi4_p_clk = {
+	.b = {
+		.ctl_reg = GSBIn_HCLK_CTL_REG(4),
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_CFPB_STATEB_REG,
+		.halt_bit = 27,
+	},
+	.c = {
+		.dbg_name = "gsbi4_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gsbi4_p_clk.c),
+	},
+};
+
+static struct branch_clk gsbi5_p_clk = {
+	.b = {
+		.ctl_reg = GSBIn_HCLK_CTL_REG(5),
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_CFPB_STATEB_REG,
+		.halt_bit = 23,
+	},
+	.c = {
+		.dbg_name = "gsbi5_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gsbi5_p_clk.c),
+	},
+};
+
+static struct branch_clk usb_hs1_p_clk = {
+	.b = {
+		.ctl_reg = USB_HS1_HCLK_CTL_REG,
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 1,
+	},
+	.c = {
+		.dbg_name = "usb_hs1_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(usb_hs1_p_clk.c),
+	},
+};
+
+static struct branch_clk usb_hsic_p_clk = {
+	.b = {
+		.ctl_reg = USB_HSIC_HCLK_CTL_REG,
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 3,
+	},
+	.c = {
+		.dbg_name = "usb_hsic_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(usb_hsic_p_clk.c),
+	},
+};
+
+static struct branch_clk sdc1_p_clk = {
+	.b = {
+		.ctl_reg = SDCn_HCLK_CTL_REG(1),
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 11,
+	},
+	.c = {
+		.dbg_name = "sdc1_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(sdc1_p_clk.c),
+	},
+};
+
+static struct branch_clk sdc2_p_clk = {
+	.b = {
+		.ctl_reg = SDCn_HCLK_CTL_REG(2),
+		.en_mask = BIT(4),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 10,
+	},
+	.c = {
+		.dbg_name = "sdc2_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(sdc2_p_clk.c),
+	},
+};
+
+/* HW-Voteable Clocks */
+static struct branch_clk adm0_clk = {
+	.b = {
+		.ctl_reg = SC0_U_CLK_BRANCH_ENA_VOTE_REG,
+		.en_mask = BIT(2),
+		.halt_reg = CLK_HALT_MSS_KPSS_MISC_STATE_REG,
+		.halt_check = HALT_VOTED,
+		.halt_bit = 14,
+	},
+	.c = {
+		.dbg_name = "adm0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(adm0_clk.c),
+	},
+};
+
+static struct branch_clk adm0_p_clk = {
+	.b = {
+		.ctl_reg = SC0_U_CLK_BRANCH_ENA_VOTE_REG,
+		.en_mask = BIT(3),
+		.halt_reg = CLK_HALT_MSS_KPSS_MISC_STATE_REG,
+		.halt_check = HALT_VOTED,
+		.halt_bit = 13,
+	},
+	.c = {
+		.dbg_name = "adm0_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(adm0_p_clk.c),
+	},
+};
+
+static struct branch_clk pmic_arb0_p_clk = {
+	.b = {
+		.ctl_reg = SC0_U_CLK_BRANCH_ENA_VOTE_REG,
+		.en_mask = BIT(8),
+		.halt_reg = CLK_HALT_SFPB_MISC_STATE_REG,
+		.halt_check = HALT_VOTED,
+		.halt_bit = 22,
+	},
+	.c = {
+		.dbg_name = "pmic_arb0_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(pmic_arb0_p_clk.c),
+	},
+};
+
+static struct branch_clk pmic_arb1_p_clk = {
+	.b = {
+		.ctl_reg = SC0_U_CLK_BRANCH_ENA_VOTE_REG,
+		.en_mask = BIT(9),
+		.halt_reg = CLK_HALT_SFPB_MISC_STATE_REG,
+		.halt_check = HALT_VOTED,
+		.halt_bit = 21,
+	},
+	.c = {
+		.dbg_name = "pmic_arb1_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(pmic_arb1_p_clk.c),
+	},
+};
+
+static struct branch_clk pmic_ssbi2_clk = {
+	.b = {
+		.ctl_reg = SC0_U_CLK_BRANCH_ENA_VOTE_REG,
+		.en_mask = BIT(7),
+		.halt_reg = CLK_HALT_SFPB_MISC_STATE_REG,
+		.halt_check = HALT_VOTED,
+		.halt_bit = 23,
+	},
+	.c = {
+		.dbg_name = "pmic_ssbi2_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(pmic_ssbi2_clk.c),
+	},
+};
+
+static struct branch_clk rpm_msg_ram_p_clk = {
+	.b = {
+		.ctl_reg = SC0_U_CLK_BRANCH_ENA_VOTE_REG,
+		.en_mask = BIT(6),
+		.halt_reg = CLK_HALT_SFPB_MISC_STATE_REG,
+		.halt_check = HALT_VOTED,
+		.halt_bit = 12,
+	},
+	.c = {
+		.dbg_name = "rpm_msg_ram_p_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(rpm_msg_ram_p_clk.c),
+	},
+};
+
+/*
+ * Low Power Audio Clocks
+ */
+#define F_AIF_OSR(f, s, d, m, n, v) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.md_val = MD8(8, m, 0, n), \
+		.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
+		.mnd_en_mask = BIT(8) * !!(n), \
+		.sys_vdd = v, \
+	}
+static struct clk_freq_tbl clk_tbl_aif_osr[] = {
+	F_AIF_OSR(       0, gnd,  1, 0,   0, NONE),
+	F_AIF_OSR(  512000, pll4, 4, 1, 192, LOW),
+	F_AIF_OSR(  768000, pll4, 4, 1, 128, LOW),
+	F_AIF_OSR( 1024000, pll4, 4, 1,  96, LOW),
+	F_AIF_OSR( 1536000, pll4, 4, 1,  64, LOW),
+	F_AIF_OSR( 2048000, pll4, 4, 1,  48, LOW),
+	F_AIF_OSR( 3072000, pll4, 4, 1,  32, LOW),
+	F_AIF_OSR( 4096000, pll4, 4, 1,  24, LOW),
+	F_AIF_OSR( 6144000, pll4, 4, 1,  16, LOW),
+	F_AIF_OSR( 8192000, pll4, 4, 1,  12, LOW),
+	F_AIF_OSR(12288000, pll4, 4, 1,   8, LOW),
+	F_AIF_OSR(24576000, pll4, 4, 1,   4, LOW),
+	F_END
+};
+
+#define CLK_AIF_OSR(i, ns, md, h_r) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = ns, \
+			.en_mask = BIT(17), \
+			.reset_reg = ns, \
+			.reset_mask = BIT(19), \
+			.halt_reg = h_r, \
+			.halt_check = ENABLE, \
+			.halt_bit = 1, \
+		}, \
+		.ns_reg = ns, \
+		.md_reg = md, \
+		.root_en_mask = BIT(9), \
+		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.set_rate = set_rate_mnd, \
+		.freq_tbl = clk_tbl_aif_osr, \
+		.current_freq = &rcg_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &clk_ops_rcg_9615, \
+			CLK_INIT(i##_clk.c), \
+		}, \
+	}
+#define CLK_AIF_OSR_DIV(i, ns, md, h_r) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = ns, \
+			.en_mask = BIT(21), \
+			.reset_reg = ns, \
+			.reset_mask = BIT(23), \
+			.halt_reg = h_r, \
+			.halt_check = ENABLE, \
+			.halt_bit = 1, \
+		}, \
+		.ns_reg = ns, \
+		.md_reg = md, \
+		.root_en_mask = BIT(9), \
+		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.set_rate = set_rate_mnd, \
+		.freq_tbl = clk_tbl_aif_osr, \
+		.current_freq = &rcg_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &clk_ops_rcg_9615, \
+			CLK_INIT(i##_clk.c), \
+		}, \
+	}
+
+#define F_AIF_BIT(d, s) \
+	{ \
+		.freq_hz = d, \
+		.ns_val = (BVAL(14, 14, s) | BVAL(13, 10, (d-1))) \
+	}
+static struct clk_freq_tbl clk_tbl_aif_bit[] = {
+	F_AIF_BIT(0, 1),  /* Use external clock. */
+	F_AIF_BIT(1, 0),  F_AIF_BIT(2, 0),  F_AIF_BIT(3, 0),  F_AIF_BIT(4, 0),
+	F_AIF_BIT(5, 0),  F_AIF_BIT(6, 0),  F_AIF_BIT(7, 0),  F_AIF_BIT(8, 0),
+	F_AIF_BIT(9, 0),  F_AIF_BIT(10, 0), F_AIF_BIT(11, 0), F_AIF_BIT(12, 0),
+	F_AIF_BIT(13, 0), F_AIF_BIT(14, 0), F_AIF_BIT(15, 0), F_AIF_BIT(16, 0),
+	F_END
+};
+
+#define CLK_AIF_BIT(i, ns, h_r) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = ns, \
+			.en_mask = BIT(15), \
+			.halt_reg = h_r, \
+			.halt_check = DELAY, \
+		}, \
+		.ns_reg = ns, \
+		.ns_mask = BM(14, 10), \
+		.set_rate = set_rate_nop, \
+		.freq_tbl = clk_tbl_aif_bit, \
+		.current_freq = &rcg_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &clk_ops_rcg_9615, \
+			CLK_INIT(i##_clk.c), \
+		}, \
+	}
+
+#define F_AIF_BIT_D(d, s) \
+	{ \
+		.freq_hz = d, \
+		.ns_val = (BVAL(18, 18, s) | BVAL(17, 10, (d-1))) \
+	}
+static struct clk_freq_tbl clk_tbl_aif_bit_div[] = {
+	F_AIF_BIT_D(0, 1),  /* Use external clock. */
+	F_AIF_BIT_D(1, 0), F_AIF_BIT_D(2, 0), F_AIF_BIT_D(3, 0),
+	F_AIF_BIT_D(4, 0), F_AIF_BIT_D(5, 0), F_AIF_BIT_D(6, 0),
+	F_AIF_BIT_D(7, 0), F_AIF_BIT_D(8, 0), F_AIF_BIT_D(9, 0),
+	F_AIF_BIT_D(10, 0), F_AIF_BIT_D(11, 0), F_AIF_BIT_D(12, 0),
+	F_AIF_BIT_D(13, 0), F_AIF_BIT_D(14, 0), F_AIF_BIT_D(15, 0),
+	F_AIF_BIT_D(16, 0),
+	F_END
+};
+
+#define CLK_AIF_BIT_DIV(i, ns, h_r) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = ns, \
+			.en_mask = BIT(19), \
+			.halt_reg = h_r, \
+			.halt_check = ENABLE, \
+		}, \
+		.ns_reg = ns, \
+		.ns_mask = BM(18, 10), \
+		.set_rate = set_rate_nop, \
+		.freq_tbl = clk_tbl_aif_bit_div, \
+		.current_freq = &rcg_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &clk_ops_rcg_9615, \
+			CLK_INIT(i##_clk.c), \
+		}, \
+	}
+
+static CLK_AIF_OSR(mi2s_osr, LCC_MI2S_NS_REG, LCC_MI2S_MD_REG,
+		LCC_MI2S_STATUS_REG);
+static CLK_AIF_BIT(mi2s_bit, LCC_MI2S_NS_REG, LCC_MI2S_STATUS_REG);
+
+static CLK_AIF_OSR_DIV(codec_i2s_mic_osr, LCC_CODEC_I2S_MIC_NS_REG,
+		LCC_CODEC_I2S_MIC_MD_REG, LCC_CODEC_I2S_MIC_STATUS_REG);
+static CLK_AIF_BIT_DIV(codec_i2s_mic_bit, LCC_CODEC_I2S_MIC_NS_REG,
+		LCC_CODEC_I2S_MIC_STATUS_REG);
+
+static CLK_AIF_OSR_DIV(spare_i2s_mic_osr, LCC_SPARE_I2S_MIC_NS_REG,
+		LCC_SPARE_I2S_MIC_MD_REG, LCC_SPARE_I2S_MIC_STATUS_REG);
+static CLK_AIF_BIT_DIV(spare_i2s_mic_bit, LCC_SPARE_I2S_MIC_NS_REG,
+		LCC_SPARE_I2S_MIC_STATUS_REG);
+
+static CLK_AIF_OSR_DIV(codec_i2s_spkr_osr, LCC_CODEC_I2S_SPKR_NS_REG,
+		LCC_CODEC_I2S_SPKR_MD_REG, LCC_CODEC_I2S_SPKR_STATUS_REG);
+static CLK_AIF_BIT_DIV(codec_i2s_spkr_bit, LCC_CODEC_I2S_SPKR_NS_REG,
+		LCC_CODEC_I2S_SPKR_STATUS_REG);
+
+static CLK_AIF_OSR_DIV(spare_i2s_spkr_osr, LCC_SPARE_I2S_SPKR_NS_REG,
+		LCC_SPARE_I2S_SPKR_MD_REG, LCC_SPARE_I2S_SPKR_STATUS_REG);
+static CLK_AIF_BIT_DIV(spare_i2s_spkr_bit, LCC_SPARE_I2S_SPKR_NS_REG,
+		LCC_SPARE_I2S_SPKR_STATUS_REG);
+
+#define F_PCM(f, s, d, m, n, v) \
+	{ \
+		.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_lpa_mux), \
+		.mnd_en_mask = BIT(8) * !!(n), \
+		.sys_vdd = v, \
+	}
+static struct clk_freq_tbl clk_tbl_pcm[] = {
+	F_PCM(       0, gnd,  1, 0,   0, NONE),
+	F_PCM(  512000, pll4, 4, 1, 192, LOW),
+	F_PCM(  768000, pll4, 4, 1, 128, LOW),
+	F_PCM( 1024000, pll4, 4, 1,  96, LOW),
+	F_PCM( 1536000, pll4, 4, 1,  64, LOW),
+	F_PCM( 2048000, pll4, 4, 1,  48, LOW),
+	F_PCM( 3072000, pll4, 4, 1,  32, LOW),
+	F_PCM( 4096000, pll4, 4, 1,  24, LOW),
+	F_PCM( 6144000, pll4, 4, 1,  16, LOW),
+	F_PCM( 8192000, pll4, 4, 1,  12, LOW),
+	F_PCM(12288000, pll4, 4, 1,   8, LOW),
+	F_PCM(24576000, pll4, 4, 1,   4, LOW),
+	F_END
+};
+
+static struct rcg_clk pcm_clk = {
+	.b = {
+		.ctl_reg = LCC_PCM_NS_REG,
+		.en_mask = BIT(11),
+		.reset_reg = LCC_PCM_NS_REG,
+		.reset_mask = BIT(13),
+		.halt_reg = LCC_PCM_STATUS_REG,
+		.halt_check = ENABLE,
+		.halt_bit = 0,
+	},
+	.ns_reg = LCC_PCM_NS_REG,
+	.md_reg = LCC_PCM_MD_REG,
+	.root_en_mask = BIT(9),
+	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.set_rate = set_rate_mnd,
+	.freq_tbl = clk_tbl_pcm,
+	.current_freq = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "pcm_clk",
+		.ops = &clk_ops_rcg_9615,
+		CLK_INIT(pcm_clk.c),
+	},
+};
+
+static struct rcg_clk audio_slimbus_clk = {
+	.b = {
+		.ctl_reg = LCC_SLIMBUS_NS_REG,
+		.en_mask = BIT(10),
+		.reset_reg = LCC_AHBEX_BRANCH_CTL_REG,
+		.reset_mask = BIT(5),
+		.halt_reg = LCC_SLIMBUS_STATUS_REG,
+		.halt_check = ENABLE,
+		.halt_bit = 0,
+	},
+	.ns_reg = LCC_SLIMBUS_NS_REG,
+	.md_reg = LCC_SLIMBUS_MD_REG,
+	.root_en_mask = BIT(9),
+	.ns_mask = (BM(31, 24) | BM(6, 0)),
+	.set_rate = set_rate_mnd,
+	.freq_tbl = clk_tbl_aif_osr,
+	.current_freq = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "audio_slimbus_clk",
+		.ops = &clk_ops_rcg_9615,
+		CLK_INIT(audio_slimbus_clk.c),
+	},
+};
+
+static struct branch_clk sps_slimbus_clk = {
+	.b = {
+		.ctl_reg = LCC_SLIMBUS_NS_REG,
+		.en_mask = BIT(12),
+		.halt_reg = LCC_SLIMBUS_STATUS_REG,
+		.halt_check = ENABLE,
+		.halt_bit = 1,
+	},
+	.parent = &audio_slimbus_clk.c,
+	.c = {
+		.dbg_name = "sps_slimbus_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(sps_slimbus_clk.c),
+	},
+};
+
+static struct branch_clk slimbus_xo_src_clk = {
+	.b = {
+		.ctl_reg = SLIMBUS_XO_SRC_CLK_CTL_REG,
+		.en_mask = BIT(2),
+		.halt_reg = CLK_HALT_DFAB_STATE_REG,
+		.halt_bit = 28,
+	},
+	.parent = &sps_slimbus_clk.c,
+	.c = {
+		.dbg_name = "slimbus_xo_src_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(slimbus_xo_src_clk.c),
+	},
+};
+
+static DEFINE_CLK_VOTER(dfab_usb_hs_clk, &dummy_clk);
+static DEFINE_CLK_VOTER(dfab_sdc1_clk, &dummy_clk);
+static DEFINE_CLK_VOTER(dfab_sdc2_clk, &dummy_clk);
+static DEFINE_CLK_VOTER(dfab_sps_clk, &dummy_clk);
+static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &dummy_clk);
+
+/*
+ * TODO: replace dummy_clk below with ebi1_clk.c once the
+ * bus driver starts voting on ebi1 rates.
+ */
+static DEFINE_CLK_VOTER(ebi1_adm_clk,    &dummy_clk);
+
+#ifdef CONFIG_DEBUG_FS
+struct measure_sel {
+	u32 test_vector;
+	struct clk *clk;
+};
+
+static struct measure_sel measure_mux[] = {
+	{ TEST_PER_LS(0x08), &slimbus_xo_src_clk.c },
+	{ TEST_PER_LS(0x12), &sdc1_p_clk.c },
+	{ TEST_PER_LS(0x13), &sdc1_clk.c },
+	{ TEST_PER_LS(0x14), &sdc2_p_clk.c },
+	{ TEST_PER_LS(0x15), &sdc2_clk.c },
+	{ TEST_PER_LS(0x26), &pmem_clk.c },
+	{ TEST_PER_LS(0x32), &dma_bam_p_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(0x7A), &pmic_ssbi2_clk.c },
+	{ TEST_PER_LS(0x7B), &pmic_arb0_p_clk.c },
+	{ TEST_PER_LS(0x7C), &pmic_arb1_p_clk.c },
+	{ TEST_PER_LS(0x7D), &prng_clk.c },
+	{ TEST_PER_LS(0x7F), &rpm_msg_ram_p_clk.c },
+	{ TEST_PER_LS(0x80), &adm0_p_clk.c },
+	{ TEST_PER_LS(0x84), &usb_hs1_p_clk.c },
+	{ TEST_PER_LS(0x85), &usb_hs1_xcvr_clk.c },
+	{ TEST_PER_LS(0x86), &usb_hsic_sys_clk.c },
+	{ TEST_PER_LS(0x87), &usb_hsic_p_clk.c },
+	{ TEST_PER_LS(0x88), &usb_hsic_xcvr_clk.c },
+	{ TEST_PER_LS(0x8B), &usb_hsic_hsio_cal_clk.c },
+	{ TEST_PER_LS(0x8D), &usb_hs1_sys_clk.c },
+	{ TEST_PER_LS(0x92), &ce1_p_clk.c },
+	{ TEST_PER_LS(0xA4), &ce1_core_clk.c },
+	{ TEST_PER_HS(0x2A), &adm0_clk.c },
+	{ TEST_LPA(0x0F), &mi2s_bit_clk.c },
+	{ TEST_LPA(0x10), &codec_i2s_mic_bit_clk.c },
+	{ TEST_LPA(0x11), &codec_i2s_spkr_bit_clk.c },
+	{ TEST_LPA(0x12), &spare_i2s_mic_bit_clk.c },
+	{ TEST_LPA(0x13), &spare_i2s_spkr_bit_clk.c },
+	{ TEST_LPA(0x14), &pcm_clk.c },
+	{ TEST_LPA(0x1D), &audio_slimbus_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;
+	u32 clk_sel;
+	struct measure_sel *p;
+	struct measure_clk *clk = to_measure_clk(c);
+	unsigned long flags;
+
+	if (!parent)
+		return -EINVAL;
+
+	p = find_measure_sel(parent);
+	if (!p)
+		return -EINVAL;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+	/*
+	 * 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_LPA:
+		writel_relaxed(0x4030D98, CLK_TEST_REG);
+		writel_relaxed(BVAL(6, 1, clk_sel)|BIT(0),
+				LCC_CLK_LS_DEBUG_CFG_REG);
+		break;
+	default:
+		ret = -EPERM;
+	}
+	/* Make sure test vector is set before starting measurements. */
+	mb();
+
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	return ret;
+}
+
+/* Sample clock for 'ticks' reference clock ticks. */
+static u32 run_measurement(unsigned ticks)
+{
+	/* Stop counters and set the XO4 counter start value. */
+	writel_relaxed(0x0, RINGOSC_TCXO_CTL_REG);
+	writel_relaxed(ticks, RINGOSC_TCXO_CTL_REG);
+
+	/* Wait for timer to become ready. */
+	while ((readl_relaxed(RINGOSC_STATUS_REG) & BIT(25)) != 0)
+		cpu_relax();
+
+	/* Run measurement and wait for completion. */
+	writel_relaxed(BIT(28)|ticks, RINGOSC_TCXO_CTL_REG);
+	while ((readl_relaxed(RINGOSC_STATUS_REG) & BIT(25)) == 0)
+		cpu_relax();
+
+	/* 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 measure_clk_get_rate(struct clk *c)
+{
+	unsigned long flags;
+	u32 pdm_reg_backup, ringosc_reg_backup;
+	u64 raw_count_short, raw_count_full;
+	struct measure_clk *clk = to_measure_clk(c);
+	unsigned ret;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+	/* 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;
+		do_div(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);
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	return ret;
+}
+#else /* !CONFIG_DEBUG_FS */
+static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	return -EINVAL;
+}
+
+static unsigned measure_clk_get_rate(struct clk *clk)
+{
+	return 0;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static struct clk_ops measure_clk_ops = {
+	.set_parent = measure_clk_set_parent,
+	.get_rate = measure_clk_get_rate,
+	.is_local = local_clk_is_local,
+};
+
+static struct measure_clk measure_clk = {
+	.c = {
+		.dbg_name = "measure_clk",
+		.ops = &measure_clk_ops,
+		CLK_INIT(measure_clk.c),
+	},
+	.multiplier = 1,
+};
+
+static struct clk_lookup msm_clocks_9615[] = {
+	CLK_LOOKUP("cxo",	cxo_clk.c,	NULL),
+	CLK_LOOKUP("pll0",	pll0_clk.c,	NULL),
+	CLK_LOOKUP("pll8",	pll8_clk.c,	NULL),
+	CLK_LOOKUP("pll9",	pll9_clk.c,	NULL),
+	CLK_LOOKUP("pll14",	pll14_clk.c,	NULL),
+	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
+
+	/* TODO: Make these real when the RPM driver's ready. */
+	CLK_DUMMY("cfpb_clk",		cfpb_clk.c,	NULL, OFF),
+	CLK_DUMMY("cfpb_a_clk",		cfpb_a_clk.c,	NULL, OFF),
+	CLK_DUMMY("dfab_clk",		dfab_clk.c,	NULL, OFF),
+	CLK_DUMMY("dfab_a_clk",		dfab_a_clk.c,	NULL, OFF),
+	CLK_DUMMY("ebi1_clk",		ebi1_clk.c,	NULL, OFF),
+	CLK_DUMMY("ebi1_a_clk",		ebi1_a_clk.c,	NULL, OFF),
+	CLK_DUMMY("sfab_clk",		sfab_clk.c,	NULL, OFF),
+	CLK_DUMMY("sfab_a_clk",		sfab_a_clk.c,	NULL, OFF),
+	CLK_DUMMY("sfpb_clk",		sfpb_clk.c,	NULL, OFF),
+	CLK_DUMMY("sfpb_a_clk",		sfpb_a_clk.c,	NULL, OFF),
+
+	CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, NULL),
+	CLK_LOOKUP("core_clk", gsbi2_uart_clk.c, NULL),
+	CLK_LOOKUP("core_clk", gsbi3_uart_clk.c, NULL),
+	CLK_LOOKUP("core_clk", gsbi4_uart_clk.c, "msm_serial_hsl.0"),
+	CLK_LOOKUP("core_clk", gsbi5_uart_clk.c, NULL),
+
+	CLK_LOOKUP("core_clk",	gsbi1_qup_clk.c, NULL),
+	CLK_LOOKUP("core_clk",	gsbi2_qup_clk.c, NULL),
+	CLK_LOOKUP("core_clk",	gsbi3_qup_clk.c, NULL),
+	CLK_LOOKUP("core_clk",	gsbi4_qup_clk.c, NULL),
+	CLK_LOOKUP("core_clk",	gsbi5_qup_clk.c, NULL),
+
+	CLK_LOOKUP("pdm_clk",		pdm_clk.c,		NULL),
+	CLK_LOOKUP("pmem_clk",		pmem_clk.c,		NULL),
+	CLK_LOOKUP("prng_clk",		prng_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		sdc1_clk.c,		"msm_sdcc.1"),
+	CLK_LOOKUP("core_clk",		sdc2_clk.c,		"msm_sdcc.2"),
+	CLK_LOOKUP("ce_pclk",		ce1_p_clk.c,		NULL),
+	CLK_LOOKUP("ce_clk",		ce1_core_clk.c,		NULL),
+	CLK_LOOKUP("dma_bam_pclk",	dma_bam_p_clk.c,	NULL),
+
+	CLK_LOOKUP("iface_clk",	gsbi1_p_clk.c, NULL),
+	CLK_LOOKUP("iface_clk",	gsbi2_p_clk.c, NULL),
+	CLK_LOOKUP("iface_clk",	gsbi3_p_clk.c, NULL),
+	CLK_LOOKUP("iface_clk",	gsbi4_p_clk.c, "msm_serial_hsl.0"),
+	CLK_LOOKUP("iface_clk",	gsbi5_p_clk.c, NULL),
+
+	CLK_LOOKUP("usb_hs_pclk",		usb_hs1_p_clk.c,	NULL),
+	CLK_LOOKUP("usb_hs_system_clk",		usb_hs1_sys_clk.c,	NULL),
+	CLK_LOOKUP("usb_hs_clk",		usb_hs1_xcvr_clk.c,	NULL),
+	CLK_LOOKUP("usb_hsic_xcvr_clk",		usb_hsic_xcvr_clk.c,	NULL),
+	CLK_LOOKUP("usb_hsic_hsio_cal_clk", usb_hsic_hsio_cal_clk.c,	NULL),
+	CLK_LOOKUP("usb_hsic_sys_clk",		usb_hsic_sys_clk.c,	NULL),
+	CLK_LOOKUP("usb_hsic_p_clk",		usb_hsic_p_clk.c,	NULL),
+
+	CLK_LOOKUP("iface_clk",		sdc1_p_clk.c,		"msm_sdcc.1"),
+	CLK_LOOKUP("iface_clk",		sdc2_p_clk.c,		"msm_sdcc.2"),
+	CLK_LOOKUP("core_clk",		adm0_clk.c,		"msm_dmov"),
+	CLK_LOOKUP("iface_clk",		adm0_p_clk.c,		"msm_dmov"),
+	CLK_LOOKUP("pmic_arb_pclk",	pmic_arb0_p_clk.c,	NULL),
+	CLK_LOOKUP("pmic_arb_pclk",	pmic_arb1_p_clk.c,	NULL),
+	CLK_LOOKUP("pmic_ssbi2",	pmic_ssbi2_clk.c,	NULL),
+	CLK_LOOKUP("rpm_msg_ram_pclk",	rpm_msg_ram_p_clk.c,	NULL),
+	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		NULL),
+	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		NULL),
+
+	CLK_LOOKUP("i2s_mic_bit_clk",	codec_i2s_mic_bit_clk.c,	NULL),
+	CLK_LOOKUP("i2s_mic_osr_clk",	codec_i2s_mic_osr_clk.c,	NULL),
+	CLK_LOOKUP("i2s_mic_bit_clk",	spare_i2s_mic_bit_clk.c,	NULL),
+	CLK_LOOKUP("i2s_mic_osr_clk",	spare_i2s_mic_osr_clk.c,	NULL),
+	CLK_LOOKUP("i2s_spkr_bit_clk",	codec_i2s_spkr_bit_clk.c,	NULL),
+	CLK_LOOKUP("i2s_spkr_osr_clk",	codec_i2s_spkr_osr_clk.c,	NULL),
+	CLK_LOOKUP("i2s_spkr_bit_clk",	spare_i2s_spkr_bit_clk.c,	NULL),
+	CLK_LOOKUP("i2s_spkr_osr_clk",	spare_i2s_spkr_osr_clk.c,	NULL),
+	CLK_LOOKUP("pcm_clk",		pcm_clk.c,			NULL),
+
+	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	NULL),
+	CLK_LOOKUP("audio_slimbus_clk",	audio_slimbus_clk.c,	NULL),
+	CLK_LOOKUP("dfab_usb_hs_clk",	dfab_usb_hs_clk.c,	NULL),
+	CLK_LOOKUP("bus_clk",		dfab_sdc1_clk.c,	"msm_sdcc.1"),
+	CLK_LOOKUP("bus_clk",		dfab_sdc2_clk.c,	"msm_sdcc.2"),
+	CLK_LOOKUP("dfab_clk",		dfab_sps_clk.c,		"msm_sps"),
+
+	/* TODO: Make this real when RPM's ready. */
+	CLK_DUMMY("ebi1_msmbus_clk",	ebi1_msmbus_clk.c, NULL, OFF),
+	CLK_DUMMY("mem_clk",		ebi1_adm_clk.c, "msm_dmov", OFF),
+
+};
+
+static void set_fsm_mode(void __iomem *mode_reg)
+{
+	u32 regval = readl_relaxed(mode_reg);
+
+	/* De-assert reset to FSM */
+	regval &= ~BIT(21);
+	writel_relaxed(regval, mode_reg);
+
+	/* Program bias count */
+	regval &= ~BM(19, 14);
+	regval |= BVAL(19, 14, 0x4);
+	writel_relaxed(regval, mode_reg);
+
+	/* Program lock count */
+	regval &= ~BM(13, 8);
+	regval |= BVAL(13, 8, 0x8);
+	writel_relaxed(regval, mode_reg);
+
+	/* Enable PLL FSM voting */
+	regval |= BIT(20);
+	writel_relaxed(regval, mode_reg);
+}
+
+/*
+ * Miscellaneous clock register initializations
+ */
+static void __init reg_init(void)
+{
+	u32 regval, is_pll_enabled;
+
+	/* Enable PDM CXO source. */
+	regval = readl_relaxed(PDM_CLK_NS_REG);
+	writel_relaxed(BIT(13) | regval, PDM_CLK_NS_REG);
+
+	/* Check if PLL0 is active */
+	is_pll_enabled = readl_relaxed(BB_PLL0_STATUS_REG) & BIT(16);
+
+	if (!is_pll_enabled) {
+		writel_relaxed(0xE, BB_PLL0_L_VAL_REG);
+		writel_relaxed(0x3, BB_PLL0_M_VAL_REG);
+		writel_relaxed(0x8, BB_PLL0_N_VAL_REG);
+
+		regval = readl_relaxed(BB_PLL0_CONFIG_REG);
+
+		/* Enable the main output and the MN accumulator  */
+		regval |= BIT(23) | BIT(22);
+
+		/* Set pre-divider and post-divider values to 1 and 1 */
+		regval &= ~BIT(19);
+		regval &= ~BM(21, 20);
+
+		/* Set VCO frequency */
+		regval &= ~BM(17, 16);
+
+		writel_relaxed(regval, BB_PLL0_CONFIG_REG);
+
+		/* Enable AUX output */
+		regval = readl_relaxed(BB_PLL0_TEST_CTL_REG);
+		regval |= BIT(12);
+		writel_relaxed(regval, BB_PLL0_TEST_CTL_REG);
+
+		set_fsm_mode(BB_PLL0_MODE_REG);
+	}
+
+	/* Check if PLL9 (SC_PLL0) is enabled in FSM mode */
+	is_pll_enabled  = readl_relaxed(SC_PLL0_STATUS_REG) & BIT(16);
+
+	if (!is_pll_enabled) {
+		writel_relaxed(0x16, SC_PLL0_L_VAL_REG);
+		writel_relaxed(0xB, SC_PLL0_M_VAL_REG);
+		writel_relaxed(0xC, SC_PLL0_N_VAL_REG);
+
+		regval = readl_relaxed(SC_PLL0_CONFIG_REG);
+
+		/* Enable main output and the MN accumulator */
+		regval |= BIT(23) | BIT(22);
+
+		/* Set pre-divider and post-divider values to 1 and 1 */
+		regval &= ~BIT(19);
+		regval &= ~BM(21, 20);
+
+		/* Set VCO frequency */
+		regval &= ~BM(17, 16);
+
+		writel_relaxed(regval, SC_PLL0_CONFIG_REG);
+
+		set_fsm_mode(SC_PLL0_MODE_REG);
+
+	} else if (readl_relaxed(SC_PLL0_MODE_REG) & BIT(20))
+		WARN(1, "PLL9 enabled in non-FSM mode!\n");
+
+	/* Enable PLL4 source on the LPASS Primary PLL Mux */
+	regval = readl_relaxed(LCC_PRI_PLL_CLK_CTL_REG);
+	writel_relaxed(regval | BIT(0), LCC_PRI_PLL_CLK_CTL_REG);
+}
+
+/* Local clock driver initialization. */
+static void __init msm9615_clock_init(void)
+{
+	xo_cxo = msm_xo_get(MSM_XO_TCXO_D0, "clock-9615");
+	if (IS_ERR(xo_cxo)) {
+		pr_err("%s: msm_xo_get(CXO) failed.\n", __func__);
+		BUG();
+	}
+
+	soc_update_sys_vdd = msm9615_update_sys_vdd;
+	local_vote_sys_vdd(HIGH);
+
+	clk_ops_pll.enable = sr_pll_clk_enable;
+
+	/* Initialize clock registers. */
+	reg_init();
+
+	/* Initialize rates for clocks that only support one. */
+	clk_set_rate(&pdm_clk.c, 19200000);
+	clk_set_rate(&prng_clk.c, 32000000);
+	clk_set_rate(&usb_hs1_xcvr_clk.c, 60000000);
+	clk_set_rate(&usb_hs1_sys_clk.c, 60000000);
+	clk_set_rate(&usb_hsic_xcvr_clk.c, 60000000);
+	clk_set_rate(&usb_hsic_sys_clk.c, 60000000);
+	clk_set_rate(&usb_hsic_clk.c, 48000000);
+
+	/*
+	 * The halt status bits for PDM may be incorrect at boot.
+	 * Toggle these clocks on and off to refresh them.
+	*/
+	rcg_clk_enable(&pdm_clk.c);
+	rcg_clk_disable(&pdm_clk.c);
+}
+
+static int __init msm9615_clock_late_init(void)
+{
+	return local_unvote_sys_vdd(HIGH);
+}
+
+struct clock_init_data msm9615_clock_init_data __initdata = {
+	.table = msm_clocks_9615,
+	.size = ARRAY_SIZE(msm_clocks_9615),
+	.init = msm9615_clock_init,
+	.late_init = msm9615_clock_late_init,
+};
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 738eacc..cf75900 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -876,6 +876,41 @@
 	return pll->parent;
 }
 
+int sr_pll_clk_enable(struct clk *clk)
+{
+	u32 mode;
+	unsigned long flags;
+	struct pll_clk *pll = to_pll_clk(clk);
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	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.
+	 */
+	mb();
+	udelay(10);
+
+	/* Disable PLL bypass mode. */
+	mode |= BIT(1);
+	writel_relaxed(mode, pll->mode_reg);
+
+	/* Wait until PLL is locked. */
+	mb();
+	udelay(60);
+
+	/* Enable PLL output. */
+	mode |= BIT(0);
+	writel_relaxed(mode, pll->mode_reg);
+
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+	return 0;
+}
+
 struct clk_ops clk_ops_pll = {
 	.enable = pll_clk_enable,
 	.disable = pll_clk_disable,
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 9af2ee9..8448d07 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -240,6 +240,8 @@
 	return container_of(clk, struct pll_clk, c);
 }
 
+int sr_pll_clk_enable(struct clk *clk);
+
 /**
  * struct branch_clk - branch
  * @enabled: true if clock is on, false otherwise
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 89775b4..44836be 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -90,6 +90,7 @@
 	int (*late_init)(void);
 };
 
+extern struct clock_init_data msm9615_clock_init_data;
 extern struct clock_init_data apq8064_dummy_clock_init_data;
 extern struct clock_init_data fsm9xxx_clock_init_data;
 extern struct clock_init_data msm7x01a_clock_init_data;
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index b255f3c..2ee35c0 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -27,6 +27,7 @@
 	if (socinfo_init() < 0)
 		pr_err("socinfo_init() failed!\n");
 
+	msm_clock_init(&msm9615_clock_init_data);
 }
 
 void __init msm9615_map_io(void)
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9615.h b/arch/arm/mach-msm/include/mach/msm_iomap-9615.h
index b54924a..9f14e88 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9615.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9615.h
@@ -59,4 +59,13 @@
 #define MSM9615_TCSR_PHYS		0x1A400000
 #define MSM9615_TCSR_SIZE		SZ_4K
 
+#define MSM9615_L2CC_PHYS		0x02040000
+#define MSM9615_L2CC_SIZE		SZ_4K
+
+#define MSM9615_CLK_CTL_PHYS            0x00900000
+#define MSM9615_CLK_CTL_SIZE            SZ_16K
+
+#define MSM9615_LPASS_CLK_CTL_PHYS      0x28000000
+#define MSM9615_LPASS_CLK_CTL_SIZE      SZ_4K
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index fde3ede..976199c 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -73,6 +73,7 @@
 #define MSM_RPM_BASE		IOMEM(0xFA801000)	/*  4K	*/
 #define MSM_RPM_MPM_BASE	IOMEM(0xFA802000)	/*  4K	*/
 #define MSM_QFPROM_BASE		IOMEM(0xFA700000)	/*  4K  */
+#define MSM_L2CC_BASE		IOMEM(0xFA701000)	/* 4K */
 
 #define MSM_SHARED_RAM_SIZE	SZ_2M
 
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 6288145..f4b981c 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -318,6 +318,9 @@
 	MSM_CHIP_DEVICE(SAW0, MSM9615),
 	MSM_CHIP_DEVICE(APCS_GCC, MSM9615),
 	MSM_CHIP_DEVICE(TCSR, MSM9615),
+	MSM_CHIP_DEVICE(L2CC, MSM9615),
+	MSM_CHIP_DEVICE(CLK_CTL, MSM9615),
+	MSM_CHIP_DEVICE(LPASS_CLK_CTL, MSM9615),
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
 		.length =   MSM_SHARED_RAM_SIZE,