[U-Boot] [PATCH 6/7] ARM: exynos: SPL support for exynos 4412
Simon Shields
simon at lineageos.org
Wed Sep 12 08:28:32 UTC 2018
This patch adds support for using u-boot's SPL in place of a proprietary
BL2 on exynos 4412 boards. This has been verified to work on both
exynos4412 boards (i9300 and i9305), and exynos4412-prime boards (n7100
and n7105), with one or two gigabytes of RAM. Using u-boot as SPL
requires an appropriate FWBL1 that does not verify the signature of BL2.
The majority of the configuration logic comes from the vendor u-boot drop,
while some was reverse-engineered from a proprietary bootloader.
Note that this patch does not initialise the exynos4412-prime clocks as
they're initialised by the proprietary bootloader - instead, they're
initialised to the same state as normal exynos4412 clocks.
Signed-off-by: Simon Shields <simon at lineageos.org>
---
arch/arm/mach-exynos/Kconfig | 6 +
arch/arm/mach-exynos/Makefile | 1 +
arch/arm/mach-exynos/clock_init_exynos4412.c | 122 ++++++
arch/arm/mach-exynos/dmc_init_exynos4412.c | 185 ++++++++
arch/arm/mach-exynos/exynos4412_setup.h | 425 +++++++++++++++++++
arch/arm/mach-exynos/power.c | 12 +
6 files changed, 751 insertions(+)
create mode 100644 arch/arm/mach-exynos/clock_init_exynos4412.c
create mode 100644 arch/arm/mach-exynos/dmc_init_exynos4412.c
create mode 100644 arch/arm/mach-exynos/exynos4412_setup.h
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index ed04369cfa..17eaf99724 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -42,6 +42,9 @@ endchoice
if ARCH_EXYNOS4
+config EXYNOS4412
+ bool
+
choice
prompt "EXYNOS4 board select"
@@ -59,12 +62,15 @@ config TARGET_S5PC210_UNIVERSAL
config TARGET_ORIGEN
bool "Exynos4412 Origen board"
select SUPPORT_SPL
+ select EXYNOS4412
config TARGET_TRATS2
bool "Exynos4412 Trat2 board"
+ select EXYNOS4412
config TARGET_ODROID
bool "Exynos4412 Odroid board"
+ select EXYNOS4412
endchoice
endif
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index ce88921868..5dcad9643b 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -13,6 +13,7 @@ ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o
obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o
obj-$(CONFIG_EXYNOS4210)+= dmc_init_exynos4210.o clock_init_exynos4210.o
+obj-$(CONFIG_EXYNOS4412)+= dmc_init_exynos4412.o clock_init_exynos4412.o
obj-y += spl_boot.o tzpc.o
obj-y += lowlevel_init.o
endif
diff --git a/arch/arm/mach-exynos/clock_init_exynos4412.c b/arch/arm/mach-exynos/clock_init_exynos4412.c
new file mode 100644
index 0000000000..140d8b3482
--- /dev/null
+++ b/arch/arm/mach-exynos/clock_init_exynos4412.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Clock initialisation for Exynos4412 based boards
+ *
+ * Copyright (C) 2018 Simon Shields <simon at lineageos.org>
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/power.h>
+#include "common_setup.h"
+#include "exynos4412_setup.h"
+
+static void reset_isp(void)
+{
+ struct exynos4412_power *pwr =
+ (struct exynos4412_power *)samsung_get_base_power();
+
+ /*
+ * This is needed on some SoC revisions
+ * to ensure that the ISP power domain is usable.
+ * It doesn't hurt to have it on SoC revisions where it's
+ * not needed, so we just do it on all.
+ */
+ writel(0, &pwr->cmu_reset_isp_sys_pwr_reg);
+ writel(0, &pwr->cmu_sysclk_isp_sys_pwr_reg);
+}
+
+void system_clock_init(void)
+{
+ struct exynos4x12_clock *clk =
+ (struct exynos4x12_clock *)samsung_get_base_clock();
+
+ reset_isp();
+
+ /* Switch clocks away from PLLs while we configure them */
+ writel(CLK_SRC_CPU_INIT, &clk->src_cpu);
+ writel(CLK_SRC_TOP0_INIT, &clk->src_top0);
+ writel(CLK_SRC_TOP1_INIT, &clk->src_top1);
+ writel(CLK_SRC_LEFTBUS_VAL, &clk->src_leftbus);
+ writel(CLK_SRC_RIGHTBUS_VAL, &clk->src_rightbus);
+ writel(CLK_SRC_PERIL0_VAL, &clk->src_peril0);
+ writel(CLK_SRC_LCD0_VAL, &clk->src_lcd);
+
+ sdelay(0x10000);
+
+ writel(CLK_DIV_DMC0_VAL, &clk->div_dmc0);
+ writel(CLK_DIV_DMC1_VAL, &clk->div_dmc1);
+ writel(CLK_DIV_TOP_VAL, &clk->div_top);
+ writel(CLK_DIV_LEFTBUS_VAL, &clk->div_leftbus);
+ writel(CLK_DIV_RIGHTBUS_VAL, &clk->div_rightbus);
+ writel(CLK_DIV_PERIL0_VAL, &clk->div_peril0);
+
+ /* PLLs */
+ writel(APLL_LOCK_VAL, &clk->apll_lock);
+ writel(MPLL_LOCK_VAL, &clk->mpll_lock);
+ writel(EPLL_LOCK_VAL, &clk->epll_lock);
+ writel(VPLL_LOCK_VAL, &clk->vpll_lock);
+
+ writel(CLK_DIV_CPU0_VAL, &clk->div_cpu0);
+ writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1);
+
+ /* APLL: 800MHz */
+ writel(APLL_CON1_VAL, &clk->apll_con1);
+ writel(APLL_CON0_VAL, &clk->apll_con0);
+
+ /*
+ * The iROM sets MPLL at 400MHz.
+ * Skip increasing MPLL if it's not at 400MHz
+ */
+ if (readl(&clk->mpll_con0) == 0xa0640301) {
+ /* MPLL: 800MHz */
+ writel(MPLL_CON1_VAL, &clk->mpll_con1);
+ writel(MPLL_CON0_VAL, &clk->mpll_con0);
+ }
+
+ /* EPLL: 96MHz */
+ writel(EPLL_CON2_VAL, &clk->epll_con2);
+ writel(EPLL_CON1_VAL, &clk->epll_con1);
+ writel(EPLL_CON0_VAL, &clk->epll_con0);
+
+ /* VPLL: 108MHz */
+ writel(VPLL_CON2_VAL, &clk->vpll_con2);
+ writel(VPLL_CON1_VAL, &clk->vpll_con1);
+ writel(VPLL_CON0_VAL, &clk->vpll_con0);
+
+ /* Stabilise */
+ sdelay(0x40000);
+
+ /* Now that PLLs are set up, use them. */
+ writel(CLK_SRC_CPU_PLLS, &clk->src_cpu);
+ writel(CLK_SRC_DMC_PLLS, &clk->src_dmc);
+ writel(CLK_SRC_TOP0_PLLS, &clk->src_top0);
+ writel(CLK_SRC_TOP1_PLLS, &clk->src_top1);
+
+ sdelay(0x10000);
+
+ /*
+ * In the SDMMC booting case, we need to reconfigure MMC clock
+ * to make the iROM happy.
+ */
+ u32 fsys2_div = readl(&clk->div_fsys2);
+ /* new MMC2 div is 16 */
+ fsys2_div |= 0xf;
+ writel(fsys2_div, &clk->div_fsys2);
+}
+
+void emmc_boot_clk_div_set(void)
+{
+ struct exynos4x12_clock *clk = (struct exynos4x12_clock *)
+ samsung_get_base_clock();
+ u32 div_fsys3 = readl(&clk->div_fsys3);
+
+ div_fsys3 &= ~(0xff0f);
+ div_fsys3 |= (1 << 8) | 0x7;
+
+ writel(div_fsys3, &clk->div_fsys3);
+}
diff --git a/arch/arm/mach-exynos/dmc_init_exynos4412.c b/arch/arm/mach-exynos/dmc_init_exynos4412.c
new file mode 100644
index 0000000000..a1efd09d02
--- /dev/null
+++ b/arch/arm/mach-exynos/dmc_init_exynos4412.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Simon Shields <simon at lineageos.org>
+ */
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/dmc.h>
+#include <asm/arch/power.h>
+#include <debug_uart.h>
+#include "common_setup.h"
+#include "exynos4412_setup.h"
+
+#define NR_TZASC_BANKS 4
+
+/* Allow non-secure and secure access to all memory */
+#define RA0_VAL 0xf0000000
+
+static void tzasc_init(void)
+{
+ unsigned int start = samsung_get_base_dmc_tzasc();
+ unsigned int end = start + (DMC_OFFSET * (NR_TZASC_BANKS - 1));
+
+ for (; start <= end; start += DMC_OFFSET) {
+ struct exynos4412_tzasc *asc = (struct exynos4412_tzasc *)start;
+
+ writel(RA0_VAL, &asc->region_attributes_0);
+ }
+}
+
+static int board_num_mem_chips(void)
+{
+ u32 pkgid = readl(EXYNOS4_PRO_ID + 4);
+
+ /* 2GB of RAM */
+ if ((pkgid & 0x30) == 0x10)
+ return 2;
+ return 1;
+}
+
+static void set_prime_stopctrl(void)
+{
+ struct exynos4x12_clock *clk = (struct exynos4x12_clock *)
+ samsung_get_base_clock();
+
+ /* PRE_WAIT_CNT, POST_WAIT_CNT = 0x1 */
+ writel(0x101, &clk->atclk_stopctrl);
+}
+
+static void do_directcmd(struct exynos4_dmc *dmc, u32 cmd, int chip, u32 delay)
+{
+ if (delay)
+ sdelay(delay);
+ if (chip)
+ cmd |= CMD_CHIP(1);
+
+ writel(cmd, &dmc->directcmd);
+}
+
+void mem_ctrl_init(int reset)
+{
+ struct exynos4_dmc *dmcs[2];
+ int chips = board_num_mem_chips();
+ int rev = exynos4412_get_rev();
+ u32 memcontrol = DMC_MEMCONTROL;
+ u32 prechconfig = 0x64000000;
+ u32 zqcontrol = DMC_PHYZQCONTROL;
+
+ dmcs[0] = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl();
+ dmcs[1] = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl()
+ + DMC_OFFSET);
+
+ if (rev == EXYNOS4412_REV_ZERO)
+ prechconfig |= 0xffff;
+ else if (rev == EXYNOS4412_REV_PRIME)
+ set_prime_stopctrl();
+
+ if (chips == 2) {
+ memcontrol |= MEM_2CHIPS;
+ zqcontrol |= CTRL_ZQ_MODE_DDS_2GB;
+ } else {
+ zqcontrol |= CTRL_ZQ_MODE_DDS_1GB;
+ }
+
+ for (int idx = 0; idx < ARRAY_SIZE(dmcs); idx++) {
+ struct exynos4_dmc *dmc = dmcs[idx];
+
+ writel(zqcontrol, &dmc->phyzqcontrol);
+ writel(PHYCONTROL0_VAL_INIT, &dmc->phycontrol0);
+ writel(PHYCONTROL0_VAL_INIT | CTRL_DLL_ON, &dmc->phycontrol0);
+
+ writel(PHYCONTROL1_VAL, &dmc->phycontrol1);
+ writel(PHYCONTROL0_VAL, &dmc->phycontrol0);
+ writel(PHYCONTROL1_VAL | FP_RESYNC, &dmc->phycontrol1);
+ writel(PHYCONTROL1_VAL, &dmc->phycontrol1);
+ writel(PHYCONTROL1_VAL | FP_RESYNC, &dmc->phycontrol1);
+ writel(PHYCONTROL1_VAL, &dmc->phycontrol1);
+
+ writel(DMC_CONCONTROL_INIT, &dmc->concontrol);
+ writel(memcontrol, &dmc->memcontrol);
+ /* map first gigabyte of RAM at 0x40000000 - 0x7fffffff */
+ writel(CHIP_BASE(0x40) | DMC_MEMCONFIG0, &dmc->memconfig0);
+
+ /* map second gigabyte at 0x80000000 - 0xbfffffff */
+ if (chips == 2)
+ writel(CHIP_BASE(0x80) | DMC_MEMCONFIG0,
+ &dmc->memconfig1);
+ writel(DMC_IVCONTROL, &dmc->ivcontrol);
+ writel(prechconfig, &dmc->prechconfig);
+ writel(PHYCONTROL0_VAL_STAGE2, &dmc->phycontrol0);
+
+ writel(T_REFI(0x5d), &dmc->timingref);
+
+ if (rev == EXYNOS4412_REV_PRIME) {
+ writel(T_RFC(0x3a) | T_RRD(0x5) | T_RP(0xa) | T_RCD(0x8)
+ | T_RC(0x1c) | T_RAS(0x13),
+ &dmc->timingrow);
+ writel(T_WTR(0x4) | T_WR(0x7) | T_RTP(0x4) | CL(0x0)
+ | WL(0x3) | RL(0x6), &dmc->timingdata);
+ writel(T_FAW(0x16) | T_XSR(0x3e) | T_XP(0x4)
+ | T_CKE(0x7) | T_MRD(0x5),
+ &dmc->timingpower);
+ } else {
+ u32 timingrow = T_RFC(0x34) | T_RP(0x9) | T_RCD(0x8)
+ | T_RC(0x1a) | T_RAS(0x11);
+ if (rev == EXYNOS4412_REV_ZERO)
+ timingrow |= T_RRD(0xa);
+ else
+ timingrow |= T_RRD(0x4);
+ writel(timingrow, &dmc->timingrow);
+ writel(T_WTR(0x3) | T_WR(0x6) | T_RTP(0x3) | CL(0x3)
+ | WL(0x3) | RL(0x6), &dmc->timingdata);
+ writel(T_FAW(0x14) | T_XSR(0x38) | T_XP(0x3)
+ | T_CKE(0x6) | T_MRD(0x5),
+ &dmc->timingpower);
+ }
+
+ for (int i = 0; i < chips; i++) {
+ do_directcmd(dmc, CMD_TYPE(0x7), i, 0x100000);
+ do_directcmd(dmc, CMD_TYPE(0x0) | CMD_BANK(0x7)
+ | CMD_ADDR(0x1c00), i, 0x100000);
+ do_directcmd(dmc, CMD_TYPE(0x0) | CMD_BANK(0x1)
+ | CMD_ADDR(0xbfc), i, 0x100000);
+ do_directcmd(dmc, CMD_TYPE(0x0) | CMD_BANK(0x0)
+ | CMD_ADDR(0x608), i, 0x100000);
+ do_directcmd(dmc, CMD_TYPE(0x0) | CMD_BANK(0x0)
+ | CMD_ADDR(0x810), i, 0);
+ do_directcmd(dmc, CMD_TYPE(0x0) | CMD_BANK(0x0)
+ | CMD_ADDR(0xc08), i, 0);
+ }
+ }
+
+ writel(PHYCONTROL0_VAL, &dmcs[0]->phycontrol0);
+ writel(MEM_TERM_EN | PHY_READ_EN | CTRL_SHGATE | CTRL_REF(8)
+ | CTRL_SHIFTC(4), &dmcs[0]->phycontrol1);
+ writel(PHYCONTROL0_VAL | CTRL_DLL_START, &dmcs[0]->phycontrol0);
+ sdelay(0x20000);
+
+ writel(CTRL_REF(8) | FP_RESYNC | CTRL_SHIFTC(4), &dmcs[0]->phycontrol1);
+ writel(CTRL_REF(8) | CTRL_SHIFTC(4), &dmcs[0]->phycontrol1);
+
+ sdelay(0x20000);
+
+ writel(PHYCONTROL0_VAL, &dmcs[1]->phycontrol0);
+ writel(MEM_TERM_EN | PHY_READ_EN | CTRL_SHGATE | CTRL_REF(8)
+ | CTRL_SHIFTC(4), &dmcs[1]->phycontrol1);
+ writel(PHYCONTROL0_VAL | CTRL_DLL_START, &dmcs[1]->phycontrol0);
+ sdelay(0x20000);
+
+ writel(CTRL_REF(8) | FP_RESYNC | CTRL_SHIFTC(4), &dmcs[1]->phycontrol1);
+ writel(CTRL_REF(8) | CTRL_SHIFTC(4), &dmcs[1]->phycontrol1);
+
+ sdelay(0x20000);
+
+ writel(DMC_CONCONTROL, &dmcs[0]->concontrol);
+ writel(DMC_CONCONTROL, &dmcs[1]->concontrol);
+
+ memcontrol |= DSREF_EN | TP_EN | DPWRDN_EN | CLK_STOP_EN;
+ writel(memcontrol, &dmcs[0]->memcontrol);
+ writel(memcontrol, &dmcs[1]->memcontrol);
+
+ tzasc_init();
+}
diff --git a/arch/arm/mach-exynos/exynos4412_setup.h b/arch/arm/mach-exynos/exynos4412_setup.h
new file mode 100644
index 0000000000..73ab75af7f
--- /dev/null
+++ b/arch/arm/mach-exynos/exynos4412_setup.h
@@ -0,0 +1,425 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2011 Samsung Electronics Co. Ltd
+ * Copyright (C) 2018 Simon Shields <simon at lineageos.org>
+ */
+
+#ifndef _EXYNOS4412_SETUP_H
+#define _EXYNOS4412_SETUP_H
+
+#include <config.h>
+#include <version.h>
+
+#include <asm/arch/cpu.h>
+
+#define EXYNOS4412_REV_ZERO 0x00
+#define EXYNOS4412_REV_MAIN 0x10
+#define EXYNOS4412_REV_PRIME 0x20
+#define EXYNOS4412_REV_MASK 0xf0
+
+static inline int exynos4412_get_rev(void)
+{
+ return readl(EXYNOS4_PRO_ID) & EXYNOS4412_REV_MASK;
+}
+
+/* CLK_DIV_CPU0 */
+#define CORE2_RATIO 0x0
+#define APLL_RATIO 0x1
+#define PCLK_DBG_RATIO 0x1
+#define ATB_RATIO 0x3
+#define PERIPH_RATIO 0x7
+#define COREM1_RATIO 0x5
+#define COREM0_RATIO 0x2
+#define CORE_RATIO 0x0
+
+/* CLK_DIV_CPU1 */
+#define CORES_RATIO 0x3
+#define HPM_RATIO 0x0
+#define COPY_RATIO 0x3
+
+#define CLK_DIV_CPU0_VAL ((CORE2_RATIO << 28) \
+ | (APLL_RATIO << 24) \
+ | (PCLK_DBG_RATIO << 20)\
+ | (ATB_RATIO << 16) \
+ | (PERIPH_RATIO << 12) \
+ | (COREM1_RATIO << 8) \
+ | (COREM0_RATIO << 4) \
+ | (CORE_RATIO))
+
+#define CLK_DIV_CPU1_VAL ((CORES_RATIO << 8) \
+ | (HPM_RATIO << 4) \
+ | (COPY_RATIO))
+/* APLL_CON1 / MPLL_CON1 */
+#define RESV1 (1 << 24)
+#define RESV0 (1 << 23)
+#define BYPASS (1 << 22)
+#define DCC_ENB (1 << 21) /* Active low */
+#define AFC_ENB (1 << 20) /* Active low */
+#define FEED_EN (1 << 16)
+#define LOCK_CON_OUT(x) ((x) << 14)
+#define LOCK_CON_IN(x) ((x) << 12)
+#define LOCK_CON_DLY(x) ((x) << 8)
+#define AFC(x) ((x) << 0)
+
+/* MPLL */
+/* 800MHz = (0x64) * 24000000 / (3 * (1 << 0)) */
+#define MPLL_MDIV 0x64
+#define MPLL_PDIV 0x3
+#define MPLL_SDIV 0x0
+#define MPLL_CON1_VAL (RESV0 | LOCK_CON_IN(3) | LOCK_CON_DLY(8))
+
+/* ARM_CLOCK/APLL */
+/* 800MHz = (0x64) * 24000000 / (3 * (1 << 0)) */
+#define APLL_MDIV 0x64
+#define APLL_PDIV 0x3
+#define APLL_SDIV 0x0
+#define APLL_CON1_VAL (RESV0 | LOCK_CON_IN(3) | LOCK_CON_DLY(8))
+
+/* EPLL_CON1 / VPLL_CON1 */
+#define SELF_PF(x) ((x) << 29)
+#define MRR(x) ((x) << 24)
+#define MFR(x) ((x) << 16)
+#define K(x) ((x) << 0)
+
+/* EPLL_CON2 / VPLL_CON2 */
+#define EXTAFC(x) ((x) << 8)
+#define DCC_ENB_EV (1 << 7) /* Active low */
+#define AFC_ENB_EV (1 << 6) /* Active low */
+#define SSCG_EN (1 << 5)
+#define BYPASS_EV (1 << 4)
+#define FVCO_EN (1 << 3)
+#define FSEL (1 << 2)
+#define ICP_BOOST(x) ((x) << 0)
+
+/* EPLL */
+/* Fout = (M + K/65536) * Fin / (P * (1 << S)) */
+/* 96MHz = (0x40) * 24000000 / (2 * (1 << 3)) */
+#define EPLL_MDIV 0x40
+#define EPLL_PDIV 0x2
+#define EPLL_SDIV 0x3
+
+#define EPLL_CON1_VAL SELF_PF(3) | MRR(6) | MFR(1)
+#define EPLL_CON2_VAL DCC_ENB_EV
+
+/* VPLL */
+#define VPLL_MDIV 0x48
+#define VPLL_PDIV 0x2
+#define VPLL_SDIV 0x3
+
+#define VPLL_CON1_VAL SELF_PF(3) | MRR(6) | MFR(1)
+#define VPLL_CON2_VAL DCC_ENB_EV
+
+/* Set PLL */
+#define set_pll(mdiv, pdiv, sdiv) ((1 << 31) | (mdiv << 16) \
+ | (pdiv << 8) | (sdiv))
+
+#define APLL_CON0_VAL set_pll(APLL_MDIV, APLL_PDIV, APLL_SDIV)
+#define MPLL_CON0_VAL set_pll(MPLL_MDIV, MPLL_PDIV, MPLL_SDIV)
+#define EPLL_CON0_VAL set_pll(EPLL_MDIV, EPLL_PDIV, EPLL_SDIV)
+#define VPLL_CON0_VAL set_pll(VPLL_MDIV, VPLL_PDIV, VPLL_SDIV)
+
+/* CLK_SRC_CPU */
+#define MUX_MPLL_USER_SEL_C(x) ((x) << 24) /* 0: FINPLL, 1: FOUTMPLL */
+#define MUX_HPM_SEL(x) ((x) << 20) /* 0: MOUTAPLL, 1: SCLKMPLL */
+#define MUX_CORE_SEL(x) ((x) << 16) /* 0: MOUTAPLL, 1: SCLKMPLL */
+#define MUX_APLL_SEL(x) ((x) << 0) /* 0: FINPLL, 1: MOUTAPLLFOUT */
+
+/* All clocks from XusbXTI */
+#define CLK_SRC_CPU_INIT (MUX_MPLL_USER_SEL_C(0) | MUX_HPM_SEL(0) \
+ | MUX_CORE_SEL(0) | MUX_APLL_SEL(0))
+
+#define CLK_SRC_CPU_PLLS (MUX_MPLL_USER_SEL_C(1) | MUX_APLL_SEL(1))
+
+/* CLK_SRC_DMC */
+#define MUX_PWI_SEL(x) ((x) << 16) /* 0: XXTI, 1: XusbXTI, ... */
+#define MUX_MPLL_SEL(x) ((x) << 12) /* 0: FINPLL, 1: MOUTMPLLFOUT */
+#define MUX_DPHY_SEL(x) ((x) << 8) /* 0: SCLKMPLL, 1: SCLKAPLL */
+#define MUX_DMC_BUS_SEL ((x) << 4) /* 0: SCLKMPLL, 1: SCLKAPLL */
+
+#define CLK_SRC_DMC_PLLS (MUX_PWI_SEL(1) | MUX_MPLL_SEL(1))
+
+/* CLK_DIV_DMC0 */
+#define CORE_TIMERS_RATIO 0x0
+#define COPY2_RATIO 0x0
+#define DMCP_RATIO 0x1
+#define DMCD_RATIO 0x1
+#define DMC_RATIO 0x7
+#define DPHY_RATIO 0x1
+#define ACP_PCLK_RATIO 0x1
+#define ACP_RATIO 0x7
+
+#define CLK_DIV_DMC0_VAL ((CORE_TIMERS_RATIO << 28) \
+ | (COPY2_RATIO << 24) \
+ | (DMCP_RATIO << 20) \
+ | (DMCD_RATIO << 16) \
+ | (DMC_RATIO << 12) \
+ | (DPHY_RATIO << 8) \
+ | (ACP_PCLK_RATIO << 4) \
+ | (ACP_RATIO))
+
+/* CLK_DIV_DMC1 */
+#define DPM_RATIO 0x7
+#define DVSEM_RATIO 0x7
+#define C2C_ACLK_RATIO 0x1
+#define PWI_RATIO 0x7
+#define C2C_RATIO 0x7
+#define G2D_ACP_RATIO 0x3
+
+#define CLK_DIV_DMC1_VAL ((DPM_RATIO << 24) \
+ | (DVSEM_RATIO << 16) \
+ | (C2C_ACLK_RATIO << 12) \
+ | (PWI_RATIO << 8) \
+ | (C2C_RATIO << 4) \
+ | (G2D_ACP_RATIO))
+
+/* CLK_SRC_TOP0 */
+#define MUX_ONENAND_SEL(x) ((x) << 28) /* 0 = DOUT133, 1 = DOUT166 */
+#define MUX_ACLK_133_SEL(x) ((x) << 24) /* 0 = SCLKMPLL, 1 = SCLKAPLL */
+#define MUX_ACLK_160_SEL(x) ((x) << 20) /* ditto */
+#define MUX_ACLK_100_SEL(x) ((x) << 16) /* ditto */
+#define MUX_ACLK_200_SEL(x) ((x) << 12) /* ditto */
+#define MUX_VPLL_SEL(x) ((x) << 8) /* 0: FINPLL, 1: FOUTVPLL */
+#define MUX_EPLL_SEL(x) ((x) << 4) /* 0: FINPLL, 1: FOUTEPLL */
+#define CLK_SRC_TOP0_INIT (MUX_ONENAND_SEL(0) \
+ | MUX_ACLK_133_SEL(0) \
+ | MUX_ACLK_160_SEL(0) \
+ | MUX_ACLK_100_SEL(0) \
+ | MUX_ACLK_200_SEL(0) \
+ | MUX_VPLL_SEL(0) \
+ | MUX_EPLL_SEL(0))
+
+#define CLK_SRC_TOP0_PLLS (MUX_VPLL_SEL(1) | MUX_EPLL_SEL(1))
+
+/* CLK_SRC_TOP1 */
+/* 0: FINPLL, 1: DIVOUT_ACLK_400_MCUISP */
+#define MUX_ACLK_400_MCUISP_SUB_SEL(x) ((x) << 24)
+/* 0: FINPLL, 1: DIVOUT_ACLK_200 */
+#define MUX_ACLK_200_SUB_SEL(x) ((x) << 20)
+/* 0: FINPLL, 1: DIVOUT_ACLK_266_GPS */
+#define MUX_ACLK_266_GPS_SUB_SEL(x) ((x) << 16)
+/* 0: FINPLL, 1: SCLKMPLL */
+#define MUX_MPLL_USER_T_SEL(x) ((x) << 12)
+/* 0: SCLKMPLL_USER_T, 1: SCLKAPLL */
+#define MUX_ACLK_400_MCUISP_SEL(x) ((x) << 8)
+/* 0: SCLKMPLL_USER_T, 1: SCLKAPLL */
+#define MUX_ACLK_266_GPS_SEL(x) ((x) << 4)
+
+#define CLK_SRC_TOP1_INIT (MUX_ACLK_400_MCUISP_SUB_SEL(0) \
+ | MUX_ACLK_200_SUB_SEL(0) \
+ | MUX_ACLK_266_GPS_SUB_SEL(0) \
+ | MUX_MPLL_USER_T_SEL(0))
+
+#define CLK_SRC_TOP1_PLLS (MUX_ACLK_266_GPS_SUB_SEL(1) | MUX_MPLL_USER_T_SEL(1))
+
+/* CLK_DIV_TOP */
+#define ACLK_400_MCUISP_RATIO 0x1
+#define ACLK_266_GPS_RATIO 0x2
+#define ONENAND_RATIO 0x1
+#define ACLK_133_RATIO 0x7
+#define ACLK_160_RATIO 0x4
+#define ACLK_100_RATIO 0xf
+#define ACLK_200_RATIO 0x4
+
+#define CLK_DIV_TOP_VAL ((ACLK_400_MCUISP_RATIO << 24) \
+ | (ACLK_266_GPS_RATIO << 20) \
+ | (ONENAND_RATIO << 16) \
+ | (ACLK_133_RATIO << 12) \
+ | (ACLK_160_RATIO << 8) \
+ | (ACLK_100_RATIO << 4) \
+ | (ACLK_200_RATIO))
+
+/* CLK_SRC_LEFTBUS */
+#define MUX_MPLL_USER_SEL_L(x) ((x) << 4) /* 0: FINPLL, 1: FOUTMPLL */
+#define MUX_GDL_SEL(x) ((x) << 0) /* 0: SCLKMPLL, 1: SCLKAPLL */
+#define CLK_SRC_LEFTBUS_VAL (MUX_MPLL_USER_SEL_L(1) | MUX_GDL_SEL(0))
+
+/* CLK_DIV_LEFTBUS */
+#define GPL_RATIO 0x1
+#define GDL_RATIO 0x7
+#define CLK_DIV_LEFTBUS_VAL ((GPL_RATIO << 4) \
+ | (GDL_RATIO))
+
+/* CLK_SRC_RIGHTBUS */
+#define MUX_MPLL_USER_SEL_R(x) ((x) << 4) /* 0: FINPLL, 1: FOUTMPLL */
+#define MUX_GDR_SEL(x) ((x) << 0) /* 0: SCLKMPLL, 1: SCLKAPLL */
+#define CLK_SRC_RIGHTBUS_VAL (MUX_MPLL_USER_SEL_R(1) | MUX_GDR_SEL(0))
+
+/* CLK_DIV_RIGHTBUS */
+#define GPR_RATIO 0x1
+#define GDR_RATIO 0x7
+#define CLK_DIV_RIGHTBUS_VAL ((GPR_RATIO << 4) \
+ | (GDR_RATIO))
+
+/* APLL_LOCK */
+#define APLL_LOCK_VAL (0x3E8)
+/* MPLL_LOCK */
+#define MPLL_LOCK_VAL (0x2F1)
+/* EPLL_LOCK */
+#define EPLL_LOCK_VAL (0x2321)
+/* VPLL_LOCK */
+#define VPLL_LOCK_VAL (0x2321)
+
+/* CLK_SRC_PERIL0 */
+#define UART4_SEL(x) ((x) << 16) /* 6: SCLK_MPLL_USER_T */
+#define UART3_SEL(x) ((x) << 12)
+#define UART2_SEL(x) ((x) << 8)
+#define UART1_SEL(x) ((x) << 4)
+#define UART0_SEL(x) ((x) << 0)
+#define CLK_SRC_PERIL0_VAL (UART4_SEL(6) \
+ | UART3_SEL(6) \
+ | UART2_SEL(6) \
+ | UART1_SEL(6) \
+ | UART0_SEL(6))
+
+/* CLK_DIV_PERIL0 */
+#define UART5_RATIO 8
+#define UART4_RATIO 8
+#define UART3_RATIO 8
+#define UART2_RATIO 8
+#define UART1_RATIO 8
+#define UART0_RATIO 8
+
+#define CLK_DIV_PERIL0_VAL ((UART5_RATIO << 20) \
+ | (UART4_RATIO << 16) \
+ | (UART3_RATIO << 12) \
+ | (UART2_RATIO << 8) \
+ | (UART1_RATIO << 4) \
+ | (UART0_RATIO))
+
+/* CLK_SRC_LCD0 */
+#define MIPI0_SEL(x) ((x) << 12) /* 1: XusbXTI */
+#define MDNIE_PWM0_SEL(x) ((x) << 8) /* 1: XusbXTI */
+#define MDNIE0_SEL(x) ((x) << 4) /* 6: SCLK_MPLL_USER_T */
+#define FIMD0_SEL(x) ((x) << 0) /* 6: SCLK_MPLL_USER_T */
+
+#define CLK_SRC_LCD0_VAL (MIPI0_SEL(0x1) \
+ | MDNIE_PWM0_SEL(0x1) \
+ | MDNIE0_SEL(0x6) \
+ | FIMD0_SEL(0x6))
+
+/* DMC PHYCONTROL0 */
+#define CTRL_FORCE(x) ((x) << 24)
+#define CTRL_INC(x) ((x) << 16)
+#define CTRL_START_POINT(x) ((x) << 8)
+#define DQS_DELAY(x) ((x) << 4)
+#define CTRL_DFDQS (0x1 << 3)
+#define CTRL_HALF (0x1 << 2)
+#define CTRL_DLL_ON (0x1 << 1)
+#define CTRL_DLL_START (0x1 << 0)
+
+/* CTRL_DLL_START will be ORd in when appropriate */
+#define PHYCONTROL0_VAL_INIT (CTRL_FORCE(0x71) | CTRL_INC(0x10) \
+ | CTRL_START_POINT(0x10) \
+ | CTRL_DFDQS)
+#define PHYCONTROL0_VAL_STAGE2 (CTRL_FORCE(0x9c) | CTRL_INC(0x40) \
+ | DQS_DELAY(0xf) | CTRL_DFDQS | CTRL_HALF \
+ | CTRL_DLL_ON | CTRL_DLL_START)
+#define PHYCONTROL0_VAL (CTRL_FORCE(0x7f) | CTRL_INC(0x10) \
+ | CTRL_START_POINT(0x10) \
+ | CTRL_DFDQS | CTRL_DLL_ON)
+
+/* DMC PHYCONTROL1 */
+#define MEM_TERM_EN (0x1 << 31)
+#define PHY_READ_EN (0x1 << 30)
+#define CTRL_SHGATE (0x1 << 29)
+#define CTRL_REF(x) (x << 4)
+#define FP_RESYNC (0x1 << 3)
+#define CTRL_SHIFTC(x) (x << 0)
+
+#define PHYCONTROL1_VAL (CTRL_REF(8) | CTRL_SHIFTC(4))
+
+/* DMC TIMINGREF */
+#define T_REFI(x) ((x) << 0)
+
+/* DMC TIMINGROW */
+#define T_RFC(x) ((x) << 24)
+#define T_RRD(x) ((x) << 20)
+#define T_RP(x) ((x) << 16)
+#define T_RCD(x) ((x) << 12)
+#define T_RC(x) ((x) << 6)
+#define T_RAS(x) ((x) << 0)
+
+/* DMC TIMINGDATA */
+#define T_WTR(x) ((x) << 28)
+#define T_WR(x) ((x) << 24)
+#define T_RTP(x) ((x) << 20)
+#define CL(x) ((x) << 16)
+#define WL(x) ((x) << 8)
+#define RL(x) ((x) << 0)
+
+/* DMC TIMINGPOWER */
+#define T_FAW(x) ((x) << 26)
+#define T_XSR(x) ((x) << 16)
+#define T_XP(x) ((x) << 8)
+#define T_CKE(x) ((x) << 4)
+#define T_MRD(x) ((x) << 0)
+
+/* DMC CONCONTROL */
+#define TIMEOUT_LEVEL0 (0xfff << 16)
+#define RD_FETCH (0x3 << 12)
+#define DRV_TYPE (0x3 << 6)
+#define AREF_EN (0x1 << 5)
+#define PDN_DQ_DISABLE (0x1 << 4)
+#define IO_PDN_CON (0x1 << 3)
+#define CLK_RATIO (0x1 << 1)
+
+#define DMC_CONCONTROL_INIT (TIMEOUT_LEVEL0 | RD_FETCH \
+ | DRV_TYPE | IO_PDN_CON | CLK_RATIO)
+
+#define DMC_CONCONTROL (TIMEOUT_LEVEL0 | RD_FETCH \
+ | DRV_TYPE | AREF_EN \
+ | PDN_DQ_DISABLE | IO_PDN_CON \
+ | CLK_RATIO)
+
+/* DMC MEMCONTROL */
+#define BURSTLEN (0x2 << 20)
+#define MEM_WIDTH (0x2 << 12)
+#define MEM_2CHIPS (0x1 << 16)
+#define MEM_TYPE (0x5 << 8) /* LPDDR2-S4 */
+#define DSREF_EN (0x1 << 5)
+#define TP_EN (0x1 << 4)
+#define DPWRDN_EN (0x1 << 1)
+#define CLK_STOP_EN (0x1 << 0)
+
+#define DMC_MEMCONTROL (BURSTLEN | MEM_WIDTH | MEM_TYPE)
+
+/* DMC MEMCONFIG0 */
+#define CHIP_BASE(x) ((x) << 24)
+#define CHIP_MASK (0xc0 << 16)
+#define CHIP_MAP (0x1 << 12)
+#define CHIP_COL (0x3 << 8)
+#define CHIP_ROW (0x2 << 4)
+#define CHIP_BANK (0x3 << 0)
+
+#define DMC_MEMCONFIG0 (CHIP_MASK | CHIP_MAP | CHIP_COL | CHIP_ROW | CHIP_BANK)
+
+/* DMC DIRECTCMD */
+#define CMD_TYPE(x) ((x) << 24)
+#define CMD_CHIP(x) ((x) << 20)
+#define CMD_BANK(x) ((x) << 16)
+#define CMD_ADDR(x) ((x) << 0)
+
+/* DMC_PHYZQCONTROL */
+#define CTRL_DCC (0xe38 << 20)
+#define CTRL_ZQ_FORCE_IMPP (0x2 << 17)
+#define CTRL_ZQ_FORCE_IMPN (0x5 << 14)
+#define CTRL_ZQ_MODE_TERM (0x2 << 11)
+#define CTRL_ZQ_MODE_DDS_1GB (0x4 << 8)
+#define CTRL_ZQ_MODE_DDS_2GB (0x5 << 8)
+#define CTRL_ZQ_DIV (0 << 4)
+#define CTRL_ZQ_FORCE (0 << 2)
+#define CTRL_ZQ_START (1 << 1)
+#define CTRL_ZQ_MODE_NOTTERM (1 << 0)
+
+#define DMC_PHYZQCONTROL (CTRL_DCC | CTRL_ZQ_FORCE_IMPP \
+ | CTRL_ZQ_FORCE_IMPN | CTRL_ZQ_MODE_TERM \
+ | CTRL_ZQ_DIV | CTRL_ZQ_FORCE | CTRL_ZQ_START \
+ | CTRL_ZQ_MODE_NOTTERM)
+
+/* DMC IVCONTROL */
+#define IV_ON (0x1 << 31)
+#define IV_SIZE_128B (0x7 << 0)
+
+#define DMC_IVCONTROL (IV_ON | IV_SIZE_128B)
+#endif
+
diff --git a/arch/arm/mach-exynos/power.c b/arch/arm/mach-exynos/power.c
index 63c410acef..a513b89551 100644
--- a/arch/arm/mach-exynos/power.c
+++ b/arch/arm/mach-exynos/power.c
@@ -162,6 +162,16 @@ static void exynos5_set_ps_hold_ctrl(void)
EXYNOS_PS_HOLD_CONTROL_DATA_HIGH);
}
+static void exynos4412_set_ps_hold_ctrl(void)
+{
+ struct exynos4412_power *power =
+ (struct exynos4412_power *)samsung_get_base_power();
+
+ /* Set PS-Hold high */
+ setbits_le32(&power->ps_hold_control,
+ EXYNOS_PS_HOLD_CONTROL_DATA_HIGH);
+}
+
/*
* Set ps_hold data driving value high
* This enables the machine to stay powered on
@@ -172,6 +182,8 @@ void set_ps_hold_ctrl(void)
{
if (cpu_is_exynos5())
exynos5_set_ps_hold_ctrl();
+ else if (proid_is_exynos4412())
+ exynos4412_set_ps_hold_ctrl();
}
--
2.18.0
More information about the U-Boot
mailing list