aboutsummaryrefslogtreecommitdiff
path: root/src/soc/samsung/exynos5420/clock_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/samsung/exynos5420/clock_init.c')
-rw-r--r--src/soc/samsung/exynos5420/clock_init.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/soc/samsung/exynos5420/clock_init.c b/src/soc/samsung/exynos5420/clock_init.c
new file mode 100644
index 0000000000..cfac01e307
--- /dev/null
+++ b/src/soc/samsung/exynos5420/clock_init.c
@@ -0,0 +1,223 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Clock setup for SMDK5420 board based on EXYNOS5 */
+
+#include <delay.h>
+#include <console/console.h>
+#include "clk.h"
+#include "cpu.h"
+#include "dp.h"
+#include "dmc.h"
+#include "setup.h"
+
+void system_clock_init(void)
+{
+ u32 val;
+
+ /* Turn on the MCT as early as possible. */
+ exynos_mct->g_tcon |= (1 << 8);
+
+ /* PLL locktime */
+ writel(APLL_LOCK_VAL, &exynos_clock->apll_lock);
+ writel(MPLL_LOCK_VAL, &exynos_clock->mpll_lock);
+ writel(BPLL_LOCK_VAL, &exynos_clock->bpll_lock);
+ writel(CPLL_LOCK_VAL, &exynos_clock->cpll_lock);
+ writel(DPLL_LOCK_VAL, &exynos_clock->dpll_lock);
+ writel(EPLL_LOCK_VAL, &exynos_clock->epll_lock);
+ writel(VPLL_LOCK_VAL, &exynos_clock->vpll_lock);
+ writel(IPLL_LOCK_VAL, &exynos_clock->ipll_lock);
+ writel(SPLL_LOCK_VAL, &exynos_clock->spll_lock);
+ writel(KPLL_LOCK_VAL, &exynos_clock->kpll_lock);
+ writel(RPLL_LOCK_VAL, &exynos_clock->rpll_lock);
+
+ setbits_le32(&exynos_clock->clk_src_cpu, MUX_HPM_SEL_MASK);
+
+ writel(0, &exynos_clock->clk_src_top6);
+
+ writel(0, &exynos_clock->clk_src_cdrex);
+ writel(SRC_KFC_HPM_SEL, &exynos_clock->clk_src_kfc);
+ writel(HPM_RATIO, &exynos_clock->clk_div_cpu1);
+ writel(CLK_DIV_CPU0_VAL, &exynos_clock->clk_div_cpu0);
+
+ /* switch A15 clock source to OSC clock before changing APLL */
+ clrbits_le32(&exynos_clock->clk_src_cpu, APLL_FOUT);
+
+ /* Set APLL */
+ writel(APLL_CON1_VAL, &exynos_clock->apll_con1);
+ val = set_pll(225, 3, 0); /* FOUT=1800MHz */
+ writel(val, &exynos_clock->apll_con0);
+ while ((readl(&exynos_clock->apll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ /* now it is safe to switch to APLL */
+ setbits_le32(&exynos_clock->clk_src_cpu, APLL_FOUT);
+
+ writel(SRC_KFC_HPM_SEL, &exynos_clock->clk_src_kfc);
+ writel(CLK_DIV_KFC_VAL, &exynos_clock->clk_div_kfc0);
+
+ /* switch A7 clock source to OSC clock before changing KPLL */
+ clrbits_le32(&exynos_clock->clk_src_kfc, KPLL_FOUT);
+
+ /* Set KPLL*/
+ writel(KPLL_CON1_VAL, &exynos_clock->kpll_con1);
+ val = set_pll(0x190, 0x4, 0x2);
+ writel(val, &exynos_clock->kpll_con0);
+ while ((readl(&exynos_clock->kpll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ /* now it is safe to switch to KPLL */
+ setbits_le32(&exynos_clock->clk_src_kfc, KPLL_FOUT);
+
+ /* Set MPLL */
+ writel(MPLL_CON1_VAL, &exynos_clock->mpll_con1);
+ val = set_pll(0xc8, 0x3, 0x1);
+ writel(val, &exynos_clock->mpll_con0);
+ while ((readl(&exynos_clock->mpll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ /* Set DPLL */
+ writel(DPLL_CON1_VAL, &exynos_clock->dpll_con1);
+ val = set_pll(0x190, 0x4, 0x2);
+ writel(val, &exynos_clock->dpll_con0);
+ while ((readl(&exynos_clock->dpll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ /* Set EPLL */
+ writel(EPLL_CON2_VAL, &exynos_clock->epll_con2);
+ writel(EPLL_CON1_VAL, &exynos_clock->epll_con1);
+ val = set_pll(0x64, 0x2, 0x1);
+ writel(val, &exynos_clock->epll_con0);
+ while ((readl(&exynos_clock->epll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ /* Set CPLL */
+ writel(CPLL_CON1_VAL, &exynos_clock->cpll_con1);
+ val = set_pll(0xde, 0x4, 0x1);
+ writel(val, &exynos_clock->cpll_con0);
+ while ((readl(&exynos_clock->cpll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ /* Set IPLL */
+ writel(IPLL_CON1_VAL, &exynos_clock->ipll_con1);
+ val = set_pll(0xB9, 0x3, 0x2);
+ writel(val, &exynos_clock->ipll_con0);
+ while ((readl(&exynos_clock->ipll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ /* Set VPLL */
+ writel(VPLL_CON1_VAL, &exynos_clock->vpll_con1);
+ val = set_pll(0xd7, 0x3, 0x2);
+ writel(val, &exynos_clock->vpll_con0);
+ while ((readl(&exynos_clock->vpll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ /* Set BPLL */
+ writel(BPLL_CON1_VAL, &exynos_clock->bpll_con1);
+ val = set_pll(0xc8, 0x3, 0x1);
+ writel(val, &exynos_clock->bpll_con0);
+ while ((readl(&exynos_clock->bpll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ /* Set SPLL */
+ writel(SPLL_CON1_VAL, &exynos_clock->spll_con1);
+ val = set_pll(200, 0x3, 0x2); /* 400MHz */
+ writel(val, &exynos_clock->spll_con0);
+ while ((readl(&exynos_clock->spll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ /* We use RPLL as the source for FIMD video stream clock */
+ writel(RPLL_CON1_VAL, &exynos_clock->rpll_con1);
+ writel(RPLL_CON2_VAL, &exynos_clock->rpll_con2);
+ /* computed by gabe from first principles; u-boot is probably
+ * wrong again
+ */
+ val = set_pll(0xa0, 0x3, 0x2);
+ writel(val, &exynos_clock->rpll_con0);
+ /* note: this is a meaningless exercise. The hardware lock
+ * detection does not work. So this just spins for some
+ * time and is done. NO indication of success should attach
+ * to this or any other spin on a con0 value.
+ */
+ while ((readl(&exynos_clock->rpll_con0) & PLL_LOCKED) == 0)
+ ;
+
+ writel(CLK_DIV_CDREX0_VAL, &exynos_clock->clk_div_cdrex0);
+ writel(CLK_DIV_CDREX1_VAL, &exynos_clock->clk_div_cdrex1);
+
+ writel(CLK_SRC_TOP0_VAL, &exynos_clock->clk_src_top0);
+ writel(CLK_SRC_TOP1_VAL, &exynos_clock->clk_src_top1);
+ writel(CLK_SRC_TOP2_VAL, &exynos_clock->clk_src_top2);
+ writel(CLK_SRC_TOP7_VAL, &exynos_clock->clk_src_top7);
+
+ writel(CLK_DIV_TOP0_VAL, &exynos_clock->clk_div_top0);
+ writel(CLK_DIV_TOP1_VAL, &exynos_clock->clk_div_top1);
+ writel(CLK_DIV_TOP2_VAL, &exynos_clock->clk_div_top2);
+
+ writel(0, &exynos_clock->clk_src_top10);
+ writel(0, &exynos_clock->clk_src_top11);
+ writel(0, &exynos_clock->clk_src_top12);
+
+ writel(CLK_SRC_TOP3_VAL, &exynos_clock->clk_src_top3);
+ writel(CLK_SRC_TOP4_VAL, &exynos_clock->clk_src_top4);
+ writel(CLK_SRC_TOP5_VAL, &exynos_clock->clk_src_top5);
+
+ /* DISP1 BLK CLK SELECTION */
+ writel(CLK_SRC_DISP1_0_VAL, &exynos_clock->clk_src_disp10);
+ writel(CLK_DIV_DISP1_0_VAL, &exynos_clock->clk_div_disp10);
+
+ /* AUDIO BLK */
+ writel(AUDIO0_SEL_EPLL, &exynos_clock->clk_src_mau);
+ writel(DIV_MAU_VAL, &exynos_clock->clk_div_mau);
+
+ /* FSYS */
+ writel(CLK_SRC_FSYS0_VAL, &exynos_clock->clk_src_fsys);
+ writel(CLK_DIV_FSYS0_VAL, &exynos_clock->clk_div_fsys0);
+ writel(CLK_DIV_FSYS1_VAL, &exynos_clock->clk_div_fsys1);
+ writel(CLK_DIV_FSYS2_VAL, &exynos_clock->clk_div_fsys2);
+
+ writel(CLK_SRC_ISP_VAL, &exynos_clock->clk_src_isp);
+ writel(CLK_DIV_ISP0_VAL, &exynos_clock->clk_div_isp0);
+ writel(CLK_DIV_ISP1_VAL, &exynos_clock->clk_div_isp1);
+
+ writel(CLK_SRC_PERIC0_VAL, &exynos_clock->clk_src_peric0);
+ writel(CLK_SRC_PERIC1_VAL, &exynos_clock->clk_src_peric1);
+
+ writel(CLK_DIV_PERIC0_VAL, &exynos_clock->clk_div_peric0);
+ writel(CLK_DIV_PERIC1_VAL, &exynos_clock->clk_div_peric1);
+ writel(CLK_DIV_PERIC2_VAL, &exynos_clock->clk_div_peric2);
+ writel(CLK_DIV_PERIC3_VAL, &exynos_clock->clk_div_peric3);
+ writel(CLK_DIV_PERIC4_VAL, &exynos_clock->clk_div_peric4);
+
+ writel(CLK_DIV_CPERI1_VAL, &exynos_clock->clk_div_cperi1);
+
+ writel(CLK_DIV2_RATIO, &exynos_clock->clkdiv2_ratio);
+ writel(CLK_DIV4_RATIO, &exynos_clock->clkdiv4_ratio);
+ writel(CLK_DIV_G2D, &exynos_clock->clk_div_g2d);
+
+ writel(CLK_SRC_CPU_VAL, &exynos_clock->clk_src_cpu);
+ writel(CLK_SRC_TOP6_VAL, &exynos_clock->clk_src_top6);
+ writel(CLK_SRC_CDREX_VAL, &exynos_clock->clk_src_cdrex);
+ writel(CLK_SRC_KFC_VAL, &exynos_clock->clk_src_kfc);
+}
+
+void clock_gate(void)
+{
+ /* Not implemented for now. */
+}