msm: clock: Move out pll code from clock-local.c to clock-pll.c
The new clock-pll driver is designed to control
PLL clocks including shared, locally controlled
and voteable PLLs. Move PLL code from clock-local.c
into this new driver.
Change-Id: I58fc0c7e4816e52d25dd2521a70baff52d8a74b2
Signed-off-by: Vikram Mulukutla <markivx@codeaurora.org>
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d233c91..14bae2d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -168,7 +168,7 @@
obj-$(CONFIG_ARCH_QSD8X50) += devices-qsd8x50.o clock-pcom-lookup.o
obj-$(CONFIG_MACH_QSD8X50_SURF) += board-qsd8x50.o
obj-$(CONFIG_MACH_QSD8X50_FFA) += board-qsd8x50.o
-obj-$(CONFIG_ARCH_MSM8X60) += devices-msm8x60.o clock-local.o clock-8x60.o acpuclock-8x60.o
+obj-$(CONFIG_ARCH_MSM8X60) += devices-msm8x60.o clock-local.o clock-8x60.o acpuclock-8x60.o clock-pll.o
obj-$(CONFIG_ARCH_MSM8X60) += clock-rpm.o
obj-$(CONFIG_ARCH_MSM8X60) += saw-regulator.o
obj-$(CONFIG_ARCH_MSM8X60) += footswitch-8x60.o
@@ -240,10 +240,10 @@
obj-$(CONFIG_MACH_MSM8625_EVB) += board-qrd7627a.o board-7627a-all.o
obj-$(CONFIG_MACH_MSM8625_QRD7) += board-qrd7627a.o board-7627a-all.o
obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o memory_topology.o
-obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o clock-7x30.o acpuclock-7x30.o
+obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o clock-7x30.o acpuclock-7x30.o clock-pll.o
obj-$(CONFIG_MACH_MSM7X25_SURF) += board-msm7x27.o devices-msm7x25.o
obj-$(CONFIG_MACH_MSM7X25_FFA) += board-msm7x27.o devices-msm7x25.o
-obj-$(CONFIG_ARCH_MSM8960) += clock-local.o clock-dss-8960.o clock-8960.o clock-rpm.o
+obj-$(CONFIG_ARCH_MSM8960) += clock-local.o clock-dss-8960.o clock-8960.o clock-rpm.o clock-pll.o
obj-$(CONFIG_ARCH_MSM8960) += footswitch-8x60.o
obj-$(CONFIG_ARCH_MSM8960) += acpuclock-8960.o
obj-$(CONFIG_ARCH_MSM8960) += memory_topology.o
@@ -270,7 +270,7 @@
obj-$(CONFIG_MACH_MPQ8064_HRD) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_MACH_MPQ8064_DTV) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
-obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o
+obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o board-copper-gpiomux.o
obj-$(CONFIG_ARCH_MSMCOPPER) += acpuclock-krait.o acpuclock-copper.o
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index f9d8dbe..5951734 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -31,6 +31,7 @@
#include "clock-pcom.h"
#include "clock-voter.h"
#include "proc_comm.h"
+#include "clock-pll.h"
#define REG_BASE(off) (MSM_CLK_CTL_BASE + (off))
#define REG(off) (MSM_CLK_CTL_SH2_BASE + (off))
@@ -268,6 +269,7 @@
.en_reg = PLL_ENA_REG,
.en_mask = BIT(1),
.status_reg = PLL1_STATUS_BASE_REG,
+ .status_mask = BIT(16),
.parent = &tcxo_clk.c,
.c = {
.dbg_name = "pll1_clk",
@@ -282,6 +284,7 @@
.en_reg = PLL_ENA_REG,
.en_mask = BIT(2),
.status_reg = PLL2_STATUS_BASE_REG,
+ .status_mask = BIT(16),
.parent = &tcxo_clk.c,
.c = {
.dbg_name = "pll2_clk",
@@ -296,6 +299,7 @@
.en_reg = PLL_ENA_REG,
.en_mask = BIT(3),
.status_reg = PLL3_STATUS_BASE_REG,
+ .status_mask = BIT(16),
.parent = &lpxo_clk.c,
.c = {
.dbg_name = "pll3_clk",
@@ -309,6 +313,7 @@
.en_reg = PLL_ENA_REG,
.en_mask = BIT(4),
.status_reg = PLL4_STATUS_BASE_REG,
+ .status_mask = BIT(16),
.parent = &lpxo_clk.c,
.c = {
.dbg_name = "pll4_clk",
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 89cde6d..ca5a63d 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -33,6 +33,7 @@
#include "clock-voter.h"
#include "clock-dss-8960.h"
#include "devices.h"
+#include "clock-pll.h"
#define REG(off) (MSM_CLK_CTL_BASE + (off))
#define REG_MM(off) (MSM_MMSS_CLK_CTL_BASE + (off))
@@ -478,7 +479,7 @@
.c = {
.dbg_name = "pll2_clk",
.rate = 800000000,
- .ops = &clk_ops_pll,
+ .ops = &clk_ops_local_pll,
CLK_INIT(pll2_clk.c),
.warned = true,
},
@@ -490,7 +491,7 @@
.c = {
.dbg_name = "pll3_clk",
.rate = 1200000000,
- .ops = &clk_ops_pll,
+ .ops = &clk_ops_local_pll,
.vdd_class = &vdd_sr2_pll,
.fmax[VDD_SR2_PLL_ON] = ULONG_MAX,
CLK_INIT(pll3_clk.c),
@@ -502,6 +503,7 @@
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(4),
.status_reg = LCC_PLL0_STATUS_REG,
+ .status_mask = BIT(16),
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll4_clk",
@@ -516,6 +518,7 @@
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(8),
.status_reg = BB_PLL8_STATUS_REG,
+ .status_mask = BIT(16),
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll8_clk",
@@ -530,6 +533,7 @@
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(14),
.status_reg = BB_PLL14_STATUS_REG,
+ .status_mask = BIT(16),
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll14_clk",
@@ -546,7 +550,7 @@
.c = {
.dbg_name = "pll15_clk",
.rate = 975000000,
- .ops = &clk_ops_pll,
+ .ops = &clk_ops_local_pll,
CLK_INIT(pll15_clk.c),
.warned = true,
},
@@ -6032,7 +6036,7 @@
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- clk_ops_pll.enable = sr_pll_clk_enable;
+ clk_ops_local_pll.enable = sr_pll_clk_enable;
/* Initialize clock registers. */
reg_init();
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 5031887..6c23c50 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -31,6 +31,7 @@
#include "clock-local.h"
#include "clock-rpm.h"
#include "clock-voter.h"
+#include "clock-pll.h"
#ifdef CONFIG_MSM_SECURE_IO
#undef readl_relaxed
@@ -304,6 +305,7 @@
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(8),
.status_reg = BB_PLL8_STATUS_REG,
+ .status_mask = BIT(16),
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll8_clk",
@@ -320,7 +322,7 @@
.c = {
.dbg_name = "pll2_clk",
.rate = 800000000,
- .ops = &clk_ops_pll,
+ .ops = &clk_ops_local_pll,
CLK_INIT(pll2_clk.c),
.warned = true,
},
@@ -332,7 +334,7 @@
.c = {
.dbg_name = "pll3_clk",
.rate = 0, /* TODO: Detect rate dynamically */
- .ops = &clk_ops_pll,
+ .ops = &clk_ops_local_pll,
CLK_INIT(pll3_clk.c),
.warned = true,
},
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 411e615..b145278 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -32,6 +32,7 @@
#include "clock-voter.h"
#include "clock-rpm.h"
#include "devices.h"
+#include "clock-pll.h"
#define REG(off) (MSM_CLK_CTL_BASE + (off))
#define REG_LPA(off) (MSM_LPASS_CLK_CTL_BASE + (off))
@@ -259,6 +260,7 @@
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(0),
.status_reg = BB_PLL0_STATUS_REG,
+ .status_mask = BIT(16),
.parent = &cxo_clk.c,
.soft_vote = &soft_vote_pll0,
.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
@@ -275,6 +277,7 @@
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(0),
.status_reg = BB_PLL0_STATUS_REG,
+ .status_mask = BIT(16),
.soft_vote = &soft_vote_pll0,
.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
.c = {
@@ -290,6 +293,7 @@
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(4),
.status_reg = LCC_PLL0_STATUS_REG,
+ .status_mask = BIT(16),
.parent = &cxo_clk.c,
.c = {
.dbg_name = "pll4_clk",
@@ -306,6 +310,7 @@
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(8),
.status_reg = BB_PLL8_STATUS_REG,
+ .status_mask = BIT(16),
.parent = &cxo_clk.c,
.soft_vote = &soft_vote_pll8,
.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
@@ -322,6 +327,7 @@
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(8),
.status_reg = BB_PLL8_STATUS_REG,
+ .status_mask = BIT(16),
.soft_vote = &soft_vote_pll8,
.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
.c = {
@@ -338,7 +344,7 @@
.c = {
.dbg_name = "pll9_acpu_clk",
.rate = 440000000,
- .ops = &clk_ops_pll,
+ .ops = &clk_ops_local_pll,
CLK_INIT(pll9_acpu_clk.c),
.warned = true,
},
@@ -348,6 +354,7 @@
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(11),
.status_reg = BB_PLL14_STATUS_REG,
+ .status_mask = BIT(16),
.parent = &cxo_clk.c,
.c = {
.dbg_name = "pll14_clk",
@@ -1742,7 +1749,7 @@
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- clk_ops_pll.enable = sr_pll_clk_enable;
+ clk_ops_local_pll.enable = sr_pll_clk_enable;
/* Enable PDM CXO source. */
regval = readl_relaxed(PDM_CLK_NS_REG);
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 84aa086..d414e44 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -627,158 +627,6 @@
return HANDOFF_ENABLED_CLK;
}
-int pll_vote_clk_enable(struct clk *clk)
-{
- u32 ena;
- unsigned long flags;
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
-
- spin_lock_irqsave(&local_clock_reg_lock, flags);
- ena = readl_relaxed(pll->en_reg);
- ena |= pll->en_mask;
- writel_relaxed(ena, pll->en_reg);
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
-
- /* Wait until PLL is enabled */
- while ((readl_relaxed(pll->status_reg) & BIT(16)) == 0)
- cpu_relax();
-
- return 0;
-}
-
-void pll_vote_clk_disable(struct clk *clk)
-{
- u32 ena;
- unsigned long flags;
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
-
- spin_lock_irqsave(&local_clock_reg_lock, flags);
- ena = readl_relaxed(pll->en_reg);
- ena &= ~(pll->en_mask);
- writel_relaxed(ena, pll->en_reg);
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
-}
-
-struct clk *pll_vote_clk_get_parent(struct clk *clk)
-{
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
- return pll->parent;
-}
-
-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,
- .auto_off = pll_vote_clk_disable,
- .is_enabled = pll_vote_clk_is_enabled,
- .get_parent = pll_vote_clk_get_parent,
-};
-
-static int pll_clk_enable(struct clk *clk)
-{
- u32 mode;
- unsigned long flags;
- struct pll_clk *pll = to_pll_clk(clk);
-
- spin_lock_irqsave(&local_clock_reg_lock, flags);
- mode = readl_relaxed(pll->mode_reg);
- /* 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.
- */
- mb();
- udelay(10);
-
- /* De-assert active-low PLL reset. */
- mode |= BIT(2);
- writel_relaxed(mode, pll->mode_reg);
-
- /* Wait until PLL is locked. */
- mb();
- udelay(50);
-
- /* Enable PLL output. */
- mode |= BIT(0);
- writel_relaxed(mode, pll->mode_reg);
-
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
- return 0;
-}
-
-static void pll_clk_disable(struct clk *clk)
-{
- u32 mode;
- unsigned long flags;
- struct pll_clk *pll = to_pll_clk(clk);
-
- /*
- * Disable the PLL output, disable test mode, enable
- * the bypass mode, and assert the reset.
- */
- spin_lock_irqsave(&local_clock_reg_lock, flags);
- mode = readl_relaxed(pll->mode_reg);
- mode &= ~BM(3, 0);
- writel_relaxed(mode, pll->mode_reg);
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
-}
-
-static struct clk *pll_clk_get_parent(struct clk *clk)
-{
- struct pll_clk *pll = to_pll_clk(clk);
- return pll->parent;
-}
-
-int sr_pll_clk_enable(struct clk *clk)
-{
- u32 mode;
- unsigned long flags;
- struct pll_clk *pll = to_pll_clk(clk);
-
- spin_lock_irqsave(&local_clock_reg_lock, flags);
- mode = readl_relaxed(pll->mode_reg);
- /* De-assert active-low PLL reset. */
- mode |= BIT(2);
- writel_relaxed(mode, pll->mode_reg);
-
- /*
- * H/W requires a 5us delay between disabling the bypass and
- * de-asserting the reset. Delay 10us just to be safe.
- */
- mb();
- udelay(10);
-
- /* Disable PLL bypass mode. */
- mode |= BIT(1);
- writel_relaxed(mode, pll->mode_reg);
-
- /* Wait until PLL is locked. */
- mb();
- udelay(60);
-
- /* Enable PLL output. */
- mode |= BIT(0);
- writel_relaxed(mode, pll->mode_reg);
-
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
- return 0;
-}
-
-struct clk_ops clk_ops_pll = {
- .enable = pll_clk_enable,
- .disable = pll_clk_disable,
- .auto_off = pll_clk_disable,
- .get_parent = pll_clk_get_parent,
-};
-
struct clk_ops clk_ops_gnd = {
};
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 3dd849a..0419ede 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -17,12 +17,6 @@
#include <linux/spinlock.h>
#include "clock.h"
-/*
- * 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))
-
#define MN_MODE_DUAL_EDGE 0x2
/* MD Registers */
@@ -257,57 +251,6 @@
};
/**
- * struct pll_vote_clk - phase locked loop (HW voteable)
- * @soft_vote: soft voting variable for multiple PLL software instances
- * @soft_vote_mask: soft voting mask for multiple PLL software instances
- * @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 {
- u32 *soft_vote;
- const u32 soft_vote_mask;
- void __iomem *const en_reg;
- const u32 en_mask;
-
- void __iomem *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
- * @mode_reg: enable register
- * @parent: clock source
- * @c: clk
- */
-struct pll_clk {
- void __iomem *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);
-}
-
-int sr_pll_clk_enable(struct clk *clk);
-
-/**
* struct branch_clk - branch
* @enabled: true if clock is on, false otherwise
* @b: branch
@@ -365,14 +308,6 @@
extern struct fixed_clk gnd_clk;
/*
- * PLL vote clock APIs
- */
-int pll_vote_clk_enable(struct clk *clk);
-void pll_vote_clk_disable(struct clk *clk);
-struct clk *pll_vote_clk_get_parent(struct clk *clk);
-int pll_vote_clk_is_enabled(struct clk *clk);
-
-/*
* Generic set-rate implementations
*/
void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf);
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index 68c390a..eb980e8 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -17,13 +17,194 @@
#include <linux/err.h>
#include <linux/remote_spinlock.h>
-#include <mach/socinfo.h>
+#include <mach/scm-io.h>
#include <mach/msm_iomap.h>
#include "clock.h"
#include "clock-pll.h"
#include "smd_private.h"
+#ifdef CONFIG_MSM_SECURE_IO
+#undef readl_relaxed
+#undef writel_relaxed
+#define readl_relaxed secure_readl
+#define writel_relaxed secure_writel
+#endif
+
+#define PLL_OUTCTRL BIT(0)
+#define PLL_BYPASSNL BIT(1)
+#define PLL_RESET_N BIT(2)
+#define PLL_MODE_MASK BM(3, 0)
+
+static DEFINE_SPINLOCK(pll_reg_lock);
+
+int pll_vote_clk_enable(struct clk *clk)
+{
+ u32 ena;
+ unsigned long flags;
+ struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+
+ spin_lock_irqsave(&pll_reg_lock, flags);
+ ena = readl_relaxed(pll->en_reg);
+ ena |= pll->en_mask;
+ writel_relaxed(ena, pll->en_reg);
+ spin_unlock_irqrestore(&pll_reg_lock, flags);
+
+ /* Wait until PLL is enabled */
+ while ((readl_relaxed(pll->status_reg) & pll->status_mask) == 0)
+ cpu_relax();
+
+ return 0;
+}
+
+void pll_vote_clk_disable(struct clk *clk)
+{
+ u32 ena;
+ unsigned long flags;
+ struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+
+ spin_lock_irqsave(&pll_reg_lock, flags);
+ ena = readl_relaxed(pll->en_reg);
+ ena &= ~(pll->en_mask);
+ writel_relaxed(ena, pll->en_reg);
+ spin_unlock_irqrestore(&pll_reg_lock, flags);
+}
+
+struct clk *pll_vote_clk_get_parent(struct clk *clk)
+{
+ struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+ return pll->parent;
+}
+
+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) & pll->status_mask);
+}
+
+struct clk_ops clk_ops_pll_vote = {
+ .enable = pll_vote_clk_enable,
+ .disable = pll_vote_clk_disable,
+ .auto_off = pll_vote_clk_disable,
+ .is_enabled = pll_vote_clk_is_enabled,
+ .get_parent = pll_vote_clk_get_parent,
+};
+
+static void __pll_clk_enable_reg(void __iomem *mode_reg)
+{
+ u32 mode = readl_relaxed(mode_reg);
+ /* Disable PLL bypass mode. */
+ mode |= PLL_BYPASSNL;
+ writel_relaxed(mode, mode_reg);
+
+ /*
+ * H/W requires a 5us delay between disabling the bypass and
+ * de-asserting the reset. Delay 10us just to be safe.
+ */
+ mb();
+ udelay(10);
+
+ /* De-assert active-low PLL reset. */
+ mode |= PLL_RESET_N;
+ writel_relaxed(mode, mode_reg);
+
+ /* Wait until PLL is locked. */
+ mb();
+ udelay(50);
+
+ /* Enable PLL output. */
+ mode |= PLL_OUTCTRL;
+ writel_relaxed(mode, mode_reg);
+
+ /* Ensure that the write above goes through before returning. */
+ mb();
+}
+
+static int local_pll_clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+ struct pll_clk *pll = to_pll_clk(clk);
+
+ spin_lock_irqsave(&pll_reg_lock, flags);
+ __pll_clk_enable_reg(pll->mode_reg);
+ spin_unlock_irqrestore(&pll_reg_lock, flags);
+
+ return 0;
+}
+
+static void __pll_clk_disable_reg(void __iomem *mode_reg)
+{
+ u32 mode = readl_relaxed(mode_reg);
+ mode &= ~PLL_MODE_MASK;
+ writel_relaxed(mode, mode_reg);
+}
+
+static void local_pll_clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+ struct pll_clk *pll = to_pll_clk(clk);
+
+ /*
+ * Disable the PLL output, disable test mode, enable
+ * the bypass mode, and assert the reset.
+ */
+ spin_lock_irqsave(&pll_reg_lock, flags);
+ __pll_clk_disable_reg(pll->mode_reg);
+ spin_unlock_irqrestore(&pll_reg_lock, flags);
+}
+
+static struct clk *local_pll_clk_get_parent(struct clk *clk)
+{
+ struct pll_clk *pll = to_pll_clk(clk);
+ return pll->parent;
+}
+
+int sr_pll_clk_enable(struct clk *clk)
+{
+ u32 mode;
+ unsigned long flags;
+ struct pll_clk *pll = to_pll_clk(clk);
+
+ spin_lock_irqsave(&pll_reg_lock, flags);
+ mode = readl_relaxed(pll->mode_reg);
+ /* De-assert active-low PLL reset. */
+ mode |= PLL_RESET_N;
+ writel_relaxed(mode, pll->mode_reg);
+
+ /*
+ * H/W requires a 5us delay between disabling the bypass and
+ * de-asserting the reset. Delay 10us just to be safe.
+ */
+ mb();
+ udelay(10);
+
+ /* Disable PLL bypass mode. */
+ mode |= PLL_BYPASSNL;
+ writel_relaxed(mode, pll->mode_reg);
+
+ /* Wait until PLL is locked. */
+ mb();
+ udelay(60);
+
+ /* Enable PLL output. */
+ mode |= PLL_OUTCTRL;
+ writel_relaxed(mode, pll->mode_reg);
+
+ /* Ensure that the write above goes through before returning. */
+ mb();
+
+ spin_unlock_irqrestore(&pll_reg_lock, flags);
+
+ return 0;
+}
+
+struct clk_ops clk_ops_local_pll = {
+ .enable = local_pll_clk_enable,
+ .disable = local_pll_clk_disable,
+ .auto_off = local_pll_clk_disable,
+ .get_parent = local_pll_clk_get_parent,
+};
+
struct pll_rate {
unsigned int lvalue;
unsigned long rate;
@@ -95,21 +276,6 @@
}
-static void pll_enable(void __iomem *addr, unsigned on)
-{
- if (on) {
- writel_relaxed(2, addr);
- mb();
- udelay(5);
- writel_relaxed(6, addr);
- mb();
- udelay(50);
- writel_relaxed(7, addr);
- } else {
- writel_relaxed(0, addr);
- }
-}
-
static int pll_clk_enable(struct clk *clk)
{
struct pll_shared_clk *pll = to_pll_shared_clk(clk);
@@ -119,7 +285,7 @@
pll_control->pll[PLL_BASE + pll_id].votes |= BIT(1);
if (!pll_control->pll[PLL_BASE + pll_id].on) {
- pll_enable(pll->mode_reg, 1);
+ __pll_clk_enable_reg(pll->mode_reg);
pll_control->pll[PLL_BASE + pll_id].on = 1;
}
@@ -137,7 +303,7 @@
pll_control->pll[PLL_BASE + pll_id].votes &= ~BIT(1);
if (pll_control->pll[PLL_BASE + pll_id].on
&& !pll_control->pll[PLL_BASE + pll_id].votes) {
- pll_enable(pll->mode_reg, 0);
+ __pll_clk_disable_reg(pll->mode_reg);
pll_control->pll[PLL_BASE + pll_id].on = 0;
}
@@ -151,11 +317,6 @@
return readl_relaxed(pll->mode_reg) & BIT(0);
}
-static bool pll_clk_is_local(struct clk *clk)
-{
- return true;
-}
-
static enum handoff pll_clk_handoff(struct clk *clk)
{
struct pll_shared_clk *pll = to_pll_shared_clk(clk);
@@ -191,6 +352,5 @@
.enable = pll_clk_enable,
.disable = pll_clk_disable,
.handoff = pll_clk_handoff,
- .is_local = pll_clk_is_local,
.is_enabled = pll_clk_is_enabled,
};
diff --git a/arch/arm/mach-msm/clock-pll.h b/arch/arm/mach-msm/clock-pll.h
index ae0ca17..7de81c9 100644
--- a/arch/arm/mach-msm/clock-pll.h
+++ b/arch/arm/mach-msm/clock-pll.h
@@ -12,6 +12,9 @@
*
*/
+#ifndef __ARCH_ARM_MACH_MSM_CLOCK_PLL_H
+#define __ARCH_ARM_MACH_MSM_CLOCK_PLL_H
+
/**
* enum - For PLL IDs
*/
@@ -50,3 +53,65 @@
* msm_shared_pll_control_init() - Initialize shared pll control structure
*/
void msm_shared_pll_control_init(void);
+
+/**
+ * struct pll_vote_clk - phase locked loop (HW voteable)
+ * @soft_vote: soft voting variable for multiple PLL software instances
+ * @soft_vote_mask: soft voting mask for multiple PLL software instances
+ * @en_reg: enable register
+ * @en_mask: ORed with @en_reg to enable the clock
+ * @status_mask: ANDed with @status_reg to determine if PLL is active.
+ * @status_reg: status register
+ * @parent: clock source
+ * @c: clk
+ */
+struct pll_vote_clk {
+ u32 *soft_vote;
+ const u32 soft_vote_mask;
+ void __iomem *const en_reg;
+ const u32 en_mask;
+ void __iomem *const status_reg;
+ const u32 status_mask;
+
+ 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
+ * @mode_reg: enable register
+ * @parent: clock source
+ * @c: clk
+ */
+struct pll_clk {
+ void __iomem *const mode_reg;
+
+ struct clk *parent;
+ struct clk c;
+};
+
+extern struct clk_ops clk_ops_local_pll;
+
+static inline struct pll_clk *to_pll_clk(struct clk *clk)
+{
+ return container_of(clk, struct pll_clk, c);
+}
+
+int sr_pll_clk_enable(struct clk *clk);
+
+/*
+ * PLL vote clock APIs
+ */
+int pll_vote_clk_enable(struct clk *clk);
+void pll_vote_clk_disable(struct clk *clk);
+struct clk *pll_vote_clk_get_parent(struct clk *clk);
+int pll_vote_clk_is_enabled(struct clk *clk);
+
+#endif
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 60be654..fda7175 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -37,6 +37,12 @@
#define CLKFLAG_MIN 0x00000400
#define CLKFLAG_MAX 0x00000800
+/*
+ * 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))
+
#define MAX_VDD_LEVELS 4
/**