]> git.sur5r.net Git - u-boot/commitdiff
tegra: Add functions to access low-level Osc/PLL details
authorSimon Glass <sjg@chromium.org>
Mon, 2 Apr 2012 13:18:47 +0000 (13:18 +0000)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Tue, 15 May 2012 06:31:37 +0000 (08:31 +0200)
Add clock_ll_read_pll() to read PLL parameters and clock_get_osc_bypass()
to find out if the Oscillator is bypassed. These are needed by warmboot.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Tom Warren <twarren@nvidia.com>
arch/arm/cpu/armv7/tegra2/clock.c
arch/arm/include/asm/arch-tegra2/clk_rst.h
arch/arm/include/asm/arch-tegra2/clock.h

index 39376ab86ef90434dacfa5b1cae8e44fabbc987e..b6b32107fe4057e5972815f6c30de2ce988ad40d 100644 (file)
@@ -410,6 +410,16 @@ enum clock_osc_freq clock_get_osc_freq(void)
        return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
 }
 
+int clock_get_osc_bypass(void)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 reg;
+
+       reg = readl(&clkrst->crc_osc_ctrl);
+       return (reg & OSC_XOBP_MASK) >> OSC_XOBP_SHIFT;
+}
+
 /* Returns a pointer to the registers of the given pll */
 static struct clk_pll *get_pll(enum clock_id clkid)
 {
@@ -420,6 +430,28 @@ static struct clk_pll *get_pll(enum clock_id clkid)
        return &clkrst->crc_pll[clkid];
 }
 
+int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
+               u32 *divp, u32 *cpcon, u32 *lfcon)
+{
+       struct clk_pll *pll = get_pll(clkid);
+       u32 data;
+
+       assert(clkid != CLOCK_ID_USB);
+
+       /* Safety check, adds to code size but is small */
+       if (!clock_id_isvalid(clkid) || clkid == CLOCK_ID_USB)
+               return -1;
+       data = readl(&pll->pll_base);
+       *divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
+       *divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT;
+       *divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
+       data = readl(&pll->pll_misc);
+       *cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT;
+       *lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT;
+
+       return 0;
+}
+
 unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
                u32 divp, u32 cpcon, u32 lfcon)
 {
index 415e4200122543c5d2bfd621a1edc22e28d8857b..8c3be915145af938c18ab2cc71254bc98a8adb66 100644 (file)
@@ -117,6 +117,7 @@ struct clk_rst_ctlr {
 #define PLL_CPCON_MASK         (15U << PLL_CPCON_SHIFT)
 
 #define PLL_LFCON_SHIFT                4
+#define PLL_LFCON_MASK         (15U << PLL_LFCON_SHIFT)
 
 #define PLLU_VCO_FREQ_SHIFT    20
 #define PLLU_VCO_FREQ_MASK     (1U << PLLU_VCO_FREQ_SHIFT)
@@ -124,6 +125,8 @@ struct clk_rst_ctlr {
 /* CLK_RST_CONTROLLER_OSC_CTRL_0 */
 #define OSC_FREQ_SHIFT         30
 #define OSC_FREQ_MASK          (3U << OSC_FREQ_SHIFT)
+#define OSC_XOBP_SHIFT         1
+#define OSC_XOBP_MASK          (1U << OSC_XOBP_SHIFT)
 
 /*
  * CLK_RST_CONTROLLER_CLK_SOURCE_x_OUT_0 - the mask here is normally 8 bits
index 6b12c76e8d5383df41ea0a94c87e0d638b5b4340..1d3ae3864407c42d06f8f0018e2e1aeae2d4cb36 100644 (file)
@@ -210,6 +210,21 @@ enum clock_osc_freq clock_get_osc_freq(void);
 unsigned long clock_start_pll(enum clock_id id, u32 divm, u32 divn,
                u32 divp, u32 cpcon, u32 lfcon);
 
+/**
+ * Read low-level parameters of a PLL.
+ *
+ * @param id   clock id to read (note: USB is not supported)
+ * @param divm returns input divider
+ * @param divn returns feedback divider
+ * @param divp returns post divider 2^n
+ * @param cpcon        returns charge pump setup control
+ * @param lfcon        returns loop filter setup control
+ *
+ * @returns 0 if ok, -1 on error (invalid clock id)
+ */
+int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
+                     u32 *divp, u32 *cpcon, u32 *lfcon);
+
 /*
  * Enable a clock
  *
@@ -368,6 +383,13 @@ void clock_ll_start_uart(enum periph_id periph_id);
  */
 enum periph_id clock_decode_periph_id(const void *blob, int node);
 
+/**
+ * Checks if the oscillator bypass is enabled (XOBP bit)
+ *
+ * @return 1 if bypass is enabled, 0 if not
+ */
+int clock_get_osc_bypass(void);
+
 /*
  * Checks that clocks are valid and prints a warning if not
  *