msm: clock-local2: Move display clock support
Move the display ops to a common file so they may be reused by multiple
targets.
Change-Id: Ica485980b9348e23ec1d54fb563b73f9b9343455
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 4cef377..3587df6 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -3030,134 +3030,6 @@
.src_clk = &dsipll0_byte_clk_src,
.div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
};
-static struct clk_freq_tbl pixel_freq = {
- .src_clk = &dsipll0_pixel_clk_src,
- .div_src_val = BVAL(10, 8, dsipll0_pixel_mm_source_val),
-};
-static struct clk_ops clk_ops_byte;
-static struct clk_ops clk_ops_pixel;
-
-#define CFG_RCGR_DIV_MASK BM(4, 0)
-#define CMD_RCGR_REG(x) (*(x)->base + (x)->cmd_rcgr_reg + 0x0)
-#define CFG_RCGR_REG(x) (*(x)->base + (x)->cmd_rcgr_reg + 0x4)
-#define M_REG(x) (*(x)->base + (x)->cmd_rcgr_reg + 0x8)
-#define N_REG(x) (*(x)->base + (x)->cmd_rcgr_reg + 0xC)
-#define MND_MODE_MASK BM(13, 12)
-#define MND_DUAL_EDGE_MODE_BVAL BVAL(13, 12, 0x2)
-#define CFG_RCGR_SRC_SEL_MASK BM(10, 8)
-#define CMD_RCGR_ROOT_STATUS_BIT BIT(31)
-
-static enum handoff byte_rcg_handoff(struct clk *clk)
-{
- struct rcg_clk *rcg = to_rcg_clk(clk);
- u32 div_val;
- unsigned long pre_div_rate, parent_rate = clk_get_rate(clk->parent);
-
- /* If the pre-divider is used, find the rate after the division */
- div_val = readl_relaxed(CFG_RCGR_REG(rcg)) & CFG_RCGR_DIV_MASK;
- if (div_val > 1)
- pre_div_rate = parent_rate / ((div_val + 1) >> 1);
- else
- pre_div_rate = parent_rate;
-
- clk->rate = pre_div_rate;
-
- if (readl_relaxed(CMD_RCGR_REG(rcg)) & CMD_RCGR_ROOT_STATUS_BIT)
- return HANDOFF_DISABLED_CLK;
-
- return HANDOFF_ENABLED_CLK;
-}
-
-static int set_rate_byte(struct clk *clk, unsigned long rate)
-{
- struct rcg_clk *rcg = to_rcg_clk(clk);
- struct clk *pll = clk->parent;
- unsigned long source_rate, div;
- int rc;
-
- if (rate == 0)
- return -EINVAL;
-
- rc = clk_set_rate(pll, rate);
- if (rc)
- return rc;
-
- source_rate = clk_round_rate(pll, rate);
- if ((2 * source_rate) % rate)
- return -EINVAL;
-
- div = ((2 * source_rate)/rate) - 1;
- if (div > CFG_RCGR_DIV_MASK)
- return -EINVAL;
-
- byte_freq.div_src_val &= ~CFG_RCGR_DIV_MASK;
- byte_freq.div_src_val |= BVAL(4, 0, div);
- set_rate_hid(rcg, &byte_freq);
-
- return 0;
-}
-
-static enum handoff pixel_rcg_handoff(struct clk *clk)
-{
- struct rcg_clk *rcg = to_rcg_clk(clk);
- u32 div_val, mval, nval, cfg_regval;
- unsigned long pre_div_rate, parent_rate = clk_get_rate(clk->parent);
-
- cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
-
- /* If the pre-divider is used, find the rate after the division */
- div_val = cfg_regval & CFG_RCGR_DIV_MASK;
- if (div_val > 1)
- pre_div_rate = parent_rate / ((div_val + 1) >> 1);
- else
- pre_div_rate = parent_rate;
-
- clk->rate = pre_div_rate;
-
- /* If MND is used, find the rate after the MND division */
- if ((cfg_regval & MND_MODE_MASK) == MND_DUAL_EDGE_MODE_BVAL) {
- mval = readl_relaxed(M_REG(rcg));
- nval = readl_relaxed(N_REG(rcg));
- if (!nval)
- return HANDOFF_DISABLED_CLK;
- nval = (~nval) + mval;
- clk->rate = (pre_div_rate * mval) / nval;
- }
-
- if (readl_relaxed(CMD_RCGR_REG(rcg)) & CMD_RCGR_ROOT_STATUS_BIT)
- return HANDOFF_DISABLED_CLK;
-
- return HANDOFF_ENABLED_CLK;
-}
-
-static int set_rate_pixel(struct clk *clk, unsigned long rate)
-{
- struct rcg_clk *rcg = to_rcg_clk(clk);
- struct clk *pll = clk->parent;
- unsigned long source_rate, div;
- int rc;
-
- if (rate == 0)
- return -EINVAL;
-
- rc = clk_set_rate(pll, rate);
- if (rc)
- return rc;
-
- source_rate = clk_round_rate(pll, rate);
- if ((2 * source_rate) % rate)
- return -EINVAL;
-
- div = ((2 * source_rate)/rate) - 1;
- if (div > CFG_RCGR_DIV_MASK)
- return -EINVAL;
-
- pixel_freq.div_src_val &= ~CFG_RCGR_DIV_MASK;
- pixel_freq.div_src_val |= BVAL(4, 0, div);
- set_rate_mnd(rcg, &pixel_freq);
-
- return 0;
-}
static struct rcg_clk byte0_clk_src = {
.cmd_rcgr_reg = BYTE0_CMD_RCGR,
@@ -3324,35 +3196,6 @@
F_END
};
-/*
- * Unlike other clocks, the HDMI rate is adjusted through PLL
- * re-programming. It is also routed through an HID divider.
- */
-static int rcg_clk_set_rate_hdmi(struct clk *c, unsigned long rate)
-{
- struct clk_freq_tbl *nf;
- struct rcg_clk *rcg = to_rcg_clk(c);
- int rc;
-
- for (nf = rcg->freq_tbl; nf->freq_hz != rate; nf++)
- if (nf->freq_hz == FREQ_END) {
- rc = -EINVAL;
- goto out;
- }
-
- rc = clk_set_rate(nf->src_clk, rate);
- if (rc < 0)
- goto out;
- set_rate_hid(rcg, nf);
-
- rcg->current_freq = nf;
- c->parent = nf->src_clk;
-out:
- return rc;
-}
-
-static struct clk_ops clk_ops_rcg_hdmi;
-
static struct rcg_clk extpclk_clk_src = {
.cmd_rcgr_reg = EXTPCLK_CMD_RCGR,
.freq_tbl = ftbl_mdss_extpclk_clk,
@@ -3385,6 +3228,10 @@
},
};
+static struct clk_freq_tbl pixel_freq = {
+ .src_clk = &dsipll0_pixel_clk_src,
+ .div_src_val = BVAL(10, 8, dsipll0_pixel_mm_source_val),
+};
static struct rcg_clk pclk0_clk_src = {
.cmd_rcgr_reg = PCLK0_CMD_RCGR,
@@ -5525,28 +5372,6 @@
writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
}
-static void __init mdss_clock_setup(void)
-{
- clk_ops_byte = clk_ops_rcg;
- clk_ops_byte.set_rate = set_rate_byte;
- clk_ops_byte.handoff = byte_rcg_handoff;
- clk_ops_byte.get_parent = NULL;
-
- clk_ops_pixel = clk_ops_rcg_mnd;
- clk_ops_pixel.set_rate = set_rate_pixel;
- clk_ops_pixel.handoff = pixel_rcg_handoff;
- clk_ops_pixel.get_parent = NULL;
-
- clk_ops_rcg_hdmi = clk_ops_rcg;
- clk_ops_rcg_hdmi.set_rate = rcg_clk_set_rate_hdmi;
-
- /*
- * MDSS needs the ahb clock and needs to init before we register the
- * lookup table.
- */
- mdss_clk_ctrl_pre_init(&mdss_ahb_clk.c);
-}
-
static void __init msm8974_clock_post_init(void)
{
if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
@@ -5693,7 +5518,11 @@
qup_i2c_clks[i][0]->parent = qup_i2c_clks[i][1];
}
- mdss_clock_setup();
+ /*
+ * MDSS needs the ahb clock and needs to init before we register the
+ * lookup table.
+ */
+ mdss_clk_ctrl_pre_init(&mdss_ahb_clk.c);
}
static int __init msm8974_clock_late_init(void)
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index dd78557..214d1b7 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -624,6 +624,148 @@
return HANDOFF_ENABLED_CLK;
}
+static enum handoff byte_rcg_handoff(struct clk *clk)
+{
+ struct rcg_clk *rcg = to_rcg_clk(clk);
+ u32 div_val;
+ unsigned long pre_div_rate, parent_rate = clk_get_rate(clk->parent);
+
+ /* If the pre-divider is used, find the rate after the division */
+ div_val = readl_relaxed(CFG_RCGR_REG(rcg)) & CFG_RCGR_DIV_MASK;
+ if (div_val > 1)
+ pre_div_rate = parent_rate / ((div_val + 1) >> 1);
+ else
+ pre_div_rate = parent_rate;
+
+ clk->rate = pre_div_rate;
+
+ if (readl_relaxed(CMD_RCGR_REG(rcg)) & CMD_RCGR_ROOT_STATUS_BIT)
+ return HANDOFF_DISABLED_CLK;
+
+ return HANDOFF_ENABLED_CLK;
+}
+
+static int set_rate_byte(struct clk *clk, unsigned long rate)
+{
+ struct rcg_clk *rcg = to_rcg_clk(clk);
+ struct clk *pll = clk->parent;
+ unsigned long source_rate, div;
+ struct clk_freq_tbl *byte_freq = rcg->current_freq;
+ int rc;
+
+ if (rate == 0)
+ return -EINVAL;
+
+ rc = clk_set_rate(pll, rate);
+ if (rc)
+ return rc;
+
+ source_rate = clk_round_rate(pll, rate);
+ if ((2 * source_rate) % rate)
+ return -EINVAL;
+
+ div = ((2 * source_rate)/rate) - 1;
+ if (div > CFG_RCGR_DIV_MASK)
+ return -EINVAL;
+
+ byte_freq->div_src_val &= ~CFG_RCGR_DIV_MASK;
+ byte_freq->div_src_val |= BVAL(4, 0, div);
+ set_rate_hid(rcg, byte_freq);
+
+ return 0;
+}
+
+static enum handoff pixel_rcg_handoff(struct clk *clk)
+{
+ struct rcg_clk *rcg = to_rcg_clk(clk);
+ u32 div_val, mval, nval, cfg_regval;
+ unsigned long pre_div_rate, parent_rate = clk_get_rate(clk->parent);
+
+ cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
+
+ /* If the pre-divider is used, find the rate after the division */
+ div_val = cfg_regval & CFG_RCGR_DIV_MASK;
+ if (div_val > 1)
+ pre_div_rate = parent_rate / ((div_val + 1) >> 1);
+ else
+ pre_div_rate = parent_rate;
+
+ clk->rate = pre_div_rate;
+
+ /* If MND is used, find the rate after the MND division */
+ if ((cfg_regval & MND_MODE_MASK) == MND_DUAL_EDGE_MODE_BVAL) {
+ mval = readl_relaxed(M_REG(rcg));
+ nval = readl_relaxed(N_REG(rcg));
+ if (!nval)
+ return HANDOFF_DISABLED_CLK;
+ nval = (~nval) + mval;
+ clk->rate = (pre_div_rate * mval) / nval;
+ }
+
+ if (readl_relaxed(CMD_RCGR_REG(rcg)) & CMD_RCGR_ROOT_STATUS_BIT)
+ return HANDOFF_DISABLED_CLK;
+
+ return HANDOFF_ENABLED_CLK;
+}
+
+static int set_rate_pixel(struct clk *clk, unsigned long rate)
+{
+ struct rcg_clk *rcg = to_rcg_clk(clk);
+ struct clk *pll = clk->parent;
+ unsigned long source_rate, div;
+ struct clk_freq_tbl *pixel_freq = rcg->current_freq;
+ int rc;
+
+ if (rate == 0)
+ return -EINVAL;
+
+ rc = clk_set_rate(pll, rate);
+ if (rc)
+ return rc;
+
+ source_rate = clk_round_rate(pll, rate);
+ if ((2 * source_rate) % rate)
+ return -EINVAL;
+
+ div = ((2 * source_rate)/rate) - 1;
+ if (div > CFG_RCGR_DIV_MASK)
+ return -EINVAL;
+
+ pixel_freq->div_src_val &= ~CFG_RCGR_DIV_MASK;
+ pixel_freq->div_src_val |= BVAL(4, 0, div);
+ set_rate_mnd(rcg, pixel_freq);
+
+ return 0;
+}
+
+/*
+ * Unlike other clocks, the HDMI rate is adjusted through PLL
+ * re-programming. It is also routed through an HID divider.
+ */
+static int rcg_clk_set_rate_hdmi(struct clk *c, unsigned long rate)
+{
+ struct clk_freq_tbl *nf;
+ struct rcg_clk *rcg = to_rcg_clk(c);
+ int rc;
+
+ for (nf = rcg->freq_tbl; nf->freq_hz != rate; nf++)
+ if (nf->freq_hz == FREQ_END) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = clk_set_rate(nf->src_clk, rate);
+ if (rc < 0)
+ goto out;
+ set_rate_hid(rcg, nf);
+
+ rcg->current_freq = nf;
+ c->parent = nf->src_clk;
+out:
+ return rc;
+}
+
+
struct clk_ops clk_ops_empty;
struct clk_ops clk_ops_rcg = {
@@ -644,6 +786,32 @@
.get_parent = rcg_mnd_clk_get_parent,
};
+struct clk_ops clk_ops_pixel = {
+ .enable = rcg_clk_prepare,
+ .set_rate = set_rate_pixel,
+ .list_rate = rcg_clk_list_rate,
+ .round_rate = rcg_clk_round_rate,
+ .handoff = pixel_rcg_handoff,
+};
+
+struct clk_ops clk_ops_byte = {
+ .enable = rcg_clk_prepare,
+ .set_rate = set_rate_byte,
+ .list_rate = rcg_clk_list_rate,
+ .round_rate = rcg_clk_round_rate,
+ .handoff = byte_rcg_handoff,
+};
+
+struct clk_ops clk_ops_rcg_hdmi = {
+ .enable = rcg_clk_prepare,
+ .set_rate = rcg_clk_set_rate_hdmi,
+ .set_rate = rcg_clk_set_rate,
+ .list_rate = rcg_clk_list_rate,
+ .round_rate = rcg_clk_round_rate,
+ .handoff = rcg_clk_handoff,
+ .get_parent = rcg_clk_get_parent,
+};
+
struct clk_ops clk_ops_branch = {
.enable = branch_clk_enable,
.disable = branch_clk_disable,
diff --git a/arch/arm/mach-msm/clock-local2.h b/arch/arm/mach-msm/clock-local2.h
index 2e1b8a9..7ac7bd3 100644
--- a/arch/arm/mach-msm/clock-local2.h
+++ b/arch/arm/mach-msm/clock-local2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. 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
@@ -173,6 +173,9 @@
extern struct clk_ops clk_ops_rcg_mnd;
extern struct clk_ops clk_ops_branch;
extern struct clk_ops clk_ops_vote;
+extern struct clk_ops clk_ops_rcg_hdmi;
+extern struct clk_ops clk_ops_byte;
+extern struct clk_ops clk_ops_pixel;
/*
* Clock definition macros