Merge "msm_xo: Work around RPM treating CXO_CLK and D0 as the same" into msm-3.0
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 119f89c..9ab630d 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4865,6 +4865,7 @@
CLK_LOOKUP("xo", cxo_clk.c, "pil_qdsp6v4.2"),
CLK_LOOKUP("xo", cxo_clk.c, "pil_gss"),
CLK_LOOKUP("xo", cxo_clk.c, "BAM_RMNT"),
+ CLK_LOOKUP("xo", cxo_clk.c, "msm_xo"),
CLK_LOOKUP("pll2", pll2_clk.c, NULL),
CLK_LOOKUP("pll8", pll8_clk.c, NULL),
CLK_LOOKUP("pll4", pll4_clk.c, NULL),
@@ -5147,6 +5148,7 @@
CLK_LOOKUP("xo", cxo_clk.c, "pil_qdsp6v4.1"),
CLK_LOOKUP("xo", cxo_clk.c, "pil_qdsp6v4.2"),
CLK_LOOKUP("xo", cxo_clk.c, "BAM_RMNT"),
+ CLK_LOOKUP("xo", cxo_clk.c, "msm_xo"),
CLK_LOOKUP("pll2", pll2_clk.c, NULL),
CLK_LOOKUP("pll8", pll8_clk.c, NULL),
CLK_LOOKUP("pll4", pll4_clk.c, NULL),
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 3e059b6..e1dc2ae 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1602,6 +1602,7 @@
CLK_LOOKUP("xo", cxo_a_clk.c, ""),
CLK_LOOKUP("xo", cxo_clk.c, "msm_otg"),
CLK_LOOKUP("xo", cxo_clk.c, "BAM_RMNT"),
+ CLK_LOOKUP("xo", cxo_clk.c, "msm_xo"),
CLK_LOOKUP("pll0", pll0_clk.c, NULL),
CLK_LOOKUP("pll8", pll8_clk.c, NULL),
CLK_LOOKUP("pll14", pll14_clk.c, NULL),
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 936fd6b..86776d3 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -21,6 +21,7 @@
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/string.h>
+#include <linux/clk.h>
#include <mach/msm_xo.h>
#include <mach/rpm.h>
@@ -232,6 +233,9 @@
{
int ret;
struct msm_xo *xo = xo_voter->xo;
+ int is_d0 = xo == &msm_xo_sources[MSM_XO_TCXO_D0];
+ int needs_workaround = cpu_is_msm8960() || cpu_is_apq8064() ||
+ cpu_is_msm8930() || cpu_is_msm9615();
if (xo_voter->mode == mode)
return 0;
@@ -244,6 +248,20 @@
xo->votes[mode]--;
goto out;
}
+ /* TODO: Remove once RPM separates the concept of D0 and CXO */
+ if (is_d0 && needs_workaround) {
+ static struct clk *xo_clk;
+
+ if (!xo_clk) {
+ xo_clk = clk_get_sys("msm_xo", "xo");
+ BUG_ON(IS_ERR(xo_clk));
+ }
+ /* Ignore transitions from pin to on or vice versa */
+ if (mode && xo_voter->mode == MSM_XO_MODE_OFF)
+ clk_enable(xo_clk);
+ else if (!mode)
+ clk_disable(xo_clk);
+ }
xo_voter->mode = mode;
out:
return ret;