summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJong Kim <jongk@nvidia.com>2012-04-27 17:53:02 -0700
committerWinnie Hsu <whsu@nvidia.com>2012-05-24 22:47:35 -0700
commit133d3400a4cdc7433ea7811e089cf93112c53252 (patch)
tree64a5d27f2de139192e370c9b32f3a3ec253088ca
parent8a8dfa17de010d177cde894b921cb063cc2e901e (diff)
ARM: tegra2: clock: Put Tegra2 clocks to known states
Add TEGRA_PREINIT_CLOCKS option to put host1x, disp1, and video clocks into known state, so that L4T Ventana/Harmony works on u-boot. bug 967065 Change-Id: If7637b13e0daf1823fa0fe694a87870f4601e4df Signed-off-by: Jong Kim <jongk@nvidia.com> (cherry picked from commit df259e5b4e0692733e4ae362ea19de01d4b9a72f) Reviewed-on: http://git-master/r/104606 GVS: Gerrit_Virtual_Submit Reviewed-by: Winnie Hsu <whsu@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 126a1d56591a..7c207153a0e9 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -2897,11 +2897,170 @@ static struct syscore_ops tegra_clk_syscore_ops = {
.resume = tegra_clk_resume,
};
+#ifdef CONFIG_TEGRA_PREINIT_CLOCKS
+
+#define RST_DEVICES_L RST_DEVICES
+#define CLK_OUT_ENB_L 0x010
+#define CLK_RSTENB_L_HOST1X_BIT (1 << 28)
+#define CLK_RSTENB_L_DISP1_BIT (1 << 27)
+#define CLK_RSTENB_L_3D_BIT (1 << 24)
+#define CLK_RSTENB_L_2D_BIT (1 << 21)
+#define CLK_RSTENB_L_VI_BIT (1 << 20)
+#define CLK_RSTENB_L_EPP_BIT (1 << 19)
+
+#define RST_DEVICES_H 0x008
+#define CLK_OUT_ENB_H 0x014
+#define CLK_RSTENB_H_MPE_BIT (1 << 28)
+
+#define GCLK_SRC_SHIFT 30
+#define GCLK_SRC_MASK (0x3 << GCLK_SRC_SHIFT)
+#define GCLK_SRC_PLLM_OUT0 0
+#define GCLK_SRC_PLLC_OUT0 1
+#define GCLK_SRC_PLLP_OUT0 2
+#define GCLK_SRC_PLLA_OUT0 3
+#define GCLK_IDLE_DIV_SHIFT 8
+#define GCLK_IDLE_DIV_MASK (0xff << GCLK_IDLE_DIV_SHIFT)
+#define GCLK_DIV_SHIFT 0
+#define GCLK_DIV_MASK (0xff << GCLK_DIV_SHIFT)
+
+#define DISP1_CLK_REG 0x138
+#define DCLK_SRC_PLLP_OUT0 0
+#define DCLK_SRC_PLLD_OUT0 1
+#define DCLK_SRC_PLLC_OUT0 2
+#define DCLK_SRC_CLKM 3
+#define DISP1_CLK_SRC (DCLK_SRC_PLLC_OUT0 << GCLK_SRC_SHIFT)
+
+#define HOST1X_CLK_REG 0x180
+#define HOST1X_CLK_SRC (GCLK_SRC_PLLP_OUT0 << GCLK_SRC_SHIFT)
+#define HOST1X_CLK_IDLE_DIV (0 << GCLK_IDLE_DIV_SHIFT)
+#define HOST1X_CLK_DIV (3 << GCLK_DIV_SHIFT)
+
+#define G3D_CLK_REG 0x158
+#define G3D_CLK_SRC (GCLK_SRC_PLLC_OUT0 << GCLK_SRC_SHIFT)
+#define G3D_CLK_IDLE_DIV (0 << GCLK_IDLE_DIV_SHIFT)
+#define G3D_CLK_DIV (0xa << GCLK_DIV_SHIFT)
+
+#define G2D_CLK_REG 0x15c
+#define G2D_CLK_SRC (GCLK_SRC_PLLC_OUT0 << GCLK_SRC_SHIFT)
+#define G2D_CLK_IDLE_DIV (0 << GCLK_IDLE_DIV_SHIFT)
+#define G2D_CLK_DIV (0xa << GCLK_DIV_SHIFT)
+
+#define VI_CLK_REG 0x148
+#define VI_CLK_SRC (GCLK_SRC_PLLC_OUT0 << GCLK_SRC_SHIFT)
+#define VI_CLK_DIV (0xa << GCLK_DIV_SHIFT)
+
+#define EPP_CLK_REG 0x16c
+#define EPP_CLK_SRC (GCLK_SRC_PLLC_OUT0 << GCLK_SRC_SHIFT)
+#define EPP_CLK_DIV (0xa << GCLK_DIV_SHIFT)
+
+#define MPE_CLK_REG 0x170
+#define MPE_CLK_SRC (GCLK_SRC_PLLC_OUT0 << GCLK_SRC_SHIFT)
+#define MPE_CLK_DIV (0xa << GCLK_DIV_SHIFT)
+
+static void __init clk_setbit(u32 reg, u32 bit)
+{
+ u32 val = clk_readl(reg);
+
+ if ((val & bit) == bit)
+ return;
+ val |= bit;
+ clk_writel(val, reg);
+ udelay(2);
+}
+
+static void __init clk_clrbit(u32 reg, u32 bit)
+{
+ u32 val = clk_readl(reg);
+
+ if ((val & bit) == 0)
+ return;
+ val &= ~bit;
+ clk_writel(val, reg);
+ udelay(2);
+}
+
+static void __init clk_setbits(u32 reg, u32 bits, u32 mask)
+{
+ u32 val = clk_readl(reg);
+
+ if ((val & mask) == bits)
+ return;
+ val &= ~mask;
+ val |= bits;
+ clk_writel(val, reg);
+ udelay(2);
+}
+
+static int __init tegra_soc_preinit_clocks(void)
+{
+ /* vi: */
+ clk_setbit(RST_DEVICES_L, CLK_RSTENB_L_VI_BIT);
+ clk_setbit(CLK_OUT_ENB_L, CLK_RSTENB_L_VI_BIT);
+ clk_setbits(VI_CLK_REG, VI_CLK_SRC, GCLK_SRC_MASK);
+ clk_setbits(VI_CLK_REG, VI_CLK_DIV, GCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_L, CLK_RSTENB_L_VI_BIT);
+
+ /* 3d: */
+ clk_setbit(RST_DEVICES_L, CLK_RSTENB_L_3D_BIT);
+ clk_setbit(CLK_OUT_ENB_L, CLK_RSTENB_L_3D_BIT);
+ clk_setbits(G3D_CLK_REG, G3D_CLK_SRC, GCLK_SRC_MASK);
+ clk_setbits(G3D_CLK_REG, G3D_CLK_IDLE_DIV, GCLK_IDLE_DIV_MASK);
+ clk_setbits(G3D_CLK_REG, G3D_CLK_DIV, GCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_L, CLK_RSTENB_L_3D_BIT);
+
+ /* 2d: */
+ clk_setbit(RST_DEVICES_L, CLK_RSTENB_L_2D_BIT);
+ clk_setbit(CLK_OUT_ENB_L, CLK_RSTENB_L_2D_BIT);
+ clk_setbits(G2D_CLK_REG, G2D_CLK_SRC, GCLK_SRC_MASK);
+ clk_setbits(G2D_CLK_REG, G2D_CLK_IDLE_DIV, GCLK_IDLE_DIV_MASK);
+ clk_setbits(G2D_CLK_REG, G2D_CLK_DIV, GCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_L, CLK_RSTENB_L_2D_BIT);
+
+ /* epp: */
+ clk_setbit(RST_DEVICES_L, CLK_RSTENB_L_EPP_BIT);
+ clk_setbit(CLK_OUT_ENB_L, CLK_RSTENB_L_EPP_BIT);
+ clk_setbits(EPP_CLK_REG, EPP_CLK_SRC, GCLK_SRC_MASK);
+ clk_setbits(EPP_CLK_REG, EPP_CLK_DIV, GCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_L, CLK_RSTENB_L_EPP_BIT);
+
+ /* mpe: */
+ clk_setbit(RST_DEVICES_H, CLK_RSTENB_H_MPE_BIT);
+ clk_setbit(CLK_OUT_ENB_H, CLK_RSTENB_H_MPE_BIT);
+ clk_setbits(MPE_CLK_REG, MPE_CLK_SRC, GCLK_SRC_MASK);
+ clk_setbits(MPE_CLK_REG, MPE_CLK_DIV, GCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_H, CLK_RSTENB_H_MPE_BIT);
+
+ /*
+ * Make sure host1x clock configuration has:
+ * HOST1X_CLK_SRC : PLLP_OUT0.
+ * HOST1X_CLK_DIVISOR: >2 to start from safe enough frequency.
+ */
+ clk_setbit(RST_DEVICES_L, CLK_RSTENB_L_HOST1X_BIT);
+ clk_setbit(CLK_OUT_ENB_L, CLK_RSTENB_L_HOST1X_BIT);
+ clk_setbits(HOST1X_CLK_REG, HOST1X_CLK_DIV, GCLK_DIV_MASK);
+ clk_setbits(HOST1X_CLK_REG, HOST1X_CLK_IDLE_DIV, GCLK_IDLE_DIV_MASK);
+ clk_setbits(HOST1X_CLK_REG, HOST1X_CLK_SRC, GCLK_SRC_MASK);
+ clk_clrbit(RST_DEVICES_L, CLK_RSTENB_L_HOST1X_BIT);
+
+ /* DISP1_CLK_SRC: DCLK_SRC_PLLP_OUT0 */
+ clk_setbit(RST_DEVICES_L, CLK_RSTENB_L_DISP1_BIT);
+ clk_setbit(CLK_OUT_ENB_L, CLK_RSTENB_L_DISP1_BIT);
+ clk_setbits(DISP1_CLK_REG, DISP1_CLK_SRC, GCLK_SRC_MASK);
+ clk_clrbit(RST_DEVICES_L, CLK_RSTENB_L_DISP1_BIT);
+
+ return 0;
+}
+#endif /* CONFIG_TEGRA_PREINIT_CLOCKS */
+
void __init tegra_soc_init_clocks(void)
{
int i;
struct clk *c;
+#ifdef CONFIG_TEGRA_PREINIT_CLOCKS
+ tegra_soc_preinit_clocks();
+#endif /* CONFIG_TEGRA_PREINIT_CLOCKS */
+
for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
tegra2_init_one_clock(tegra_ptr_clks[i]);