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)