summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Wu <pengw@nvidia.com>2014-04-04 13:52:26 -0700
committerWinnie Hsu <whsu@nvidia.com>2014-09-24 16:19:23 -0700
commit9c595943ba23bfe46640b75fcf6c038f26bd32d8 (patch)
treeb6d4779822d33c71c507504742d6df7278166496
parent880a98b164b217b9cace66517c72e260b17e013c (diff)
ARM: tegra12: add clock preinit code for U-Boot
U-Boot doesn't setup clock as NVTBoot or fastboot, so clocks need to be preinit before our normal clock init. Bug 1482099 Change-Id: I5ad8dc7e61f1ad4864410a808c41298a91c7198f Signed-off-by: Bryan Wu <pengw@nvidia.com> Signed-off-by: Prabhu Kuttiyam <pkuttiyam@nvidia.com> Reviewed-on: http://git-master/r/408427 (cherry picked from commit 6682ca58527e47fe6db40855d2deba48a6d321d3) Reviewed-on: http://git-master/r/500873 Reviewed-by: Winnie Hsu <whsu@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/Kconfig7
-rw-r--r--arch/arm/mach-tegra/tegra12_clocks.c216
2 files changed, 223 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index f29663cf760e..71ecf93a1a4b 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -593,6 +593,13 @@ config TEGRA_SLOW_CSITE
When enabled, csite will be running at 1 Mhz and the performance of
jtag, lauterbach and other debugger will be extremely slow.
+config TEGRA_PREINIT_CLOCKS
+ bool "Preinitialize Tegra clocks to known states"
+ default n
+ help
+ Preinitialize Tegra clocks to known states before actual full-
+ scale clock initialization starts.
+
config TEGRA_PREPOWER_WIFI
bool "Pre-power up WiFi "
default n
diff --git a/arch/arm/mach-tegra/tegra12_clocks.c b/arch/arm/mach-tegra/tegra12_clocks.c
index a621bf490e84..7a8d2be1da60 100644
--- a/arch/arm/mach-tegra/tegra12_clocks.c
+++ b/arch/arm/mach-tegra/tegra12_clocks.c
@@ -9774,11 +9774,227 @@ static void tegra12_init_xusb_clocks(void)
tegra12_init_one_clock(&tegra_xusb_coupled_clks[i]);
}
+#ifdef CONFIG_TEGRA_PREINIT_CLOCKS
+
+#define CLK_RSTENB_DEV_V_0_AUDIO_BIT (1 << 10)
+#define CLK_RSTENB_DEV_V_0_3D2_BIT (1 << 2)
+
+#define CLK_RSTENB_DEV_L_0_HOST1X_BIT (1 << 28)
+#define CLK_RSTENB_DEV_L_0_DISP1_BIT (1 << 27)
+#define CLK_RSTENB_DEV_L_0_3D_BIT (1 << 24)
+#define CLK_RSTENB_DEV_L_0_ISP_BIT (1 << 23)
+#define CLK_RSTENB_DEV_L_0_2D_BIT (1 << 21)
+#define CLK_RSTENB_DEV_L_0_VI_BIT (1 << 20)
+#define CLK_RSTENB_DEV_L_0_EPP_BIT (1 << 19)
+
+#define CLK_RSTENB_DEV_H_0_VDE_BIT (1 << 29)
+#define CLK_RSTENB_DEV_H_0_MPE_BIT (1 << 28)
+
+#define CLK_RSTENB_DEV_U_0_CSITE_BIT (1 << 9)
+
+#define CLK_RSTENB_DEV_X_0_HDMI_AUDIO_BIT (1 << 16)
+
+#define HOST1X_CLK_REG_OFFSET 0x180
+#define HOST1X_CLK_SRC_SHIFT 30
+#define HOST1X_CLK_SRC_MASK (0x3 << HOST1X_CLK_SRC_SHIFT)
+#define HOST1X_CLK_SRC_PLLM_OUT0 0
+#define HOST1X_CLK_SRC_PLLC_OUT0 1
+#define HOST1X_CLK_SRC_PLLP_OUT0 2
+#define HOST1X_CLK_SRC_PLLA_OUT0 3
+#define HOST1X_CLK_SRC_DEFAULT (\
+ HOST1X_CLK_SRC_PLLP_OUT0 << HOST1X_CLK_SRC_SHIFT)
+#define HOST1X_CLK_IDLE_DIV_SHIFT 8
+#define HOST1X_CLK_IDLE_DIV_MASK (0xff << HOST1X_CLK_IDLE_DIV_SHIFT)
+#define HOST1X_CLK_IDLE_DIV_DEFAULT (0 << HOST1X_CLK_IDLE_DIV_SHIFT)
+#define HOST1X_CLK_DIV_SHIFT 0
+#define HOST1X_CLK_DIV_MASK (0xff << HOST1X_CLK_DIV_SHIFT)
+#define HOST1X_CLK_DIV_DEFAULT (3 << HOST1X_CLK_DIV_SHIFT)
+
+#define VCLK_SRC_SHIFT 30
+#define VCLK_SRC_MASK (0x3 << VCLK_SRC_SHIFT)
+#define VCLK_SRC_PLLM_OUT0 0
+#define VCLK_SRC_PLLC_OUT0 1
+#define VCLK_SRC_PLLP_OUT0 2
+#define VCLK_SRC_PLLA_OUT0 3
+#define VCLK_SRC_DEFAULT (VCLK_SRC_PLLM_OUT0 << VCLK_SRC_SHIFT)
+#define VCLK_IDLE_DIV_SHIFT 8
+#define VCLK_IDLE_DIV_MASK (0xff << VCLK_IDLE_DIV_SHIFT)
+#define VCLK_IDLE_DIV_DEFAULT (0 << VCLK_IDLE_DIV_SHIFT)
+#define VCLK_DIV_SHIFT 0
+#define VCLK_DIV_MASK (0xff << VCLK_DIV_SHIFT)
+#define VCLK_DIV_DEFAULT (0xa << VCLK_DIV_SHIFT)
+
+#define ISP_CLK_REG_OFFSET 0x144
+#define VI_CLK_REG_OFFSET 0x148
+#define VI_SENSOR_CLK_REG_OFFSET 0x1a8
+#define VI_SENSOR2_CLK_REG_OFFSET 0x658
+#define VI_CLK_DIV_DEFAULT (0x12 << VCLK_DIV_SHIFT)
+#define G3D_CLK_REG_OFFSET 0x158
+#define G2D_CLK_REG_OFFSET 0x15c
+#define EPP_CLK_REG_OFFSET 0x16c
+#define MPE_CLK_REG_OFFSET 0x170
+#define VDE_CLK_REG_OFFSET 0x170
+#define G3D2_CLK_REG_OFFSET 0x3b0
+#define HDMI_AUDIO_CLK_REG_OFFSET 0x668
+#define HDMI_AUDIO_CLK_DIV_DEFAULT (0x12 << VCLK_DIV_SHIFT)
+#define CSITE_CLK_REG_OFFSET 0x1d4
+#define CSITE_CLK_DIV_DEFAULT (0x4 << VCLK_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 void __init vclk_init(int tag, u32 src, u32 rebit)
+{
+ u32 rst, enb;
+
+ switch (tag) {
+ case 'L':
+ rst = RST_DEVICES_L;
+ enb = CLK_OUT_ENB_L;
+ break;
+ case 'H':
+ rst = RST_DEVICES_H;
+ enb = CLK_OUT_ENB_H;
+ break;
+ case 'U':
+ rst = RST_DEVICES_U;
+ enb = CLK_OUT_ENB_U;
+ break;
+ case 'V':
+ rst = RST_DEVICES_V;
+ enb = CLK_OUT_ENB_V;
+ break;
+ case 'W':
+ rst = RST_DEVICES_W;
+ enb = CLK_OUT_ENB_W;
+ break;
+ case 'X':
+ rst = RST_DEVICES_X;
+ enb = CLK_OUT_ENB_X;
+ break;
+ default:
+ /* Quietly ignore. */
+ return;
+ }
+
+ clk_setbit(rst, rebit);
+ clk_clrbit(enb, rebit);
+
+ clk_setbits(src, VCLK_SRC_DEFAULT, VCLK_SRC_MASK);
+ clk_setbits(src, VCLK_DIV_DEFAULT, VCLK_DIV_MASK);
+
+ clk_clrbit(rst, rebit);
+}
+
+static int __init tegra_soc_preinit_clocks(void)
+{
+ /*
+ * 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_DEV_L_0_HOST1X_BIT);
+ clk_setbit(CLK_OUT_ENB_L, CLK_RSTENB_DEV_L_0_HOST1X_BIT);
+ clk_setbits(HOST1X_CLK_REG_OFFSET,
+ HOST1X_CLK_DIV_DEFAULT, HOST1X_CLK_DIV_MASK);
+ clk_setbits(HOST1X_CLK_REG_OFFSET,
+ HOST1X_CLK_IDLE_DIV_DEFAULT, HOST1X_CLK_IDLE_DIV_MASK);
+ clk_setbits(HOST1X_CLK_REG_OFFSET,
+ HOST1X_CLK_SRC_DEFAULT, HOST1X_CLK_SRC_MASK);
+ clk_clrbit(RST_DEVICES_L, CLK_RSTENB_DEV_L_0_HOST1X_BIT);
+
+ /*
+ * Make sure vi clock configuration has:
+ * VI_CLK_DIVISOR: 0x12
+ * VI_SENSOR_CLK_DIVISOR: 0x12
+ * VI_SENSOR2_CLK_DIVISOR: 0x12
+ */
+ clk_setbit(RST_DEVICES_L, CLK_RSTENB_DEV_L_0_VI_BIT);
+ clk_setbit(CLK_OUT_ENB_L, CLK_RSTENB_DEV_L_0_VI_BIT);
+ clk_setbits(VI_CLK_REG_OFFSET,
+ VCLK_SRC_DEFAULT, VCLK_SRC_MASK);
+ clk_setbits(VI_CLK_REG_OFFSET, VI_CLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_setbits(VI_SENSOR_CLK_REG_OFFSET, VCLK_SRC_DEFAULT, VCLK_SRC_MASK);
+ clk_setbits(VI_SENSOR_CLK_REG_OFFSET,
+ VI_CLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_setbits(VI_SENSOR2_CLK_REG_OFFSET, VCLK_SRC_DEFAULT, VCLK_SRC_MASK);
+ clk_setbits(VI_SENSOR2_CLK_REG_OFFSET,
+ VI_CLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_L, CLK_RSTENB_DEV_L_0_VI_BIT);
+
+ /*
+ * Make sure hdmi_audio clock configuration has:
+ * HDMI_AUDIO_CLK_DIVISOR: 0x12
+ */
+ clk_setbit(RST_DEVICES_X, CLK_RSTENB_DEV_X_0_HDMI_AUDIO_BIT);
+ clk_setbit(CLK_OUT_ENB_X, CLK_RSTENB_DEV_X_0_HDMI_AUDIO_BIT);
+ clk_setbits(HDMI_AUDIO_CLK_REG_OFFSET,
+ HDMI_AUDIO_CLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_X, CLK_RSTENB_DEV_X_0_HDMI_AUDIO_BIT);
+
+ /*
+ * Make sure csite clock configuration has:
+ * CSITE_CLK_DIVISOR: 0x4
+ */
+ clk_setbit(RST_DEVICES_U, CLK_RSTENB_DEV_U_0_CSITE_BIT);
+ clk_setbit(CLK_OUT_ENB_U, CLK_RSTENB_DEV_U_0_CSITE_BIT);
+ clk_setbits(CSITE_CLK_REG_OFFSET, CSITE_CLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_U, CLK_RSTENB_DEV_U_0_CSITE_BIT);
+
+ /* Pre-initialize Video clocks. */
+ vclk_init('L', G3D_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_3D_BIT);
+ vclk_init('L', G2D_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_2D_BIT);
+ vclk_init('L', ISP_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_ISP_BIT);
+ vclk_init('L', EPP_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_EPP_BIT);
+ vclk_init('H', VDE_CLK_REG_OFFSET, CLK_RSTENB_DEV_H_0_VDE_BIT);
+ vclk_init('H', MPE_CLK_REG_OFFSET, CLK_RSTENB_DEV_H_0_MPE_BIT);
+ vclk_init('V', G3D2_CLK_REG_OFFSET, CLK_RSTENB_DEV_V_0_3D2_BIT);
+
+ return 0;
+}
+#endif /* CONFIG_TEGRA_PREINIT_CLOCKS */
+
void __init tegra12x_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++)
tegra12_init_one_clock(tegra_ptr_clks[i]);