diff options
Diffstat (limited to 'arch/arm/cpu/armv7/exynos')
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/Makefile | 15 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/clock.c | 43 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/clock_init.h | 154 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/clock_init_exynos4.c | 95 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/clock_init_exynos5.c | 684 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/common_setup.h | 45 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/dmc_common.c | 200 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 233 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/dmc_init_exynos4.c | 213 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/exynos4_setup.h | 594 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/exynos5_setup.h | 567 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/lowlevel_init.c | 73 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/pinmux.c | 40 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/power.c | 50 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/spl_boot.c | 203 | 
15 files changed, 3201 insertions, 8 deletions
| diff --git a/arch/arm/cpu/armv7/exynos/Makefile b/arch/arm/cpu/armv7/exynos/Makefile index b2f9152e1..466115559 100644 --- a/arch/arm/cpu/armv7/exynos/Makefile +++ b/arch/arm/cpu/armv7/exynos/Makefile @@ -22,10 +22,19 @@ include $(TOPDIR)/config.mk  LIB	= $(obj)lib$(SOC).o -COBJS	+= clock.o power.o soc.o system.o pinmux.o tzpc.o +COBJS-y	+= clock.o power.o soc.o system.o pinmux.o tzpc.o -SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS)) +ifdef CONFIG_SPL_BUILD +COBJS-$(CONFIG_EXYNOS5)	+= clock_init_exynos5.o +COBJS-$(CONFIG_EXYNOS5)	+= dmc_common.o dmc_init_ddr3.o +COBJS-$(CONFIG_EXYNOS4210)+= dmc_init_exynos4.o clock_init_exynos4.o +COBJS-y	+= spl_boot.o +COBJS-y	+= lowlevel_init.o +endif + +COBJS   := $(COBJS-y) +SRCS	:= $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS))  all:	 $(obj).depend $(LIB) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index e1c42462e..9f0718198 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -27,6 +27,10 @@  #include <asm/arch/clk.h>  #include <asm/arch/periph.h> +#define PLL_DIV_1024	1024 +#define PLL_DIV_65535	65535 +#define PLL_DIV_65536	65536 +  /* *   * This structure is to store the src bit, div bit and prediv bit   * positions of the peripheral clocks of the src and div registers @@ -85,6 +89,7 @@ static struct set_epll_con_val exynos5_epll_div[] = {  static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)  {  	unsigned long m, p, s = 0, mask, fout; +	unsigned int div;  	unsigned int freq;  	/*  	 * APLL_CON: MIDV [25:16] @@ -110,14 +115,42 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)  	if (pllreg == EPLL) {  		k = k & 0xffff;  		/* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */ -		fout = (m + k / 65536) * (freq / (p * (1 << s))); +		fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s)));  	} else if (pllreg == VPLL) {  		k = k & 0xfff; -		/* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */ -		fout = (m + k / 1024) * (freq / (p * (1 << s))); + +		/* +		 * Exynos4210 +		 * FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) +		 * +		 * Exynos4412 +		 * FOUT = (MDIV + K / 65535) * FIN / (PDIV * 2^SDIV) +		 * +		 * Exynos5250 +		 * FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) +		 */ +		if (proid_is_exynos4210()) +			div = PLL_DIV_1024; +		else if (proid_is_exynos4412()) +			div = PLL_DIV_65535; +		else if (proid_is_exynos5250()) +			div = PLL_DIV_65536; +		else +			return 0; + +		fout = (m + k / div) * (freq / (p * (1 << s)));  	} else { -		/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */ -		fout = m * (freq / (p * (1 << s))); +		/* +		 * Exynos4210 +		 * FOUT = MDIV * FIN / (PDIV * 2^SDIV) +		 * +		 * Exynos4412 / Exynos5250 +		 * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1)) +		 */ +		if (proid_is_exynos4210()) +			fout = m * (freq / (p * (1 << s))); +		else +			fout = m * (freq / (p * (1 << (s - 1))));  	}  	return fout; diff --git a/arch/arm/cpu/armv7/exynos/clock_init.h b/arch/arm/cpu/armv7/exynos/clock_init.h new file mode 100644 index 000000000..20a1d47e0 --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/clock_init.h @@ -0,0 +1,154 @@ +/* + * Clock initialization routines + * + * Copyright (c) 2011 The Chromium OS Authors. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __EXYNOS_CLOCK_INIT_H +#define __EXYNOS_CLOCK_INIT_H + +enum { +	MEM_TIMINGS_MSR_COUNT	= 4, +}; + +/* These are the ratio's for configuring ARM clock */ +struct arm_clk_ratios { +	unsigned arm_freq_mhz;		/* Frequency of ARM core in MHz */ + +	unsigned apll_mdiv; +	unsigned apll_pdiv; +	unsigned apll_sdiv; + +	unsigned arm2_ratio; +	unsigned apll_ratio; +	unsigned pclk_dbg_ratio; +	unsigned atb_ratio; +	unsigned periph_ratio; +	unsigned acp_ratio; +	unsigned cpud_ratio; +	unsigned arm_ratio; +}; + +/* These are the memory timings for a particular memory type and speed */ +struct mem_timings { +	enum mem_manuf mem_manuf;	/* Memory manufacturer */ +	enum ddr_mode mem_type;		/* Memory type */ +	unsigned frequency_mhz;		/* Frequency of memory in MHz */ + +	/* Here follow the timing parameters for the selected memory */ +	unsigned apll_mdiv; +	unsigned apll_pdiv; +	unsigned apll_sdiv; +	unsigned mpll_mdiv; +	unsigned mpll_pdiv; +	unsigned mpll_sdiv; +	unsigned cpll_mdiv; +	unsigned cpll_pdiv; +	unsigned cpll_sdiv; +	unsigned gpll_mdiv; +	unsigned gpll_pdiv; +	unsigned gpll_sdiv; +	unsigned epll_mdiv; +	unsigned epll_pdiv; +	unsigned epll_sdiv; +	unsigned vpll_mdiv; +	unsigned vpll_pdiv; +	unsigned vpll_sdiv; +	unsigned bpll_mdiv; +	unsigned bpll_pdiv; +	unsigned bpll_sdiv; +	unsigned pclk_cdrex_ratio; +	unsigned direct_cmd_msr[MEM_TIMINGS_MSR_COUNT]; + +	unsigned timing_ref; +	unsigned timing_row; +	unsigned timing_data; +	unsigned timing_power; + +	/* DQS, DQ, DEBUG offsets */ +	unsigned phy0_dqs; +	unsigned phy1_dqs; +	unsigned phy0_dq; +	unsigned phy1_dq; +	unsigned phy0_tFS; +	unsigned phy1_tFS; +	unsigned phy0_pulld_dqs; +	unsigned phy1_pulld_dqs; + +	unsigned lpddr3_ctrl_phy_reset; +	unsigned ctrl_start_point; +	unsigned ctrl_inc; +	unsigned ctrl_start; +	unsigned ctrl_dll_on; +	unsigned ctrl_ref; + +	unsigned ctrl_force; +	unsigned ctrl_rdlat; +	unsigned ctrl_bstlen; + +	unsigned fp_resync; +	unsigned iv_size; +	unsigned dfi_init_start; +	unsigned aref_en; + +	unsigned rd_fetch; + +	unsigned zq_mode_dds; +	unsigned zq_mode_term; +	unsigned zq_mode_noterm;	/* 1 to allow termination disable */ + +	unsigned memcontrol; +	unsigned memconfig; + +	unsigned membaseconfig0; +	unsigned membaseconfig1; +	unsigned prechconfig_tp_cnt; +	unsigned dpwrdn_cyc; +	unsigned dsref_cyc; +	unsigned concontrol; +	/* Channel and Chip Selection */ +	uint8_t dmc_channels;		/* number of memory channels */ +	uint8_t chips_per_channel;	/* number of chips per channel */ +	uint8_t chips_to_configure;	/* number of chips to configure */ +	uint8_t send_zq_init;		/* 1 to send this command */ +	unsigned impedance;		/* drive strength impedeance */ +	uint8_t gate_leveling_enable;	/* check gate leveling is enabled */ +}; + +/** + * Get the correct memory timings for our selected memory type and speed. + * + * This function can be called from SPL or the main U-Boot. + * + * @return pointer to the memory timings that we should use + */ +struct mem_timings *clock_get_mem_timings(void); + +/* + * Initialize clock for the device + */ +void system_clock_init(void); + +/* + * Set clock divisor value for booting from EMMC. + */ +void emmc_boot_clk_div_set(void); +#endif diff --git a/arch/arm/cpu/armv7/exynos/clock_init_exynos4.c b/arch/arm/cpu/armv7/exynos/clock_init_exynos4.c new file mode 100644 index 000000000..31610909f --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/clock_init_exynos4.c @@ -0,0 +1,95 @@ +/* + * Clock Initialization for board based on EXYNOS4210 + * + * Copyright (C) 2013 Samsung Electronics + * Rajeshwari Shinde <rajeshwari.s@samsung.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <version.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clk.h> +#include <asm/arch/clock.h> +#include "common_setup.h" +#include "exynos4_setup.h" + +/* + * system_clock_init: Initialize core clock and bus clock. + * void system_clock_init(void) + */ +void system_clock_init(void) +{ +	struct exynos4_clock *clk = +			(struct exynos4_clock *)samsung_get_base_clock(); + +	writel(CLK_SRC_CPU_VAL, &clk->src_cpu); + +	sdelay(0x10000); + +	writel(CLK_SRC_TOP0_VAL, &clk->src_top0); +	writel(CLK_SRC_TOP1_VAL, &clk->src_top1); +	writel(CLK_SRC_DMC_VAL, &clk->src_dmc); +	writel(CLK_SRC_LEFTBUS_VAL, &clk->src_leftbus); +	writel(CLK_SRC_RIGHTBUS_VAL, &clk->src_rightbus); +	writel(CLK_SRC_FSYS_VAL, &clk->src_fsys); +	writel(CLK_SRC_PERIL0_VAL, &clk->src_peril0); +	writel(CLK_SRC_CAM_VAL, &clk->src_cam); +	writel(CLK_SRC_MFC_VAL, &clk->src_mfc); +	writel(CLK_SRC_G3D_VAL, &clk->src_g3d); +	writel(CLK_SRC_LCD0_VAL, &clk->src_lcd0); + +	sdelay(0x10000); + +	writel(CLK_DIV_CPU0_VAL, &clk->div_cpu0); +	writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1); +	writel(CLK_DIV_DMC0_VAL, &clk->div_dmc0); +	writel(CLK_DIV_DMC1_VAL, &clk->div_dmc1); +	writel(CLK_DIV_LEFTBUS_VAL, &clk->div_leftbus); +	writel(CLK_DIV_RIGHTBUS_VAL, &clk->div_rightbus); +	writel(CLK_DIV_TOP_VAL, &clk->div_top); +	writel(CLK_DIV_FSYS1_VAL, &clk->div_fsys1); +	writel(CLK_DIV_FSYS2_VAL, &clk->div_fsys2); +	writel(CLK_DIV_FSYS3_VAL, &clk->div_fsys3); +	writel(CLK_DIV_PERIL0_VAL, &clk->div_peril0); +	writel(CLK_DIV_CAM_VAL, &clk->div_cam); +	writel(CLK_DIV_MFC_VAL, &clk->div_mfc); +	writel(CLK_DIV_G3D_VAL, &clk->div_g3d); +	writel(CLK_DIV_LCD0_VAL, &clk->div_lcd0); + +	/* Set PLL locktime */ +	writel(PLL_LOCKTIME, &clk->apll_lock); +	writel(PLL_LOCKTIME, &clk->mpll_lock); +	writel(PLL_LOCKTIME, &clk->epll_lock); +	writel(PLL_LOCKTIME, &clk->vpll_lock); + +	writel(APLL_CON1_VAL, &clk->apll_con1); +	writel(APLL_CON0_VAL, &clk->apll_con0); +	writel(MPLL_CON1_VAL, &clk->mpll_con1); +	writel(MPLL_CON0_VAL, &clk->mpll_con0); +	writel(EPLL_CON1_VAL, &clk->epll_con1); +	writel(EPLL_CON0_VAL, &clk->epll_con0); +	writel(VPLL_CON1_VAL, &clk->vpll_con1); +	writel(VPLL_CON0_VAL, &clk->vpll_con0); + +	sdelay(0x30000); +} diff --git a/arch/arm/cpu/armv7/exynos/clock_init_exynos5.c b/arch/arm/cpu/armv7/exynos/clock_init_exynos5.c new file mode 100644 index 000000000..0f9c57235 --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/clock_init_exynos5.c @@ -0,0 +1,684 @@ +/* + * Clock setup for SMDK5250 board based on EXYNOS5 + * + * Copyright (C) 2012 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/clk.h> +#include <asm/arch/clock.h> +#include <asm/arch/spl.h> +#include <asm/arch/dwmmc.h> + +#include "clock_init.h" +#include "common_setup.h" +#include "exynos5_setup.h" + +#define FSYS1_MMC0_DIV_MASK	0xff0f +#define FSYS1_MMC0_DIV_VAL	0x0701 + +DECLARE_GLOBAL_DATA_PTR; + +struct arm_clk_ratios arm_clk_ratios[] = { +	{ +		.arm_freq_mhz = 600, + +		.apll_mdiv = 0xc8, +		.apll_pdiv = 0x4, +		.apll_sdiv = 0x1, + +		.arm2_ratio = 0x0, +		.apll_ratio = 0x1, +		.pclk_dbg_ratio = 0x1, +		.atb_ratio = 0x2, +		.periph_ratio = 0x7, +		.acp_ratio = 0x7, +		.cpud_ratio = 0x1, +		.arm_ratio = 0x0, +	}, { +		.arm_freq_mhz = 800, + +		.apll_mdiv = 0x64, +		.apll_pdiv = 0x3, +		.apll_sdiv = 0x0, + +		.arm2_ratio = 0x0, +		.apll_ratio = 0x1, +		.pclk_dbg_ratio = 0x1, +		.atb_ratio = 0x3, +		.periph_ratio = 0x7, +		.acp_ratio = 0x7, +		.cpud_ratio = 0x2, +		.arm_ratio = 0x0, +	}, { +		.arm_freq_mhz = 1000, + +		.apll_mdiv = 0x7d, +		.apll_pdiv = 0x3, +		.apll_sdiv = 0x0, + +		.arm2_ratio = 0x0, +		.apll_ratio = 0x1, +		.pclk_dbg_ratio = 0x1, +		.atb_ratio = 0x4, +		.periph_ratio = 0x7, +		.acp_ratio = 0x7, +		.cpud_ratio = 0x2, +		.arm_ratio = 0x0, +	}, { +		.arm_freq_mhz = 1200, + +		.apll_mdiv = 0x96, +		.apll_pdiv = 0x3, +		.apll_sdiv = 0x0, + +		.arm2_ratio = 0x0, +		.apll_ratio = 0x3, +		.pclk_dbg_ratio = 0x1, +		.atb_ratio = 0x5, +		.periph_ratio = 0x7, +		.acp_ratio = 0x7, +		.cpud_ratio = 0x3, +		.arm_ratio = 0x0, +	}, { +		.arm_freq_mhz = 1400, + +		.apll_mdiv = 0xaf, +		.apll_pdiv = 0x3, +		.apll_sdiv = 0x0, + +		.arm2_ratio = 0x0, +		.apll_ratio = 0x3, +		.pclk_dbg_ratio = 0x1, +		.atb_ratio = 0x6, +		.periph_ratio = 0x7, +		.acp_ratio = 0x7, +		.cpud_ratio = 0x3, +		.arm_ratio = 0x0, +	}, { +		.arm_freq_mhz = 1700, + +		.apll_mdiv = 0x1a9, +		.apll_pdiv = 0x6, +		.apll_sdiv = 0x0, + +		.arm2_ratio = 0x0, +		.apll_ratio = 0x3, +		.pclk_dbg_ratio = 0x1, +		.atb_ratio = 0x6, +		.periph_ratio = 0x7, +		.acp_ratio = 0x7, +		.cpud_ratio = 0x3, +		.arm_ratio = 0x0, +	} +}; +struct mem_timings mem_timings[] = { +	{ +		.mem_manuf = MEM_MANUF_ELPIDA, +		.mem_type = DDR_MODE_DDR3, +		.frequency_mhz = 800, +		.mpll_mdiv = 0xc8, +		.mpll_pdiv = 0x3, +		.mpll_sdiv = 0x0, +		.cpll_mdiv = 0xde, +		.cpll_pdiv = 0x4, +		.cpll_sdiv = 0x2, +		.gpll_mdiv = 0x215, +		.gpll_pdiv = 0xc, +		.gpll_sdiv = 0x1, +		.epll_mdiv = 0x60, +		.epll_pdiv = 0x3, +		.epll_sdiv = 0x3, +		.vpll_mdiv = 0x96, +		.vpll_pdiv = 0x3, +		.vpll_sdiv = 0x2, + +		.bpll_mdiv = 0x64, +		.bpll_pdiv = 0x3, +		.bpll_sdiv = 0x0, +		.pclk_cdrex_ratio = 0x5, +		.direct_cmd_msr = { +			0x00020018, 0x00030000, 0x00010042, 0x00000d70 +		}, +		.timing_ref = 0x000000bb, +		.timing_row = 0x8c36650e, +		.timing_data = 0x3630580b, +		.timing_power = 0x41000a44, +		.phy0_dqs = 0x08080808, +		.phy1_dqs = 0x08080808, +		.phy0_dq = 0x08080808, +		.phy1_dq = 0x08080808, +		.phy0_tFS = 0x4, +		.phy1_tFS = 0x4, +		.phy0_pulld_dqs = 0xf, +		.phy1_pulld_dqs = 0xf, + +		.lpddr3_ctrl_phy_reset = 0x1, +		.ctrl_start_point = 0x10, +		.ctrl_inc = 0x10, +		.ctrl_start = 0x1, +		.ctrl_dll_on = 0x1, +		.ctrl_ref = 0x8, + +		.ctrl_force = 0x1a, +		.ctrl_rdlat = 0x0b, +		.ctrl_bstlen = 0x08, + +		.fp_resync = 0x8, +		.iv_size = 0x7, +		.dfi_init_start = 1, +		.aref_en = 1, + +		.rd_fetch = 0x3, + +		.zq_mode_dds = 0x7, +		.zq_mode_term = 0x1, +		.zq_mode_noterm = 0, + +		/* +		* Dynamic Clock: Always Running +		* Memory Burst length: 8 +		* Number of chips: 1 +		* Memory Bus width: 32 bit +		* Memory Type: DDR3 +		* Additional Latancy for PLL: 0 Cycle +		*/ +		.memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE | +			DMC_MEMCONTROL_DPWRDN_DISABLE | +			DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE | +			DMC_MEMCONTROL_TP_DISABLE | +			DMC_MEMCONTROL_DSREF_ENABLE | +			DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) | +			DMC_MEMCONTROL_MEM_TYPE_DDR3 | +			DMC_MEMCONTROL_MEM_WIDTH_32BIT | +			DMC_MEMCONTROL_NUM_CHIP_1 | +			DMC_MEMCONTROL_BL_8 | +			DMC_MEMCONTROL_PZQ_DISABLE | +			DMC_MEMCONTROL_MRR_BYTE_7_0, +		.memconfig = DMC_MEMCONFIGX_CHIP_MAP_INTERLEAVED | +			DMC_MEMCONFIGX_CHIP_COL_10 | +			DMC_MEMCONFIGX_CHIP_ROW_15 | +			DMC_MEMCONFIGX_CHIP_BANK_8, +		.membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40), +		.membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80), +		.prechconfig_tp_cnt = 0xff, +		.dpwrdn_cyc = 0xff, +		.dsref_cyc = 0xffff, +		.concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE | +			DMC_CONCONTROL_TIMEOUT_LEVEL0 | +			DMC_CONCONTROL_RD_FETCH_DISABLE | +			DMC_CONCONTROL_EMPTY_DISABLE | +			DMC_CONCONTROL_AREF_EN_DISABLE | +			DMC_CONCONTROL_IO_PD_CON_DISABLE, +		.dmc_channels = 2, +		.chips_per_channel = 2, +		.chips_to_configure = 1, +		.send_zq_init = 1, +		.impedance = IMP_OUTPUT_DRV_30_OHM, +		.gate_leveling_enable = 0, +	}, { +		.mem_manuf = MEM_MANUF_SAMSUNG, +		.mem_type = DDR_MODE_DDR3, +		.frequency_mhz = 800, +		.mpll_mdiv = 0xc8, +		.mpll_pdiv = 0x3, +		.mpll_sdiv = 0x0, +		.cpll_mdiv = 0xde, +		.cpll_pdiv = 0x4, +		.cpll_sdiv = 0x2, +		.gpll_mdiv = 0x215, +		.gpll_pdiv = 0xc, +		.gpll_sdiv = 0x1, +		.epll_mdiv = 0x60, +		.epll_pdiv = 0x3, +		.epll_sdiv = 0x3, +		.vpll_mdiv = 0x96, +		.vpll_pdiv = 0x3, +		.vpll_sdiv = 0x2, + +		.bpll_mdiv = 0x64, +		.bpll_pdiv = 0x3, +		.bpll_sdiv = 0x0, +		.pclk_cdrex_ratio = 0x5, +		.direct_cmd_msr = { +			0x00020018, 0x00030000, 0x00010000, 0x00000d70 +		}, +		.timing_ref = 0x000000bb, +		.timing_row = 0x8c36650e, +		.timing_data = 0x3630580b, +		.timing_power = 0x41000a44, +		.phy0_dqs = 0x08080808, +		.phy1_dqs = 0x08080808, +		.phy0_dq = 0x08080808, +		.phy1_dq = 0x08080808, +		.phy0_tFS = 0x8, +		.phy1_tFS = 0x8, +		.phy0_pulld_dqs = 0xf, +		.phy1_pulld_dqs = 0xf, + +		.lpddr3_ctrl_phy_reset = 0x1, +		.ctrl_start_point = 0x10, +		.ctrl_inc = 0x10, +		.ctrl_start = 0x1, +		.ctrl_dll_on = 0x1, +		.ctrl_ref = 0x8, + +		.ctrl_force = 0x1a, +		.ctrl_rdlat = 0x0b, +		.ctrl_bstlen = 0x08, + +		.fp_resync = 0x8, +		.iv_size = 0x7, +		.dfi_init_start = 1, +		.aref_en = 1, + +		.rd_fetch = 0x3, + +		.zq_mode_dds = 0x5, +		.zq_mode_term = 0x1, +		.zq_mode_noterm = 1, + +		/* +		* Dynamic Clock: Always Running +		* Memory Burst length: 8 +		* Number of chips: 1 +		* Memory Bus width: 32 bit +		* Memory Type: DDR3 +		* Additional Latancy for PLL: 0 Cycle +		*/ +		.memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE | +			DMC_MEMCONTROL_DPWRDN_DISABLE | +			DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE | +			DMC_MEMCONTROL_TP_DISABLE | +			DMC_MEMCONTROL_DSREF_ENABLE | +			DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) | +			DMC_MEMCONTROL_MEM_TYPE_DDR3 | +			DMC_MEMCONTROL_MEM_WIDTH_32BIT | +			DMC_MEMCONTROL_NUM_CHIP_1 | +			DMC_MEMCONTROL_BL_8 | +			DMC_MEMCONTROL_PZQ_DISABLE | +			DMC_MEMCONTROL_MRR_BYTE_7_0, +		.memconfig = DMC_MEMCONFIGX_CHIP_MAP_INTERLEAVED | +			DMC_MEMCONFIGX_CHIP_COL_10 | +			DMC_MEMCONFIGX_CHIP_ROW_15 | +			DMC_MEMCONFIGX_CHIP_BANK_8, +		.membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40), +		.membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80), +		.prechconfig_tp_cnt = 0xff, +		.dpwrdn_cyc = 0xff, +		.dsref_cyc = 0xffff, +		.concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE | +			DMC_CONCONTROL_TIMEOUT_LEVEL0 | +			DMC_CONCONTROL_RD_FETCH_DISABLE | +			DMC_CONCONTROL_EMPTY_DISABLE | +			DMC_CONCONTROL_AREF_EN_DISABLE | +			DMC_CONCONTROL_IO_PD_CON_DISABLE, +		.dmc_channels = 2, +		.chips_per_channel = 2, +		.chips_to_configure = 1, +		.send_zq_init = 1, +		.impedance = IMP_OUTPUT_DRV_40_OHM, +		.gate_leveling_enable = 1, +	} +}; + +/** + * Get the required memory type and speed (SPL version). + * + * In SPL we have no device tree, so we use the machine parameters + * + * @param mem_type	Returns memory type + * @param frequency_mhz	Returns memory speed in MHz + * @param arm_freq	Returns ARM clock speed in MHz + * @param mem_manuf	Return Memory Manufacturer name + */ +static void clock_get_mem_selection(enum ddr_mode *mem_type, +		unsigned *frequency_mhz, unsigned *arm_freq, +		enum mem_manuf *mem_manuf) +{ +	struct spl_machine_param *params; + +	params = spl_get_machine_params(); +	*mem_type = params->mem_type; +	*frequency_mhz = params->frequency_mhz; +	*arm_freq = params->arm_freq_mhz; +	*mem_manuf = params->mem_manuf; +} + +/* Get the ratios for setting ARM clock */ +struct arm_clk_ratios *get_arm_ratios(void) +{ +	struct arm_clk_ratios *arm_ratio; +	enum ddr_mode mem_type; +	enum mem_manuf mem_manuf; +	unsigned frequency_mhz, arm_freq; +	int i; + +	clock_get_mem_selection(&mem_type, &frequency_mhz, +				&arm_freq, &mem_manuf); + +	for (i = 0, arm_ratio = arm_clk_ratios; i < ARRAY_SIZE(arm_clk_ratios); +		i++, arm_ratio++) { +		if (arm_ratio->arm_freq_mhz == arm_freq) +			return arm_ratio; +	} + +	/* will hang if failed to find clock ratio */ +	while (1) +		; + +	return NULL; +} + +struct mem_timings *clock_get_mem_timings(void) +{ +	struct mem_timings *mem; +	enum ddr_mode mem_type; +	enum mem_manuf mem_manuf; +	unsigned frequency_mhz, arm_freq; +	int i; + +	clock_get_mem_selection(&mem_type, &frequency_mhz, +				&arm_freq, &mem_manuf); +	for (i = 0, mem = mem_timings; i < ARRAY_SIZE(mem_timings); +	     i++, mem++) { +		if (mem->mem_type == mem_type && +		    mem->frequency_mhz == frequency_mhz && +		    mem->mem_manuf == mem_manuf) +			return mem; +	} + +	/* will hang if failed to find memory timings */ +	while (1) +		; + +	return NULL; +} + +void system_clock_init() +{ +	struct exynos5_clock *clk = +		(struct exynos5_clock *)samsung_get_base_clock(); +	struct mem_timings *mem; +	struct arm_clk_ratios *arm_clk_ratio; +	u32 val, tmp; + +	mem = clock_get_mem_timings(); +	arm_clk_ratio = get_arm_ratios(); + +	clrbits_le32(&clk->src_cpu, MUX_APLL_SEL_MASK); +	do { +		val = readl(&clk->mux_stat_cpu); +	} while ((val | MUX_APLL_SEL_MASK) != val); + +	clrbits_le32(&clk->src_core1, MUX_MPLL_SEL_MASK); +	do { +		val = readl(&clk->mux_stat_core1); +	} while ((val | MUX_MPLL_SEL_MASK) != val); + +	clrbits_le32(&clk->src_top2, MUX_CPLL_SEL_MASK); +	clrbits_le32(&clk->src_top2, MUX_EPLL_SEL_MASK); +	clrbits_le32(&clk->src_top2, MUX_VPLL_SEL_MASK); +	clrbits_le32(&clk->src_top2, MUX_GPLL_SEL_MASK); +	tmp = MUX_CPLL_SEL_MASK | MUX_EPLL_SEL_MASK | MUX_VPLL_SEL_MASK +		| MUX_GPLL_SEL_MASK; +	do { +		val = readl(&clk->mux_stat_top2); +	} while ((val | tmp) != val); + +	clrbits_le32(&clk->src_cdrex, MUX_BPLL_SEL_MASK); +	do { +		val = readl(&clk->mux_stat_cdrex); +	} while ((val | MUX_BPLL_SEL_MASK) != val); + +	/* PLL locktime */ +	writel(APLL_LOCK_VAL, &clk->apll_lock); + +	writel(MPLL_LOCK_VAL, &clk->mpll_lock); + +	writel(BPLL_LOCK_VAL, &clk->bpll_lock); + +	writel(CPLL_LOCK_VAL, &clk->cpll_lock); + +	writel(GPLL_LOCK_VAL, &clk->gpll_lock); + +	writel(EPLL_LOCK_VAL, &clk->epll_lock); + +	writel(VPLL_LOCK_VAL, &clk->vpll_lock); + +	writel(CLK_REG_DISABLE, &clk->pll_div2_sel); + +	writel(MUX_HPM_SEL_MASK, &clk->src_cpu); +	do { +		val = readl(&clk->mux_stat_cpu); +	} while ((val | HPM_SEL_SCLK_MPLL) != val); + +	val = arm_clk_ratio->arm2_ratio << 28 +		| arm_clk_ratio->apll_ratio << 24 +		| arm_clk_ratio->pclk_dbg_ratio << 20 +		| arm_clk_ratio->atb_ratio << 16 +		| arm_clk_ratio->periph_ratio << 12 +		| arm_clk_ratio->acp_ratio << 8 +		| arm_clk_ratio->cpud_ratio << 4 +		| arm_clk_ratio->arm_ratio; +	writel(val, &clk->div_cpu0); +	do { +		val = readl(&clk->div_stat_cpu0); +	} while (0 != val); + +	writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1); +	do { +		val = readl(&clk->div_stat_cpu1); +	} while (0 != val); + +	/* Set APLL */ +	writel(APLL_CON1_VAL, &clk->apll_con1); +	val = set_pll(arm_clk_ratio->apll_mdiv, arm_clk_ratio->apll_pdiv, +			arm_clk_ratio->apll_sdiv); +	writel(val, &clk->apll_con0); +	while ((readl(&clk->apll_con0) & APLL_CON0_LOCKED) == 0) +		; + +	/* Set MPLL */ +	writel(MPLL_CON1_VAL, &clk->mpll_con1); +	val = set_pll(mem->mpll_mdiv, mem->mpll_pdiv, mem->mpll_sdiv); +	writel(val, &clk->mpll_con0); +	while ((readl(&clk->mpll_con0) & MPLL_CON0_LOCKED) == 0) +		; + +	/* Set BPLL */ +	writel(BPLL_CON1_VAL, &clk->bpll_con1); +	val = set_pll(mem->bpll_mdiv, mem->bpll_pdiv, mem->bpll_sdiv); +	writel(val, &clk->bpll_con0); +	while ((readl(&clk->bpll_con0) & BPLL_CON0_LOCKED) == 0) +		; + +	/* Set CPLL */ +	writel(CPLL_CON1_VAL, &clk->cpll_con1); +	val = set_pll(mem->cpll_mdiv, mem->cpll_pdiv, mem->cpll_sdiv); +	writel(val, &clk->cpll_con0); +	while ((readl(&clk->cpll_con0) & CPLL_CON0_LOCKED) == 0) +		; + +	/* Set GPLL */ +	writel(GPLL_CON1_VAL, &clk->gpll_con1); +	val = set_pll(mem->gpll_mdiv, mem->gpll_pdiv, mem->gpll_sdiv); +	writel(val, &clk->gpll_con0); +	while ((readl(&clk->gpll_con0) & GPLL_CON0_LOCKED) == 0) +		; + +	/* Set EPLL */ +	writel(EPLL_CON2_VAL, &clk->epll_con2); +	writel(EPLL_CON1_VAL, &clk->epll_con1); +	val = set_pll(mem->epll_mdiv, mem->epll_pdiv, mem->epll_sdiv); +	writel(val, &clk->epll_con0); +	while ((readl(&clk->epll_con0) & EPLL_CON0_LOCKED) == 0) +		; + +	/* Set VPLL */ +	writel(VPLL_CON2_VAL, &clk->vpll_con2); +	writel(VPLL_CON1_VAL, &clk->vpll_con1); +	val = set_pll(mem->vpll_mdiv, mem->vpll_pdiv, mem->vpll_sdiv); +	writel(val, &clk->vpll_con0); +	while ((readl(&clk->vpll_con0) & VPLL_CON0_LOCKED) == 0) +		; + +	writel(CLK_SRC_CORE0_VAL, &clk->src_core0); +	writel(CLK_DIV_CORE0_VAL, &clk->div_core0); +	while (readl(&clk->div_stat_core0) != 0) +		; + +	writel(CLK_DIV_CORE1_VAL, &clk->div_core1); +	while (readl(&clk->div_stat_core1) != 0) +		; + +	writel(CLK_DIV_SYSRGT_VAL, &clk->div_sysrgt); +	while (readl(&clk->div_stat_sysrgt) != 0) +		; + +	writel(CLK_DIV_ACP_VAL, &clk->div_acp); +	while (readl(&clk->div_stat_acp) != 0) +		; + +	writel(CLK_DIV_SYSLFT_VAL, &clk->div_syslft); +	while (readl(&clk->div_stat_syslft) != 0) +		; + +	writel(CLK_SRC_TOP0_VAL, &clk->src_top0); +	writel(CLK_SRC_TOP1_VAL, &clk->src_top1); +	writel(TOP2_VAL, &clk->src_top2); +	writel(CLK_SRC_TOP3_VAL, &clk->src_top3); + +	writel(CLK_DIV_TOP0_VAL, &clk->div_top0); +	while (readl(&clk->div_stat_top0)) +		; + +	writel(CLK_DIV_TOP1_VAL, &clk->div_top1); +	while (readl(&clk->div_stat_top1)) +		; + +	writel(CLK_SRC_LEX_VAL, &clk->src_lex); +	while (1) { +		val = readl(&clk->mux_stat_lex); +		if (val == (val | 1)) +			break; +	} + +	writel(CLK_DIV_LEX_VAL, &clk->div_lex); +	while (readl(&clk->div_stat_lex)) +		; + +	writel(CLK_DIV_R0X_VAL, &clk->div_r0x); +	while (readl(&clk->div_stat_r0x)) +		; + +	writel(CLK_DIV_R0X_VAL, &clk->div_r0x); +	while (readl(&clk->div_stat_r0x)) +		; + +	writel(CLK_DIV_R1X_VAL, &clk->div_r1x); +	while (readl(&clk->div_stat_r1x)) +		; + +	writel(CLK_REG_DISABLE, &clk->src_cdrex); + +	writel(CLK_DIV_CDREX_VAL, &clk->div_cdrex); +	while (readl(&clk->div_stat_cdrex)) +		; + +	val = readl(&clk->src_cpu); +	val |= CLK_SRC_CPU_VAL; +	writel(val, &clk->src_cpu); + +	val = readl(&clk->src_top2); +	val |= CLK_SRC_TOP2_VAL; +	writel(val, &clk->src_top2); + +	val = readl(&clk->src_core1); +	val |= CLK_SRC_CORE1_VAL; +	writel(val, &clk->src_core1); + +	writel(CLK_SRC_FSYS0_VAL, &clk->src_fsys); +	writel(CLK_DIV_FSYS0_VAL, &clk->div_fsys0); +	while (readl(&clk->div_stat_fsys0)) +		; + +	writel(CLK_REG_DISABLE, &clk->clkout_cmu_cpu); +	writel(CLK_REG_DISABLE, &clk->clkout_cmu_core); +	writel(CLK_REG_DISABLE, &clk->clkout_cmu_acp); +	writel(CLK_REG_DISABLE, &clk->clkout_cmu_top); +	writel(CLK_REG_DISABLE, &clk->clkout_cmu_lex); +	writel(CLK_REG_DISABLE, &clk->clkout_cmu_r0x); +	writel(CLK_REG_DISABLE, &clk->clkout_cmu_r1x); +	writel(CLK_REG_DISABLE, &clk->clkout_cmu_cdrex); + +	writel(CLK_SRC_PERIC0_VAL, &clk->src_peric0); +	writel(CLK_DIV_PERIC0_VAL, &clk->div_peric0); + +	writel(CLK_SRC_PERIC1_VAL, &clk->src_peric1); +	writel(CLK_DIV_PERIC1_VAL, &clk->div_peric1); +	writel(CLK_DIV_PERIC2_VAL, &clk->div_peric2); +	writel(CLK_DIV_PERIC3_VAL, &clk->div_peric3); + +	writel(SCLK_SRC_ISP_VAL, &clk->sclk_src_isp); +	writel(SCLK_DIV_ISP_VAL, &clk->sclk_div_isp); +	writel(CLK_DIV_ISP0_VAL, &clk->div_isp0); +	writel(CLK_DIV_ISP1_VAL, &clk->div_isp1); +	writel(CLK_DIV_ISP2_VAL, &clk->div_isp2); + +	/* FIMD1 SRC CLK SELECTION */ +	writel(CLK_SRC_DISP1_0_VAL, &clk->src_disp1_0); + +	val = MMC2_PRE_RATIO_VAL << MMC2_PRE_RATIO_OFFSET +		| MMC2_RATIO_VAL << MMC2_RATIO_OFFSET +		| MMC3_PRE_RATIO_VAL << MMC3_PRE_RATIO_OFFSET +		| MMC3_RATIO_VAL << MMC3_RATIO_OFFSET; +	writel(val, &clk->div_fsys2); +} + +void clock_init_dp_clock(void) +{ +	struct exynos5_clock *clk = +		(struct exynos5_clock *)samsung_get_base_clock(); + +	/* DP clock enable */ +	setbits_le32(&clk->gate_ip_disp1, CLK_GATE_DP1_ALLOW); + +	/* We run DP at 267 Mhz */ +	setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1); +} + +/* + * Set clock divisor value for booting from EMMC. + * Set DWMMC channel-0 clk div to operate mmc0 device at 50MHz. + */ +void emmc_boot_clk_div_set(void) +{ +	struct exynos5_clock *clk = +		(struct exynos5_clock *)samsung_get_base_clock(); +	unsigned int div_mmc; + +	div_mmc = readl((unsigned int) &clk->div_fsys1) & ~FSYS1_MMC0_DIV_MASK; +	div_mmc |= FSYS1_MMC0_DIV_VAL; +	writel(div_mmc, (unsigned int) &clk->div_fsys1); +} diff --git a/arch/arm/cpu/armv7/exynos/common_setup.h b/arch/arm/cpu/armv7/exynos/common_setup.h new file mode 100644 index 000000000..e6318c036 --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/common_setup.h @@ -0,0 +1,45 @@ +/* + * Common APIs for EXYNOS based board + * + * Copyright (C) 2013 Samsung Electronics + * Rajeshwari Shinde <rajeshwari.s@samsung.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#define DMC_OFFSET	0x10000 + +/* + * Memory initialization + * + * @param reset     Reset PHY during initialization. + */ +void mem_ctrl_init(int reset); + + /* System Clock initialization */ +void system_clock_init(void); + +/* + * Init subsystems according to the reset status + * + * @return 0 for a normal boot, non-zero for a resume + */ +int do_lowlevel_init(void); + +void sdelay(unsigned long); diff --git a/arch/arm/cpu/armv7/exynos/dmc_common.c b/arch/arm/cpu/armv7/exynos/dmc_common.c new file mode 100644 index 000000000..645f57e5b --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/dmc_common.c @@ -0,0 +1,200 @@ +/* + * Mem setup common file for different types of DDR present on SMDK5250 boards. + * + * Copyright (C) 2012 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/arch/spl.h> + +#include "clock_init.h" +#include "common_setup.h" +#include "exynos5_setup.h" + +#define ZQ_INIT_TIMEOUT	10000 + +int dmc_config_zq(struct mem_timings *mem, +		  struct exynos5_phy_control *phy0_ctrl, +		  struct exynos5_phy_control *phy1_ctrl) +{ +	unsigned long val = 0; +	int i; + +	/* +	 * ZQ Calibration: +	 * Select Driver Strength, +	 * long calibration for manual calibration +	 */ +	val = PHY_CON16_RESET_VAL; +	val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT; +	val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT; +	val |= ZQ_CLK_DIV_EN; +	writel(val, &phy0_ctrl->phy_con16); +	writel(val, &phy1_ctrl->phy_con16); + +	/* Disable termination */ +	if (mem->zq_mode_noterm) +		val |= PHY_CON16_ZQ_MODE_NOTERM_MASK; +	writel(val, &phy0_ctrl->phy_con16); +	writel(val, &phy1_ctrl->phy_con16); + +	/* ZQ_MANUAL_START: Enable */ +	val |= ZQ_MANUAL_STR; +	writel(val, &phy0_ctrl->phy_con16); +	writel(val, &phy1_ctrl->phy_con16); + +	/* ZQ_MANUAL_START: Disable */ +	val &= ~ZQ_MANUAL_STR; + +	/* +	 * Since we are manaully calibrating the ZQ values, +	 * we are looping for the ZQ_init to complete. +	 */ +	i = ZQ_INIT_TIMEOUT; +	while ((readl(&phy0_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { +		sdelay(100); +		i--; +	} +	if (!i) +		return -1; +	writel(val, &phy0_ctrl->phy_con16); + +	i = ZQ_INIT_TIMEOUT; +	while ((readl(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { +		sdelay(100); +		i--; +	} +	if (!i) +		return -1; +	writel(val, &phy1_ctrl->phy_con16); + +	return 0; +} + +void update_reset_dll(struct exynos5_dmc *dmc, enum ddr_mode mode) +{ +	unsigned long val; + +	if (mode == DDR_MODE_DDR3) { +		val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE; +		writel(val, &dmc->phycontrol0); +	} + +	/* Update DLL Information: Force DLL Resyncronization */ +	val = readl(&dmc->phycontrol0); +	val |= FP_RSYNC; +	writel(val, &dmc->phycontrol0); + +	/* Reset Force DLL Resyncronization */ +	val = readl(&dmc->phycontrol0); +	val &= ~FP_RSYNC; +	writel(val, &dmc->phycontrol0); +} + +void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) +{ +	int channel, chip; + +	for (channel = 0; channel < mem->dmc_channels; channel++) { +		unsigned long mask; + +		mask = channel << DIRECT_CMD_CHANNEL_SHIFT; +		for (chip = 0; chip < mem->chips_to_configure; chip++) { +			int i; + +			mask |= chip << DIRECT_CMD_CHIP_SHIFT; + +			/* Sending NOP command */ +			writel(DIRECT_CMD_NOP | mask, &dmc->directcmd); + +			/* +			 * TODO(alim.akhtar@samsung.com): Do we need these +			 * delays? This one and the next were not there for +			 * DDR3. +			 */ +			sdelay(0x10000); + +			/* Sending EMRS/MRS commands */ +			for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) { +				writel(mem->direct_cmd_msr[i] | mask, +				       &dmc->directcmd); +				sdelay(0x10000); +			} + +			if (mem->send_zq_init) { +				/* Sending ZQINIT command */ +				writel(DIRECT_CMD_ZQINIT | mask, +				       &dmc->directcmd); + +				sdelay(10000); +			} +		} +	} +} + +void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc) +{ +	int channel, chip; + +	for (channel = 0; channel < mem->dmc_channels; channel++) { +		unsigned long mask; + +		mask = channel << DIRECT_CMD_CHANNEL_SHIFT; +		for (chip = 0; chip < mem->chips_per_channel; chip++) { +			mask |= chip << DIRECT_CMD_CHIP_SHIFT; + +			/* PALL (all banks precharge) CMD */ +			writel(DIRECT_CMD_PALL | mask, &dmc->directcmd); +			sdelay(0x10000); +		} +	} +} + +void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc) +{ +	writel(mem->memconfig, &dmc->memconfig0); +	writel(mem->memconfig, &dmc->memconfig1); +	writel(DMC_MEMBASECONFIG0_VAL, &dmc->membaseconfig0); +	writel(DMC_MEMBASECONFIG1_VAL, &dmc->membaseconfig1); +} + +void mem_ctrl_init(int reset) +{ +	struct spl_machine_param *param = spl_get_machine_params(); +	struct mem_timings *mem; +	int ret; + +	mem = clock_get_mem_timings(); + +	/* If there are any other memory variant, add their init call below */ +	if (param->mem_type == DDR_MODE_DDR3) { +		ret = ddr3_mem_ctrl_init(mem, param->mem_iv_size, reset); +		if (ret) { +			/* will hang if failed to init memory control */ +			while (1) +				; +		} +	} else { +		/* will hang if unknow memory type  */ +		while (1) +			; +	} +} diff --git a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c new file mode 100644 index 000000000..e03d74b78 --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c @@ -0,0 +1,233 @@ +/* + * DDR3 mem setup file for SMDK5250 board based on EXYNOS5 + * + * Copyright (C) 2012 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/cpu.h> +#include <asm/arch/dmc.h> +#include "common_setup.h" +#include "exynos5_setup.h" +#include "clock_init.h" + +#define RDLVL_COMPLETE_TIMEOUT	10000 + +static void reset_phy_ctrl(void) +{ +	struct exynos5_clock *clk = +		(struct exynos5_clock *)samsung_get_base_clock(); + +	writel(DDR3PHY_CTRL_PHY_RESET_OFF, &clk->lpddr3phy_ctrl); +	writel(DDR3PHY_CTRL_PHY_RESET, &clk->lpddr3phy_ctrl); +} + +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, +		       int reset) +{ +	unsigned int val; +	struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl; +	struct exynos5_dmc *dmc; +	int i; + +	phy0_ctrl = (struct exynos5_phy_control *)samsung_get_base_dmc_phy(); +	phy1_ctrl = (struct exynos5_phy_control *)(samsung_get_base_dmc_phy() +							+ DMC_OFFSET); +	dmc = (struct exynos5_dmc *)samsung_get_base_dmc_ctrl(); + +	if (reset) +		reset_phy_ctrl(); + +	/* Set Impedance Output Driver */ +	val = (mem->impedance << CA_CK_DRVR_DS_OFFSET) | +		(mem->impedance << CA_CKE_DRVR_DS_OFFSET) | +		(mem->impedance << CA_CS_DRVR_DS_OFFSET) | +		(mem->impedance << CA_ADR_DRVR_DS_OFFSET); +	writel(val, &phy0_ctrl->phy_con39); +	writel(val, &phy1_ctrl->phy_con39); + +	/* Set Read Latency and Burst Length for PHY0 and PHY1 */ +	val = (mem->ctrl_bstlen << PHY_CON42_CTRL_BSTLEN_SHIFT) | +		(mem->ctrl_rdlat << PHY_CON42_CTRL_RDLAT_SHIFT); +	writel(val, &phy0_ctrl->phy_con42); +	writel(val, &phy1_ctrl->phy_con42); + +	/* ZQ Calibration */ +	if (dmc_config_zq(mem, phy0_ctrl, phy1_ctrl)) +		return SETUP_ERR_ZQ_CALIBRATION_FAILURE; + +	/* DQ Signal */ +	writel(mem->phy0_pulld_dqs, &phy0_ctrl->phy_con14); +	writel(mem->phy1_pulld_dqs, &phy1_ctrl->phy_con14); + +	writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT) +		| (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT), +		&dmc->concontrol); + +	update_reset_dll(dmc, DDR_MODE_DDR3); + +	/* DQS Signal */ +	writel(mem->phy0_dqs, &phy0_ctrl->phy_con4); +	writel(mem->phy1_dqs, &phy1_ctrl->phy_con4); + +	writel(mem->phy0_dq, &phy0_ctrl->phy_con6); +	writel(mem->phy1_dq, &phy1_ctrl->phy_con6); + +	writel(mem->phy0_tFS, &phy0_ctrl->phy_con10); +	writel(mem->phy1_tFS, &phy1_ctrl->phy_con10); + +	val = (mem->ctrl_start_point << PHY_CON12_CTRL_START_POINT_SHIFT) | +		(mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | +		(mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) | +		(mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); +	writel(val, &phy0_ctrl->phy_con12); +	writel(val, &phy1_ctrl->phy_con12); + +	/* Start DLL locking */ +	writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT), +	       &phy0_ctrl->phy_con12); +	writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT), +	       &phy1_ctrl->phy_con12); + +	update_reset_dll(dmc, DDR_MODE_DDR3); + +	writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), +	       &dmc->concontrol); + +	/* Memory Channel Inteleaving Size */ +	writel(mem->iv_size, &dmc->ivcontrol); + +	writel(mem->memconfig, &dmc->memconfig0); +	writel(mem->memconfig, &dmc->memconfig1); +	writel(mem->membaseconfig0, &dmc->membaseconfig0); +	writel(mem->membaseconfig1, &dmc->membaseconfig1); + +	/* Precharge Configuration */ +	writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, +	       &dmc->prechconfig); + +	/* Power Down mode Configuration */ +	writel(mem->dpwrdn_cyc << PWRDNCONFIG_DPWRDN_CYC_SHIFT | +		mem->dsref_cyc << PWRDNCONFIG_DSREF_CYC_SHIFT, +		&dmc->pwrdnconfig); + +	/* TimingRow, TimingData, TimingPower and Timingaref +	 * values as per Memory AC parameters +	 */ +	writel(mem->timing_ref, &dmc->timingref); +	writel(mem->timing_row, &dmc->timingrow); +	writel(mem->timing_data, &dmc->timingdata); +	writel(mem->timing_power, &dmc->timingpower); + +	/* Send PALL command */ +	dmc_config_prech(mem, dmc); + +	/* Send NOP, MRS and ZQINIT commands */ +	dmc_config_mrs(mem, dmc); + +	if (mem->gate_leveling_enable) { +		val = PHY_CON0_RESET_VAL; +		val |= P0_CMD_EN; +		writel(val, &phy0_ctrl->phy_con0); +		writel(val, &phy1_ctrl->phy_con0); + +		val = PHY_CON2_RESET_VAL; +		val |= INIT_DESKEW_EN; +		writel(val, &phy0_ctrl->phy_con2); +		writel(val, &phy1_ctrl->phy_con2); + +		val = PHY_CON0_RESET_VAL; +		val |= P0_CMD_EN; +		val |= BYTE_RDLVL_EN; +		writel(val, &phy0_ctrl->phy_con0); +		writel(val, &phy1_ctrl->phy_con0); + +		val = (mem->ctrl_start_point << +				PHY_CON12_CTRL_START_POINT_SHIFT) | +			(mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | +			(mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) | +			(mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) | +			(mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); +		writel(val, &phy0_ctrl->phy_con12); +		writel(val, &phy1_ctrl->phy_con12); + +		val = PHY_CON2_RESET_VAL; +		val |= INIT_DESKEW_EN; +		val |= RDLVL_GATE_EN; +		writel(val, &phy0_ctrl->phy_con2); +		writel(val, &phy1_ctrl->phy_con2); + +		val = PHY_CON0_RESET_VAL; +		val |= P0_CMD_EN; +		val |= BYTE_RDLVL_EN; +		val |= CTRL_SHGATE; +		writel(val, &phy0_ctrl->phy_con0); +		writel(val, &phy1_ctrl->phy_con0); + +		val = PHY_CON1_RESET_VAL; +		val &= ~(CTRL_GATEDURADJ_MASK); +		writel(val, &phy0_ctrl->phy_con1); +		writel(val, &phy1_ctrl->phy_con1); + +		writel(CTRL_RDLVL_GATE_ENABLE, &dmc->rdlvl_config); +		i = RDLVL_COMPLETE_TIMEOUT; +		while ((readl(&dmc->phystatus) & +			(RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1)) != +			(RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1) && i > 0) { +			/* +			 * TODO(waihong): Comment on how long this take to +			 * timeout +			 */ +			sdelay(100); +			i--; +		} +		if (!i) +			return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; +		writel(CTRL_RDLVL_GATE_DISABLE, &dmc->rdlvl_config); + +		writel(0, &phy0_ctrl->phy_con14); +		writel(0, &phy1_ctrl->phy_con14); + +		val = (mem->ctrl_start_point << +				PHY_CON12_CTRL_START_POINT_SHIFT) | +			(mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | +			(mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) | +			(mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) | +			(mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) | +			(mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); +		writel(val, &phy0_ctrl->phy_con12); +		writel(val, &phy1_ctrl->phy_con12); + +		update_reset_dll(dmc, DDR_MODE_DDR3); +	} + +	/* Send PALL command */ +	dmc_config_prech(mem, dmc); + +	writel(mem->memcontrol, &dmc->memcontrol); + +	/* Set DMC Concontrol and enable auto-refresh counter */ +	writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT) +		| (mem->aref_en << CONCONTROL_AREF_EN_SHIFT), &dmc->concontrol); +	return 0; +} diff --git a/arch/arm/cpu/armv7/exynos/dmc_init_exynos4.c b/arch/arm/cpu/armv7/exynos/dmc_init_exynos4.c new file mode 100644 index 000000000..ecddc7268 --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/dmc_init_exynos4.c @@ -0,0 +1,213 @@ +/* + * Memory setup for board based on EXYNOS4210 + * + * Copyright (C) 2013 Samsung Electronics + * Rajeshwari Shinde <rajeshwari.s@samsung.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <asm/arch/dmc.h> +#include "common_setup.h" +#include "exynos4_setup.h" + +struct mem_timings mem = { +	.direct_cmd_msr = { +		DIRECT_CMD1, DIRECT_CMD2, DIRECT_CMD3, DIRECT_CMD4 +	}, +	.timingref = TIMINGREF_VAL, +	.timingrow = TIMINGROW_VAL, +	.timingdata = TIMINGDATA_VAL, +	.timingpower = TIMINGPOWER_VAL, +	.zqcontrol = ZQ_CONTROL_VAL, +	.control0 = CONTROL0_VAL, +	.control1 = CONTROL1_VAL, +	.control2 = CONTROL2_VAL, +	.concontrol = CONCONTROL_VAL, +	.prechconfig = PRECHCONFIG, +	.memcontrol = MEMCONTROL_VAL, +	.memconfig0 = MEMCONFIG0_VAL, +	.memconfig1 = MEMCONFIG1_VAL, +	.dll_resync = FORCE_DLL_RESYNC, +	.dll_on = DLL_CONTROL_ON, +}; +static void phy_control_reset(int ctrl_no, struct exynos4_dmc *dmc) +{ +	if (ctrl_no) { +		writel((mem.control1 | (1 << mem.dll_resync)), +		       &dmc->phycontrol1); +		writel((mem.control1 | (0 << mem.dll_resync)), +		       &dmc->phycontrol1); +	} else { +		writel((mem.control0 | (0 << mem.dll_on)), +		       &dmc->phycontrol0); +		writel((mem.control0 | (1 << mem.dll_on)), +		       &dmc->phycontrol0); +	} +} + +static void dmc_config_mrs(struct exynos4_dmc *dmc, int chip) +{ +	int i; +	unsigned long mask = 0; + +	if (chip) +		mask = DIRECT_CMD_CHIP1_SHIFT; + +	for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) { +		writel(mem.direct_cmd_msr[i] | mask, +		       &dmc->directcmd); +	} +} + +static void dmc_init(struct exynos4_dmc *dmc) +{ +	/* +	 * DLL Parameter Setting: +	 * Termination: Enable R/W +	 * Phase Delay for DQS Cleaning: 180' Shift +	 */ +	writel(mem.control1, &dmc->phycontrol1); + +	/* +	 * ZQ Calibration +	 * Termination: Disable +	 * Auto Calibration Start: Enable +	 */ +	writel(mem.zqcontrol, &dmc->phyzqcontrol); +	sdelay(0x100000); + +	/* +	 * Update DLL Information: +	 * Force DLL Resyncronization +	 */ +	phy_control_reset(1, dmc); +	phy_control_reset(0, dmc); + +	/* Set DLL Parameters */ +	writel(mem.control1, &dmc->phycontrol1); + +	/* DLL Start */ +	writel((mem.control0 | CTRL_START | CTRL_DLL_ON), &dmc->phycontrol0); + +	writel(mem.control2, &dmc->phycontrol2); + +	/* Set Clock Ratio of Bus clock to Memory Clock */ +	writel(mem.concontrol, &dmc->concontrol); + +	/* +	 * Memor Burst length: 8 +	 * Number of chips: 2 +	 * Memory Bus width: 32 bit +	 * Memory Type: DDR3 +	 * Additional Latancy for PLL: 1 Cycle +	 */ +	writel(mem.memcontrol, &dmc->memcontrol); + +	writel(mem.memconfig0, &dmc->memconfig0); +	writel(mem.memconfig1, &dmc->memconfig1); + +	/* Config Precharge Policy */ +	writel(mem.prechconfig, &dmc->prechconfig); +	/* +	 * TimingAref, TimingRow, TimingData, TimingPower Setting: +	 * Values as per Memory AC Parameters +	 */ +	writel(mem.timingref, &dmc->timingref); +	writel(mem.timingrow, &dmc->timingrow); +	writel(mem.timingdata, &dmc->timingdata); +	writel(mem.timingpower, &dmc->timingpower); + +	/* Chip0: NOP Command: Assert and Hold CKE to high level */ +	writel(DIRECT_CMD_NOP, &dmc->directcmd); +	sdelay(0x100000); + +	/* Chip0: EMRS2, EMRS3, EMRS, MRS Commands Using Direct Command */ +	dmc_config_mrs(dmc, 0); +	sdelay(0x100000); + +	/* Chip0: ZQINIT */ +	writel(DIRECT_CMD_ZQ, &dmc->directcmd); +	sdelay(0x100000); + +	writel((DIRECT_CMD_NOP | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd); +	sdelay(0x100000); + +	/* Chip1: EMRS2, EMRS3, EMRS, MRS Commands Using Direct Command */ +	dmc_config_mrs(dmc, 1); +	sdelay(0x100000); + +	/* Chip1: ZQINIT */ +	writel((DIRECT_CMD_ZQ | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd); +	sdelay(0x100000); + +	phy_control_reset(1, dmc); +	sdelay(0x100000); + +	/* turn on DREX0, DREX1 */ +	writel((mem.concontrol | AREF_EN), &dmc->concontrol); +} + +void mem_ctrl_init(int reset) +{ +	struct exynos4_dmc *dmc; + +	/* +	 * Async bridge configuration at CPU_core: +	 * 1: half_sync +	 * 0: full_sync +	 */ +	writel(1, ASYNC_CONFIG); +#ifdef CONFIG_ORIGEN +	/* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */ +	writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE + +		APB_SFR_INTERLEAVE_CONF_OFFSET); +	/* Update MIU Configuration */ +	writel(APB_SFR_ARBRITATION_CONF_VAL, EXYNOS4_MIU_BASE + +		APB_SFR_ARBRITATION_CONF_OFFSET); +#else +	writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE + +		APB_SFR_INTERLEAVE_CONF_OFFSET); +	writel(INTERLEAVE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE + +		ABP_SFR_INTERLEAVE_ADDRMAP_START_OFFSET); +	writel(INTERLEAVE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE + +		ABP_SFR_INTERLEAVE_ADDRMAP_END_OFFSET); +	writel(INTERLEAVE_ADDR_MAP_EN, EXYNOS4_MIU_BASE + +		ABP_SFR_SLV_ADDRMAP_CONF_OFFSET); +#ifdef CONFIG_MIU_LINEAR +	writel(SLAVE0_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE + +		ABP_SFR_SLV0_SINGLE_ADDRMAP_START_OFFSET); +	writel(SLAVE0_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE + +		ABP_SFR_SLV0_SINGLE_ADDRMAP_END_OFFSET); +	writel(SLAVE1_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE + +		ABP_SFR_SLV1_SINGLE_ADDRMAP_START_OFFSET); +	writel(SLAVE1_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE + +		ABP_SFR_SLV1_SINGLE_ADDRMAP_END_OFFSET); +	writel(APB_SFR_SLV_ADDR_MAP_CONF_VAL, EXYNOS4_MIU_BASE + +		ABP_SFR_SLV_ADDRMAP_CONF_OFFSET); +#endif +#endif +	/* DREX0 */ +	dmc = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl(); +	dmc_init(dmc); +	dmc = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl() +					+ DMC_OFFSET); +	dmc_init(dmc); +} diff --git a/arch/arm/cpu/armv7/exynos/exynos4_setup.h b/arch/arm/cpu/armv7/exynos/exynos4_setup.h new file mode 100644 index 000000000..6d250581d --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/exynos4_setup.h @@ -0,0 +1,594 @@ +/* + * Machine Specific Values for EXYNOS4012 based board + * + * Copyright (C) 2011 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ORIGEN_SETUP_H +#define _ORIGEN_SETUP_H + +#include <config.h> +#include <version.h> +#include <asm/arch/cpu.h> + +#ifdef CONFIG_CLK_800_330_165 +#define DRAM_CLK_330 +#endif +#ifdef CONFIG_CLK_1000_200_200 +#define DRAM_CLK_200 +#endif +#ifdef CONFIG_CLK_1000_330_165 +#define DRAM_CLK_330 +#endif +#ifdef CONFIG_CLK_1000_400_200 +#define DRAM_CLK_400 +#endif + +/* Bus Configuration Register Address */ +#define ASYNC_CONFIG		0x10010350 + +/* CLK_SRC_CPU */ +#define MUX_HPM_SEL_MOUTAPLL		0x0 +#define MUX_HPM_SEL_SCLKMPLL		0x1 +#define MUX_CORE_SEL_MOUTAPLL		0x0 +#define MUX_CORE_SEL_SCLKMPLL		0x1 +#define MUX_MPLL_SEL_FILPLL		0x0 +#define MUX_MPLL_SEL_MOUTMPLLFOUT	0x1 +#define MUX_APLL_SEL_FILPLL		0x0 +#define MUX_APLL_SEL_MOUTMPLLFOUT	0x1 +#define CLK_SRC_CPU_VAL			((MUX_HPM_SEL_MOUTAPLL << 20) \ +					| (MUX_CORE_SEL_MOUTAPLL << 16) \ +					| (MUX_MPLL_SEL_MOUTMPLLFOUT << 8)\ +					| (MUX_APLL_SEL_MOUTMPLLFOUT << 0)) + +/* CLK_DIV_CPU0 */ +#define APLL_RATIO		0x0 +#define PCLK_DBG_RATIO		0x1 +#define ATB_RATIO		0x3 +#define PERIPH_RATIO		0x3 +#define COREM1_RATIO		0x7 +#define COREM0_RATIO		0x3 +#define CORE_RATIO		0x0 +#define CLK_DIV_CPU0_VAL	((APLL_RATIO << 24) \ +				| (PCLK_DBG_RATIO << 20) \ +				| (ATB_RATIO << 16) \ +				| (PERIPH_RATIO << 12) \ +				| (COREM1_RATIO << 8) \ +				| (COREM0_RATIO << 4) \ +				| (CORE_RATIO << 0)) + +/* CLK_DIV_CPU1 */ +#define HPM_RATIO		0x0 +#define COPY_RATIO		0x3 +#define CLK_DIV_CPU1_VAL	((HPM_RATIO << 4) | (COPY_RATIO)) + +/* CLK_SRC_DMC */ +#define MUX_PWI_SEL_XXTI		0x0 +#define MUX_PWI_SEL_XUSBXTI		0x1 +#define MUX_PWI_SEL_SCLK_HDMI24M	0x2 +#define MUX_PWI_SEL_SCLK_USBPHY0	0x3 +#define MUX_PWI_SEL_SCLK_USBPHY1	0x4 +#define MUX_PWI_SEL_SCLK_HDMIPHY	0x5 +#define MUX_PWI_SEL_SCLKMPLL		0x6 +#define MUX_PWI_SEL_SCLKEPLL		0x7 +#define MUX_PWI_SEL_SCLKVPLL		0x8 +#define MUX_DPHY_SEL_SCLKMPLL		0x0 +#define MUX_DPHY_SEL_SCLKAPLL		0x1 +#define MUX_DMC_BUS_SEL_SCLKMPLL	0x0 +#define MUX_DMC_BUS_SEL_SCLKAPLL	0x1 +#define CLK_SRC_DMC_VAL			((MUX_PWI_SEL_XUSBXTI << 16) \ +					| (MUX_DPHY_SEL_SCLKMPLL << 8) \ +					| (MUX_DMC_BUS_SEL_SCLKMPLL << 4)) + +/* CLK_DIV_DMC0 */ +#define CORE_TIMERS_RATIO	0x1 +#define COPY2_RATIO		0x3 +#define DMCP_RATIO		0x1 +#define DMCD_RATIO		0x1 +#define DMC_RATIO		0x1 +#define DPHY_RATIO		0x1 +#define ACP_PCLK_RATIO		0x1 +#define ACP_RATIO		0x3 +#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 << 0)) + +/* CLK_DIV_DMC1 */ +#define DPM_RATIO		0x1 +#define DVSEM_RATIO		0x1 +#define PWI_RATIO		0x1 +#define CLK_DIV_DMC1_VAL	((DPM_RATIO << 24) \ +				| (DVSEM_RATIO << 16) \ +				| (PWI_RATIO << 8)) + +/* CLK_SRC_TOP0 */ +#define MUX_ONENAND_SEL_ACLK_133	0x0 +#define MUX_ONENAND_SEL_ACLK_160	0x1 +#define MUX_ACLK_133_SEL_SCLKMPLL	0x0 +#define MUX_ACLK_133_SEL_SCLKAPLL	0x1 +#define MUX_ACLK_160_SEL_SCLKMPLL	0x0 +#define MUX_ACLK_160_SEL_SCLKAPLL	0x1 +#define MUX_ACLK_100_SEL_SCLKMPLL	0x0 +#define MUX_ACLK_100_SEL_SCLKAPLL	0x1 +#define MUX_ACLK_200_SEL_SCLKMPLL	0x0 +#define MUX_ACLK_200_SEL_SCLKAPLL	0x1 +#define MUX_VPLL_SEL_FINPLL		0x0 +#define MUX_VPLL_SEL_FOUTVPLL		0x1 +#define MUX_EPLL_SEL_FINPLL		0x0 +#define MUX_EPLL_SEL_FOUTEPLL		0x1 +#define MUX_ONENAND_1_SEL_MOUTONENAND	0x0 +#define MUX_ONENAND_1_SEL_SCLKVPLL	0x1 +#define CLK_SRC_TOP0_VAL		((MUX_ONENAND_SEL_ACLK_133 << 28) \ +					| (MUX_ACLK_133_SEL_SCLKMPLL << 24) \ +					| (MUX_ACLK_160_SEL_SCLKMPLL << 20) \ +					| (MUX_ACLK_100_SEL_SCLKMPLL << 16) \ +					| (MUX_ACLK_200_SEL_SCLKMPLL << 12) \ +					| (MUX_VPLL_SEL_FINPLL << 8) \ +					| (MUX_EPLL_SEL_FINPLL << 4)\ +					| (MUX_ONENAND_1_SEL_MOUTONENAND << 0)) + +/* CLK_SRC_TOP1 */ +#define VPLLSRC_SEL_FINPLL	0x0 +#define VPLLSRC_SEL_SCLKHDMI24M	0x1 +#define CLK_SRC_TOP1_VAL	(VPLLSRC_SEL_FINPLL) + +/* CLK_DIV_TOP */ +#define ONENAND_RATIO		0x0 +#define ACLK_133_RATIO		0x5 +#define ACLK_160_RATIO		0x4 +#define ACLK_100_RATIO		0x7 +#define ACLK_200_RATIO		0x3 +#define CLK_DIV_TOP_VAL		((ONENAND_RATIO << 16)	\ +				| (ACLK_133_RATIO << 12)\ +				| (ACLK_160_RATIO << 8)	\ +				| (ACLK_100_RATIO << 4)	\ +				| (ACLK_200_RATIO << 0)) + +/* CLK_SRC_LEFTBUS */ +#define MUX_GDL_SEL_SCLKMPLL	0x0 +#define MUX_GDL_SEL_SCLKAPLL	0x1 +#define CLK_SRC_LEFTBUS_VAL	(MUX_GDL_SEL_SCLKMPLL) + +/* CLK_DIV_LEFTBUS */ +#define GPL_RATIO		0x1 +#define GDL_RATIO		0x3 +#define CLK_DIV_LEFTBUS_VAL	((GPL_RATIO << 4) | (GDL_RATIO)) + +/* CLK_SRC_RIGHTBUS */ +#define MUX_GDR_SEL_SCLKMPLL	0x0 +#define MUX_GDR_SEL_SCLKAPLL	0x1 +#define CLK_SRC_RIGHTBUS_VAL	(MUX_GDR_SEL_SCLKMPLL) + +/* CLK_DIV_RIGHTBUS */ +#define GPR_RATIO		0x1 +#define GDR_RATIO		0x3 +#define CLK_DIV_RIGHTBUS_VAL	((GPR_RATIO << 4) | (GDR_RATIO)) + +/* CLK_SRS_FSYS: 6 = SCLKMPLL */ +#define SATA_SEL_SCLKMPLL	0 +#define SATA_SEL_SCLKAPLL	1 + +#define MMC_SEL_XXTI		0 +#define MMC_SEL_XUSBXTI		1 +#define MMC_SEL_SCLK_HDMI24M	2 +#define MMC_SEL_SCLK_USBPHY0	3 +#define MMC_SEL_SCLK_USBPHY1	4 +#define MMC_SEL_SCLK_HDMIPHY	5 +#define MMC_SEL_SCLKMPLL	6 +#define MMC_SEL_SCLKEPLL	7 +#define MMC_SEL_SCLKVPLL	8 + +#define MMCC0_SEL		MMC_SEL_SCLKMPLL +#define MMCC1_SEL		MMC_SEL_SCLKMPLL +#define MMCC2_SEL		MMC_SEL_SCLKMPLL +#define MMCC3_SEL		MMC_SEL_SCLKMPLL +#define MMCC4_SEL		MMC_SEL_SCLKMPLL +#define CLK_SRC_FSYS_VAL	((SATA_SEL_SCLKMPLL << 24) \ +				| (MMCC4_SEL << 16) \ +				| (MMCC3_SEL << 12) \ +				| (MMCC2_SEL << 8) \ +				| (MMCC1_SEL << 4) \ +				| (MMCC0_SEL << 0)) + +/* SCLK_MMC[0-4] = MOUTMMC[0-4]/(MMC[0-4]_RATIO + 1)/(MMC[0-4]_PRE_RATIO +1) */ +/* CLK_DIV_FSYS1 */ +#define MMC0_RATIO		0xF +#define MMC0_PRE_RATIO		0x0 +#define MMC1_RATIO		0xF +#define MMC1_PRE_RATIO		0x0 +#define CLK_DIV_FSYS1_VAL	((MMC1_PRE_RATIO << 24) \ +				| (MMC1_RATIO << 16) \ +				| (MMC0_PRE_RATIO << 8) \ +				| (MMC0_RATIO << 0)) + +/* CLK_DIV_FSYS2 */ +#define MMC2_RATIO		0xF +#define MMC2_PRE_RATIO		0x0 +#define MMC3_RATIO		0xF +#define MMC3_PRE_RATIO		0x0 +#define CLK_DIV_FSYS2_VAL	((MMC3_PRE_RATIO << 24) \ +				| (MMC3_RATIO << 16) \ +				| (MMC2_PRE_RATIO << 8) \ +				| (MMC2_RATIO << 0)) + +/* CLK_DIV_FSYS3 */ +#define MMC4_RATIO		0xF +#define MMC4_PRE_RATIO		0x0 +#define CLK_DIV_FSYS3_VAL	((MMC4_PRE_RATIO << 8) \ +				| (MMC4_RATIO << 0)) + +/* CLK_SRC_PERIL0 */ +#define UART_SEL_XXTI		0 +#define UART_SEL_XUSBXTI	1 +#define UART_SEL_SCLK_HDMI24M	2 +#define UART_SEL_SCLK_USBPHY0	3 +#define UART_SEL_SCLK_USBPHY1	4 +#define UART_SEL_SCLK_HDMIPHY	5 +#define UART_SEL_SCLKMPLL	6 +#define UART_SEL_SCLKEPLL	7 +#define UART_SEL_SCLKVPLL	8 + +#define UART0_SEL		UART_SEL_SCLKMPLL +#define UART1_SEL		UART_SEL_SCLKMPLL +#define UART2_SEL		UART_SEL_SCLKMPLL +#define UART3_SEL		UART_SEL_SCLKMPLL +#define UART4_SEL		UART_SEL_SCLKMPLL +#define CLK_SRC_PERIL0_VAL	((UART4_SEL << 16) \ +				| (UART3_SEL << 12) \ +				| (UART2_SEL << 8) \ +				| (UART1_SEL << 4) \ +				| (UART0_SEL << 0)) + +/* SCLK_UART[0-4] = MOUTUART[0-4]/(UART[0-4]_RATIO + 1) */ +/* CLK_DIV_PERIL0 */ +#define UART0_RATIO		7 +#define UART1_RATIO		7 +#define UART2_RATIO		7 +#define UART3_RATIO		7 +#define UART4_RATIO		7 +#define CLK_DIV_PERIL0_VAL	((UART4_RATIO << 16) \ +				| (UART3_RATIO << 12) \ +				| (UART2_RATIO << 8) \ +				| (UART1_RATIO << 4) \ +				| (UART0_RATIO << 0)) + +/* Clock Source CAM/FIMC */ +/* CLK_SRC_CAM */ +#define CAM0_SEL_XUSBXTI	1 +#define CAM1_SEL_XUSBXTI	1 +#define CSIS0_SEL_XUSBXTI	1 +#define CSIS1_SEL_XUSBXTI	1 + +#define FIMC_SEL_SCLKMPLL	6 +#define FIMC0_LCLK_SEL		FIMC_SEL_SCLKMPLL +#define FIMC1_LCLK_SEL		FIMC_SEL_SCLKMPLL +#define FIMC2_LCLK_SEL		FIMC_SEL_SCLKMPLL +#define FIMC3_LCLK_SEL		FIMC_SEL_SCLKMPLL + +#define CLK_SRC_CAM_VAL		((CSIS1_SEL_XUSBXTI << 28) \ +				| (CSIS0_SEL_XUSBXTI << 24) \ +				| (CAM1_SEL_XUSBXTI << 20) \ +				| (CAM0_SEL_XUSBXTI << 16) \ +				| (FIMC3_LCLK_SEL << 12) \ +				| (FIMC2_LCLK_SEL << 8) \ +				| (FIMC1_LCLK_SEL << 4) \ +				| (FIMC0_LCLK_SEL << 0)) + +/* SCLK CAM */ +/* CLK_DIV_CAM */ +#define FIMC0_LCLK_RATIO	4 +#define FIMC1_LCLK_RATIO	4 +#define FIMC2_LCLK_RATIO	4 +#define FIMC3_LCLK_RATIO	4 +#define CLK_DIV_CAM_VAL		((FIMC3_LCLK_RATIO << 12) \ +				| (FIMC2_LCLK_RATIO << 8) \ +				| (FIMC1_LCLK_RATIO << 4) \ +				| (FIMC0_LCLK_RATIO << 0)) + +/* SCLK MFC */ +/* CLK_SRC_MFC */ +#define MFC_SEL_MPLL		0 +#define MOUTMFC_0		0 +#define MFC_SEL			MOUTMFC_0 +#define MFC_0_SEL		MFC_SEL_MPLL +#define CLK_SRC_MFC_VAL		((MFC_SEL << 8) | (MFC_0_SEL)) + + +/* CLK_DIV_MFC */ +#define MFC_RATIO		3 +#define CLK_DIV_MFC_VAL		(MFC_RATIO) + +/* SCLK G3D */ +/* CLK_SRC_G3D */ +#define G3D_SEL_MPLL		0 +#define MOUTG3D_0		0 +#define G3D_SEL			MOUTG3D_0 +#define G3D_0_SEL		G3D_SEL_MPLL +#define CLK_SRC_G3D_VAL		((G3D_SEL << 8) | (G3D_0_SEL)) + +/* CLK_DIV_G3D */ +#define G3D_RATIO		1 +#define CLK_DIV_G3D_VAL		(G3D_RATIO) + +/* SCLK LCD0 */ +/* CLK_SRC_LCD0 */ +#define FIMD_SEL_SCLKMPLL	6 +#define MDNIE0_SEL_XUSBXTI	1 +#define MDNIE_PWM0_SEL_XUSBXTI	1 +#define MIPI0_SEL_XUSBXTI	1 +#define CLK_SRC_LCD0_VAL	((MIPI0_SEL_XUSBXTI << 12) \ +				| (MDNIE_PWM0_SEL_XUSBXTI << 8) \ +				| (MDNIE0_SEL_XUSBXTI << 4) \ +				| (FIMD_SEL_SCLKMPLL << 0)) + +/* CLK_DIV_LCD0 */ +#define FIMD0_RATIO		4 +#define CLK_DIV_LCD0_VAL	(FIMD0_RATIO) + +/* Required period to generate a stable clock output */ +/* PLL_LOCK_TIME */ +#define PLL_LOCKTIME		0x1C20 + +/* PLL Values */ +#define DISABLE			0 +#define ENABLE			1 +#define SET_PLL(mdiv, pdiv, sdiv)	((ENABLE << 31)\ +					| (mdiv << 16) \ +					| (pdiv << 8) \ +					| (sdiv << 0)) + +/* APLL_CON0 */ +#define APLL_MDIV		0xFA +#define APLL_PDIV		0x6 +#define APLL_SDIV		0x1 +#define APLL_CON0_VAL		SET_PLL(APLL_MDIV, APLL_PDIV, APLL_SDIV) + +/* APLL_CON1 */ +#define APLL_AFC_ENB		0x1 +#define APLL_AFC		0xC +#define APLL_CON1_VAL		((APLL_AFC_ENB << 31) | (APLL_AFC << 0)) + +/* MPLL_CON0 */ +#define MPLL_MDIV		0xC8 +#define MPLL_PDIV		0x6 +#define MPLL_SDIV		0x1 +#define MPLL_CON0_VAL		SET_PLL(MPLL_MDIV, MPLL_PDIV, MPLL_SDIV) + +/* MPLL_CON1 */ +#define MPLL_AFC_ENB		0x0 +#define MPLL_AFC		0x1C +#define MPLL_CON1_VAL		((MPLL_AFC_ENB << 31) | (MPLL_AFC << 0)) + +/* EPLL_CON0 */ +#define EPLL_MDIV		0x30 +#define EPLL_PDIV		0x3 +#define EPLL_SDIV		0x2 +#define EPLL_CON0_VAL		SET_PLL(EPLL_MDIV, EPLL_PDIV, EPLL_SDIV) + +/* EPLL_CON1 */ +#define EPLL_K			0x0 +#define EPLL_CON1_VAL		(EPLL_K >> 0) + +/* VPLL_CON0 */ +#define VPLL_MDIV		0x35 +#define VPLL_PDIV		0x3 +#define VPLL_SDIV		0x2 +#define VPLL_CON0_VAL		SET_PLL(VPLL_MDIV, VPLL_PDIV, VPLL_SDIV) + +/* VPLL_CON1 */ +#define VPLL_SSCG_EN		DISABLE +#define VPLL_SEL_PF_DN_SPREAD	0x0 +#define VPLL_MRR		0x11 +#define VPLL_MFR		0x0 +#define VPLL_K			0x400 +#define VPLL_CON1_VAL		((VPLL_SSCG_EN << 31)\ +				| (VPLL_SEL_PF_DN_SPREAD << 29) \ +				| (VPLL_MRR << 24) \ +				| (VPLL_MFR << 16) \ +				| (VPLL_K << 0)) + +/* DMC */ +#define DIRECT_CMD_NOP	0x07000000 +#define DIRECT_CMD_ZQ	0x0a000000 +#define DIRECT_CMD_CHIP1_SHIFT	(1 << 20) +#define MEM_TIMINGS_MSR_COUNT	4 +#define CTRL_START	(1 << 0) +#define CTRL_DLL_ON	(1 << 1) +#define AREF_EN		(1 << 5) +#define DRV_TYPE	(1 << 6) + +struct mem_timings { +	unsigned direct_cmd_msr[MEM_TIMINGS_MSR_COUNT]; +	unsigned timingref; +	unsigned timingrow; +	unsigned timingdata; +	unsigned timingpower; +	unsigned zqcontrol; +	unsigned control0; +	unsigned control1; +	unsigned control2; +	unsigned concontrol; +	unsigned prechconfig; +	unsigned memcontrol; +	unsigned memconfig0; +	unsigned memconfig1; +	unsigned dll_resync; +	unsigned dll_on; +}; + +/* MIU */ +/* MIU Config Register Offsets*/ +#define APB_SFR_INTERLEAVE_CONF_OFFSET	0x400 +#define APB_SFR_ARBRITATION_CONF_OFFSET	0xC00 +#define ABP_SFR_SLV_ADDRMAP_CONF_OFFSET	0x800 +#define ABP_SFR_INTERLEAVE_ADDRMAP_START_OFFSET	0x808 +#define ABP_SFR_INTERLEAVE_ADDRMAP_END_OFFSET	0x810 +#define ABP_SFR_SLV0_SINGLE_ADDRMAP_START_OFFSET	0x818 +#define ABP_SFR_SLV0_SINGLE_ADDRMAP_END_OFFSET	0x820 +#define ABP_SFR_SLV1_SINGLE_ADDRMAP_START_OFFSET	0x828 +#define ABP_SFR_SLV1_SINGLE_ADDRMAP_END_OFFSET	0x830 + +#ifdef CONFIG_ORIGEN +/* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */ +#define APB_SFR_INTERLEAVE_CONF_VAL	0x20001507 +#define APB_SFR_ARBRITATION_CONF_VAL	0x00000001 +#endif + +#define INTERLEAVE_ADDR_MAP_START_ADDR	0x40000000 +#define INTERLEAVE_ADDR_MAP_END_ADDR	0xbfffffff +#define INTERLEAVE_ADDR_MAP_EN		0x00000001 + +#ifdef CONFIG_MIU_1BIT_INTERLEAVED +/* Interleave_bit0: 0xC*/ +#define APB_SFR_INTERLEAVE_CONF_VAL	0x0000000c +#endif +#ifdef CONFIG_MIU_2BIT_INTERLEAVED +/* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0xc */ +#define APB_SFR_INTERLEAVE_CONF_VAL	0x2000150c +#endif +#define SLAVE0_SINGLE_ADDR_MAP_START_ADDR	0x40000000 +#define SLAVE0_SINGLE_ADDR_MAP_END_ADDR		0x7fffffff +#define SLAVE1_SINGLE_ADDR_MAP_START_ADDR	0x80000000 +#define SLAVE1_SINGLE_ADDR_MAP_END_ADDR		0xbfffffff +/* Enable SME0 and SME1*/ +#define APB_SFR_SLV_ADDR_MAP_CONF_VAL		0x00000006 + +#define FORCE_DLL_RESYNC	3 +#define DLL_CONTROL_ON		1 + +#define DIRECT_CMD1	0x00020000 +#define DIRECT_CMD2	0x00030000 +#define DIRECT_CMD3	0x00010002 +#define DIRECT_CMD4	0x00000328 + +#define CTRL_ZQ_MODE_NOTERM	(0x1 << 0) +#define CTRL_ZQ_START		(0x1 << 1) +#define CTRL_ZQ_DIV		(0 << 4) +#define CTRL_ZQ_MODE_DDS	(0x7 << 8) +#define CTRL_ZQ_MODE_TERM	(0x2 << 11) +#define CTRL_ZQ_FORCE_IMPN	(0x5 << 14) +#define CTRL_ZQ_FORCE_IMPP	(0x6 << 17) +#define CTRL_DCC		(0xE38 << 20) +#define ZQ_CONTROL_VAL		(CTRL_ZQ_MODE_NOTERM | CTRL_ZQ_START\ +				| CTRL_ZQ_DIV | CTRL_ZQ_MODE_DDS\ +				| CTRL_ZQ_MODE_TERM | CTRL_ZQ_FORCE_IMPN\ +				| CTRL_ZQ_FORCE_IMPP | CTRL_DCC) + +#define ASYNC			(0 << 0) +#define CLK_RATIO		(1 << 1) +#define DIV_PIPE		(1 << 3) +#define AWR_ON			(1 << 4) +#define AREF_DISABLE		(0 << 5) +#define DRV_TYPE_DISABLE	(0 << 6) +#define CHIP0_NOT_EMPTY		(0 << 8) +#define CHIP1_NOT_EMPTY		(0 << 9) +#define DQ_SWAP_DISABLE		(0 << 10) +#define QOS_FAST_DISABLE	(0 << 11) +#define RD_FETCH		(0x3 << 12) +#define TIMEOUT_LEVEL0		(0xFFF << 16) +#define CONCONTROL_VAL		(ASYNC | CLK_RATIO | DIV_PIPE | AWR_ON\ +				| AREF_DISABLE | DRV_TYPE_DISABLE\ +				| CHIP0_NOT_EMPTY | CHIP1_NOT_EMPTY\ +				| DQ_SWAP_DISABLE | QOS_FAST_DISABLE\ +				| RD_FETCH | TIMEOUT_LEVEL0) + +#define CLK_STOP_DISABLE	(0 << 1) +#define DPWRDN_DISABLE		(0 << 2) +#define DPWRDN_TYPE		(0 << 3) +#define TP_DISABLE		(0 << 4) +#define DSREF_DIABLE		(0 << 5) +#define ADD_LAT_PALL		(1 << 6) +#define MEM_TYPE_DDR3		(0x6 << 8) +#define MEM_WIDTH_32		(0x2 << 12) +#define NUM_CHIP_2		(1 << 16) +#define BL_8			(0x3 << 20) +#define MEMCONTROL_VAL		(CLK_STOP_DISABLE | DPWRDN_DISABLE\ +				| DPWRDN_TYPE | TP_DISABLE | DSREF_DIABLE\ +				| ADD_LAT_PALL | MEM_TYPE_DDR3 | MEM_WIDTH_32\ +				| NUM_CHIP_2 | BL_8) + + +#define CHIP_BANK_8		(0x3 << 0) +#define CHIP_ROW_14		(0x2 << 4) +#define CHIP_COL_10		(0x3 << 8) +#define CHIP_MAP_INTERLEAVED	(1 << 12) +#define CHIP_MASK		(0xe0 << 16) +#ifdef CONFIG_MIU_LINEAR +#define CHIP0_BASE		(0x40 << 24) +#define CHIP1_BASE		(0x60 << 24) +#else +#define CHIP0_BASE		(0x20 << 24) +#define CHIP1_BASE		(0x40 << 24) +#endif +#define MEMCONFIG0_VAL		(CHIP_BANK_8 | CHIP_ROW_14 | CHIP_COL_10\ +				| CHIP_MAP_INTERLEAVED | CHIP_MASK | CHIP0_BASE) +#define MEMCONFIG1_VAL		(CHIP_BANK_8 | CHIP_ROW_14 | CHIP_COL_10\ +				| CHIP_MAP_INTERLEAVED | CHIP_MASK | CHIP1_BASE) + +#define TP_CNT			(0xff << 24) +#define PRECHCONFIG		TP_CNT + +#define CTRL_OFF		(0 << 0) +#define CTRL_DLL_OFF		(0 << 1) +#define CTRL_HALF		(0 << 2) +#define CTRL_DFDQS		(1 << 3) +#define DQS_DELAY		(0 << 4) +#define CTRL_START_POINT	(0x10 << 8) +#define CTRL_INC		(0x10 << 16) +#define CTRL_FORCE		(0x71 << 24) +#define CONTROL0_VAL		(CTRL_OFF | CTRL_DLL_OFF | CTRL_HALF\ +				| CTRL_DFDQS | DQS_DELAY | CTRL_START_POINT\ +				| CTRL_INC | CTRL_FORCE) + +#define CTRL_SHIFTC		(0x6 << 0) +#define CTRL_REF		(8 << 4) +#define CTRL_SHGATE		(1 << 29) +#define TERM_READ_EN		(1 << 30) +#define TERM_WRITE_EN		(1 << 31) +#define CONTROL1_VAL		(CTRL_SHIFTC | CTRL_REF | CTRL_SHGATE\ +				| TERM_READ_EN | TERM_WRITE_EN) + +#define CONTROL2_VAL		0x00000000 + +#ifdef CONFIG_ORIGEN +#define TIMINGREF_VAL		0x000000BB +#define TIMINGROW_VAL		0x4046654f +#define	TIMINGDATA_VAL		0x46400506 +#define	TIMINGPOWER_VAL		0x52000A3C +#else +#define TIMINGREF_VAL		0x000000BC +#ifdef DRAM_CLK_330 +#define TIMINGROW_VAL		0x3545548d +#define	TIMINGDATA_VAL		0x45430506 +#define	TIMINGPOWER_VAL		0x4439033c +#endif +#ifdef DRAM_CLK_400 +#define TIMINGROW_VAL		0x45430506 +#define	TIMINGDATA_VAL		0x56500506 +#define	TIMINGPOWER_VAL		0x5444033d +#endif +#endif +#endif diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h new file mode 100644 index 000000000..8f36c1604 --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -0,0 +1,567 @@ +/* + * Machine Specific Values for SMDK5250 board based on EXYNOS5 + * + * Copyright (C) 2012 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _SMDK5250_SETUP_H +#define _SMDK5250_SETUP_H + +#include <config.h> +#include <asm/arch/dmc.h> + +/* APLL_CON1	*/ +#define APLL_CON1_VAL	(0x00203800) + +/* MPLL_CON1	*/ +#define MPLL_CON1_VAL   (0x00203800) + +/* CPLL_CON1	*/ +#define CPLL_CON1_VAL	(0x00203800) + +/* GPLL_CON1	*/ +#define GPLL_CON1_VAL	(0x00203800) + +/* EPLL_CON1, CON2	*/ +#define EPLL_CON1_VAL	0x00000000 +#define EPLL_CON2_VAL	0x00000080 + +/* VPLL_CON1, CON2	*/ +#define VPLL_CON1_VAL	0x00000000 +#define VPLL_CON2_VAL	0x00000080 + +/* BPLL_CON1	*/ +#define BPLL_CON1_VAL	0x00203800 + +/* Set PLL */ +#define set_pll(mdiv, pdiv, sdiv)	(1<<31 | mdiv<<16 | pdiv<<8 | sdiv) + +/* CLK_SRC_CPU	*/ +/* 0 = MOUTAPLL,  1 = SCLKMPLL	*/ +#define MUX_HPM_SEL             0 +#define MUX_CPU_SEL             0 +#define MUX_APLL_SEL            1 + +#define CLK_SRC_CPU_VAL		((MUX_HPM_SEL << 20)    \ +				| (MUX_CPU_SEL << 16)  \ +				| (MUX_APLL_SEL)) + +/* MEMCONTROL register bit fields */ +#define DMC_MEMCONTROL_CLK_STOP_DISABLE	(0 << 0) +#define DMC_MEMCONTROL_DPWRDN_DISABLE	(0 << 1) +#define DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE	(0 << 2) +#define DMC_MEMCONTROL_TP_DISABLE	(0 << 4) +#define DMC_MEMCONTROL_DSREF_DISABLE	(0 << 5) +#define DMC_MEMCONTROL_DSREF_ENABLE	(1 << 5) +#define DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(x)    (x << 6) + +#define DMC_MEMCONTROL_MEM_TYPE_LPDDR3  (7 << 8) +#define DMC_MEMCONTROL_MEM_TYPE_DDR3    (6 << 8) +#define DMC_MEMCONTROL_MEM_TYPE_LPDDR2  (5 << 8) + +#define DMC_MEMCONTROL_MEM_WIDTH_32BIT  (2 << 12) + +#define DMC_MEMCONTROL_NUM_CHIP_1       (0 << 16) +#define DMC_MEMCONTROL_NUM_CHIP_2       (1 << 16) + +#define DMC_MEMCONTROL_BL_8             (3 << 20) +#define DMC_MEMCONTROL_BL_4             (2 << 20) + +#define DMC_MEMCONTROL_PZQ_DISABLE      (0 << 24) + +#define DMC_MEMCONTROL_MRR_BYTE_7_0     (0 << 25) +#define DMC_MEMCONTROL_MRR_BYTE_15_8    (1 << 25) +#define DMC_MEMCONTROL_MRR_BYTE_23_16   (2 << 25) +#define DMC_MEMCONTROL_MRR_BYTE_31_24   (3 << 25) + +/* MEMCONFIG0 register bit fields */ +#define DMC_MEMCONFIGX_CHIP_MAP_INTERLEAVED     (1 << 12) +#define DMC_MEMCONFIGX_CHIP_COL_10              (3 << 8) +#define DMC_MEMCONFIGX_CHIP_ROW_14              (2 << 4) +#define DMC_MEMCONFIGX_CHIP_ROW_15              (3 << 4) +#define DMC_MEMCONFIGX_CHIP_BANK_8              (3 << 0) + +#define DMC_MEMBASECONFIGX_CHIP_BASE(x)         (x << 16) +#define DMC_MEMBASECONFIGX_CHIP_MASK(x)         (x << 0) +#define DMC_MEMBASECONFIG_VAL(x)        (       \ +	DMC_MEMBASECONFIGX_CHIP_BASE(x) |       \ +	DMC_MEMBASECONFIGX_CHIP_MASK(0x780)     \ +) + +#define DMC_MEMBASECONFIG0_VAL  DMC_MEMBASECONFIG_VAL(0x40) +#define DMC_MEMBASECONFIG1_VAL  DMC_MEMBASECONFIG_VAL(0x80) + +#define DMC_PRECHCONFIG_VAL             0xFF000000 +#define DMC_PWRDNCONFIG_VAL             0xFFFF00FF + +#define DMC_CONCONTROL_RESET_VAL	0x0FFF0000 +#define DFI_INIT_START		(1 << 28) +#define EMPTY			(1 << 8) +#define AREF_EN			(1 << 5) + +#define DFI_INIT_COMPLETE_CHO	(1 << 2) +#define DFI_INIT_COMPLETE_CH1	(1 << 3) + +#define RDLVL_COMPLETE_CHO	(1 << 14) +#define RDLVL_COMPLETE_CH1	(1 << 15) + +#define CLK_STOP_EN	(1 << 0) +#define DPWRDN_EN	(1 << 1) +#define DSREF_EN	(1 << 5) + +/* COJCONTROL register bit fields */ +#define DMC_CONCONTROL_IO_PD_CON_DISABLE	(0 << 3) +#define DMC_CONCONTROL_AREF_EN_DISABLE		(0 << 5) +#define DMC_CONCONTROL_EMPTY_DISABLE		(0 << 8) +#define DMC_CONCONTROL_EMPTY_ENABLE		(1 << 8) +#define DMC_CONCONTROL_RD_FETCH_DISABLE		(0x0 << 12) +#define DMC_CONCONTROL_TIMEOUT_LEVEL0		(0xFFF << 16) +#define DMC_CONCONTROL_DFI_INIT_START_DISABLE	(0 << 28) + +/* CLK_DIV_CPU0_VAL */ +#define CLK_DIV_CPU0_VAL	((ARM2_RATIO << 28)             \ +				| (APLL_RATIO << 24)            \ +				| (PCLK_DBG_RATIO << 20)        \ +				| (ATB_RATIO << 16)             \ +				| (PERIPH_RATIO << 12)          \ +				| (ACP_RATIO << 8)              \ +				| (CPUD_RATIO << 4)             \ +				| (ARM_RATIO)) + + +/* CLK_FSYS */ +#define CLK_SRC_FSYS0_VAL              0x66666 +#define CLK_DIV_FSYS0_VAL	       0x0BB00000 + +/* CLK_DIV_CPU1	*/ +#define HPM_RATIO               0x2 +#define COPY_RATIO              0x0 + +/* CLK_DIV_CPU1 = 0x00000003 */ +#define CLK_DIV_CPU1_VAL        ((HPM_RATIO << 4)		\ +				| (COPY_RATIO)) + +/* CLK_SRC_CORE0 */ +#define CLK_SRC_CORE0_VAL       0x00000000 + +/* CLK_SRC_CORE1 */ +#define CLK_SRC_CORE1_VAL       0x100 + +/* CLK_DIV_CORE0 */ +#define CLK_DIV_CORE0_VAL       0x00120000 + +/* CLK_DIV_CORE1 */ +#define CLK_DIV_CORE1_VAL       0x07070700 + +/* CLK_DIV_SYSRGT */ +#define CLK_DIV_SYSRGT_VAL      0x00000111 + +/* CLK_DIV_ACP */ +#define CLK_DIV_ACP_VAL         0x12 + +/* CLK_DIV_SYSLFT */ +#define CLK_DIV_SYSLFT_VAL      0x00000311 + +/* CLK_SRC_CDREX */ +#define CLK_SRC_CDREX_VAL       0x1 + +/* CLK_DIV_CDREX */ +#define MCLK_CDREX2_RATIO       0x0 +#define ACLK_EFCON_RATIO        0x1 +#define MCLK_DPHY_RATIO		0x1 +#define MCLK_CDREX_RATIO	0x1 +#define ACLK_C2C_200_RATIO	0x1 +#define C2C_CLK_400_RATIO	0x1 +#define PCLK_CDREX_RATIO	0x1 +#define ACLK_CDREX_RATIO	0x1 + +#define CLK_DIV_CDREX_VAL	((MCLK_DPHY_RATIO << 24)        \ +				| (C2C_CLK_400_RATIO << 6)	\ +				| (PCLK_CDREX_RATIO << 4)	\ +				| (ACLK_CDREX_RATIO)) + +/* CLK_SRC_TOP0	*/ +#define MUX_ACLK_300_GSCL_SEL           0x0 +#define MUX_ACLK_300_GSCL_MID_SEL       0x0 +#define MUX_ACLK_400_G3D_MID_SEL        0x0 +#define MUX_ACLK_333_SEL	        0x0 +#define MUX_ACLK_300_DISP1_SEL	        0x0 +#define MUX_ACLK_300_DISP1_MID_SEL      0x0 +#define MUX_ACLK_200_SEL	        0x0 +#define MUX_ACLK_166_SEL	        0x0 +#define CLK_SRC_TOP0_VAL	((MUX_ACLK_300_GSCL_SEL  << 25)		\ +				| (MUX_ACLK_300_GSCL_MID_SEL << 24)	\ +				| (MUX_ACLK_400_G3D_MID_SEL << 20)	\ +				| (MUX_ACLK_333_SEL << 16)		\ +				| (MUX_ACLK_300_DISP1_SEL << 15)	\ +				| (MUX_ACLK_300_DISP1_MID_SEL << 14)	\ +				| (MUX_ACLK_200_SEL << 12)		\ +				| (MUX_ACLK_166_SEL << 8)) + +/* CLK_SRC_TOP1	*/ +#define MUX_ACLK_400_G3D_SEL            0x1 +#define MUX_ACLK_400_ISP_SEL            0x0 +#define MUX_ACLK_400_IOP_SEL            0x0 +#define MUX_ACLK_MIPI_HSI_TXBASE_SEL    0x0 +#define MUX_ACLK_300_GSCL_MID1_SEL      0x0 +#define MUX_ACLK_300_DISP1_MID1_SEL     0x0 +#define CLK_SRC_TOP1_VAL	((MUX_ACLK_400_G3D_SEL << 28)           \ +				|(MUX_ACLK_400_ISP_SEL << 24)           \ +				|(MUX_ACLK_400_IOP_SEL << 20)           \ +				|(MUX_ACLK_MIPI_HSI_TXBASE_SEL << 16)   \ +				|(MUX_ACLK_300_GSCL_MID1_SEL << 12)     \ +				|(MUX_ACLK_300_DISP1_MID1_SEL << 8)) + +/* CLK_SRC_TOP2 */ +#define MUX_GPLL_SEL                    0x1 +#define MUX_BPLL_USER_SEL               0x0 +#define MUX_MPLL_USER_SEL               0x0 +#define MUX_VPLL_SEL                    0x1 +#define MUX_EPLL_SEL                    0x1 +#define MUX_CPLL_SEL                    0x1 +#define VPLLSRC_SEL                     0x0 +#define CLK_SRC_TOP2_VAL	((MUX_GPLL_SEL << 28)		\ +				| (MUX_BPLL_USER_SEL << 24)	\ +				| (MUX_MPLL_USER_SEL << 20)	\ +				| (MUX_VPLL_SEL << 16)	        \ +				| (MUX_EPLL_SEL << 12)	        \ +				| (MUX_CPLL_SEL << 8)           \ +				| (VPLLSRC_SEL)) +/* CLK_SRC_TOP3 */ +#define MUX_ACLK_333_SUB_SEL            0x1 +#define MUX_ACLK_400_SUB_SEL            0x1 +#define MUX_ACLK_266_ISP_SUB_SEL        0x1 +#define MUX_ACLK_266_GPS_SUB_SEL        0x0 +#define MUX_ACLK_300_GSCL_SUB_SEL       0x1 +#define MUX_ACLK_266_GSCL_SUB_SEL       0x1 +#define MUX_ACLK_300_DISP1_SUB_SEL      0x1 +#define MUX_ACLK_200_DISP1_SUB_SEL      0x1 +#define CLK_SRC_TOP3_VAL	((MUX_ACLK_333_SUB_SEL << 24)	        \ +				| (MUX_ACLK_400_SUB_SEL << 20)	        \ +				| (MUX_ACLK_266_ISP_SUB_SEL << 16)	\ +				| (MUX_ACLK_266_GPS_SUB_SEL << 12)      \ +				| (MUX_ACLK_300_GSCL_SUB_SEL << 10)     \ +				| (MUX_ACLK_266_GSCL_SUB_SEL << 8)      \ +				| (MUX_ACLK_300_DISP1_SUB_SEL << 6)     \ +				| (MUX_ACLK_200_DISP1_SUB_SEL << 4)) + +/* CLK_DIV_TOP0	*/ +#define ACLK_300_DISP1_RATIO	0x2 +#define ACLK_400_G3D_RATIO	0x0 +#define ACLK_333_RATIO		0x0 +#define ACLK_266_RATIO		0x2 +#define ACLK_200_RATIO		0x3 +#define ACLK_166_RATIO		0x1 +#define ACLK_133_RATIO		0x1 +#define ACLK_66_RATIO		0x5 + +#define CLK_DIV_TOP0_VAL	((ACLK_300_DISP1_RATIO << 28)	\ +				| (ACLK_400_G3D_RATIO << 24)	\ +				| (ACLK_333_RATIO  << 20)	\ +				| (ACLK_266_RATIO << 16)	\ +				| (ACLK_200_RATIO << 12)	\ +				| (ACLK_166_RATIO << 8)		\ +				| (ACLK_133_RATIO << 4)		\ +				| (ACLK_66_RATIO)) + +/* CLK_DIV_TOP1	*/ +#define ACLK_MIPI_HSI_TX_BASE_RATIO     0x3 +#define ACLK_66_PRE_RATIO               0x1 +#define ACLK_400_ISP_RATIO              0x1 +#define ACLK_400_IOP_RATIO              0x1 +#define ACLK_300_GSCL_RATIO             0x2 + +#define CLK_DIV_TOP1_VAL	((ACLK_MIPI_HSI_TX_BASE_RATIO << 28)	\ +				| (ACLK_66_PRE_RATIO << 24)		\ +				| (ACLK_400_ISP_RATIO  << 20)		\ +				| (ACLK_400_IOP_RATIO << 16)		\ +				| (ACLK_300_GSCL_RATIO << 12)) + +/* APLL_LOCK	*/ +#define APLL_LOCK_VAL	(0x546) +/* MPLL_LOCK	*/ +#define MPLL_LOCK_VAL	(0x546) +/* CPLL_LOCK	*/ +#define CPLL_LOCK_VAL	(0x546) +/* GPLL_LOCK	*/ +#define GPLL_LOCK_VAL	(0x546) +/* EPLL_LOCK	*/ +#define EPLL_LOCK_VAL	(0x3A98) +/* VPLL_LOCK	*/ +#define VPLL_LOCK_VAL	(0x3A98) +/* BPLL_LOCK	*/ +#define BPLL_LOCK_VAL	(0x546) + +#define MUX_APLL_SEL_MASK	(1 << 0) +#define MUX_MPLL_SEL_MASK	(1 << 8) +#define MPLL_SEL_MOUT_MPLLFOUT	(2 << 8) +#define MUX_CPLL_SEL_MASK	(1 << 8) +#define MUX_EPLL_SEL_MASK	(1 << 12) +#define MUX_VPLL_SEL_MASK	(1 << 16) +#define MUX_GPLL_SEL_MASK	(1 << 28) +#define MUX_BPLL_SEL_MASK	(1 << 0) +#define MUX_HPM_SEL_MASK	(1 << 20) +#define HPM_SEL_SCLK_MPLL	(1 << 21) +#define APLL_CON0_LOCKED	(1 << 29) +#define MPLL_CON0_LOCKED	(1 << 29) +#define BPLL_CON0_LOCKED	(1 << 29) +#define CPLL_CON0_LOCKED	(1 << 29) +#define EPLL_CON0_LOCKED	(1 << 29) +#define GPLL_CON0_LOCKED	(1 << 29) +#define VPLL_CON0_LOCKED	(1 << 29) +#define CLK_REG_DISABLE		0x0 +#define TOP2_VAL		0x0110000 + +/* CLK_SRC_PERIC0 */ +#define PWM_SEL		6 +#define UART3_SEL	6 +#define UART2_SEL	6 +#define UART1_SEL	6 +#define UART0_SEL	6 +/* SRC_CLOCK = SCLK_MPLL */ +#define CLK_SRC_PERIC0_VAL	((PWM_SEL << 24)        \ +				| (UART3_SEL << 12)     \ +				| (UART2_SEL << 8)       \ +				| (UART1_SEL << 4)      \ +				| (UART0_SEL)) + +/* CLK_SRC_PERIC1 */ +/* SRC_CLOCK = SCLK_MPLL */ +#define SPI0_SEL		6 +#define SPI1_SEL		6 +#define SPI2_SEL		6 +#define CLK_SRC_PERIC1_VAL	((SPI2_SEL << 24) \ +				| (SPI1_SEL << 20) \ +				| (SPI0_SEL << 16)) + +/* SCLK_SRC_ISP - set SPI0/1 to 6 = SCLK_MPLL_USER */ +#define SPI0_ISP_SEL		6 +#define SPI1_ISP_SEL		6 +#define SCLK_SRC_ISP_VAL	(SPI1_ISP_SEL << 4) \ +				| (SPI0_ISP_SEL << 0) + +/* SCLK_DIV_ISP - set SPI0/1 to 0xf = divide by 16 */ +#define SPI0_ISP_RATIO		0xf +#define SPI1_ISP_RATIO		0xf +#define SCLK_DIV_ISP_VAL	(SPI1_ISP_RATIO << 12) \ +				| (SPI0_ISP_RATIO << 0) + +/* CLK_DIV_PERIL0	*/ +#define UART5_RATIO	7 +#define UART4_RATIO	7 +#define UART3_RATIO	7 +#define UART2_RATIO	7 +#define UART1_RATIO	7 +#define UART0_RATIO	7 + +#define CLK_DIV_PERIC0_VAL	((UART3_RATIO << 12)    \ +				| (UART2_RATIO << 8)    \ +				| (UART1_RATIO << 4)    \ +				| (UART0_RATIO)) +/* CLK_DIV_PERIC1 */ +#define SPI1_RATIO		0x7 +#define SPI0_RATIO		0xf +#define SPI1_SUB_RATIO		0x0 +#define SPI0_SUB_RATIO		0x0 +#define CLK_DIV_PERIC1_VAL	((SPI1_SUB_RATIO << 24) \ +				| ((SPI1_RATIO << 16) \ +				| (SPI0_SUB_RATIO << 8) \ +				| (SPI0_RATIO << 0))) + +/* CLK_DIV_PERIC2 */ +#define SPI2_RATIO		0xf +#define SPI2_SUB_RATIO		0x0 +#define CLK_DIV_PERIC2_VAL	((SPI2_SUB_RATIO << 8) \ +				| (SPI2_RATIO << 0)) + +/* CLK_DIV_PERIC3 */ +#define PWM_RATIO		8 +#define CLK_DIV_PERIC3_VAL	(PWM_RATIO << 0) + +/* CLK_DIV_FSYS2 */ +#define MMC2_RATIO_MASK		0xf +#define MMC2_RATIO_VAL		0x3 +#define MMC2_RATIO_OFFSET	0 + +#define MMC2_PRE_RATIO_MASK	0xff +#define MMC2_PRE_RATIO_VAL	0x9 +#define MMC2_PRE_RATIO_OFFSET	8 + +#define MMC3_RATIO_MASK		0xf +#define MMC3_RATIO_VAL		0x1 +#define MMC3_RATIO_OFFSET	16 + +#define MMC3_PRE_RATIO_MASK	0xff +#define MMC3_PRE_RATIO_VAL	0x0 +#define MMC3_PRE_RATIO_OFFSET	24 + +/* CLK_SRC_LEX */ +#define CLK_SRC_LEX_VAL         0x0 + +/* CLK_DIV_LEX */ +#define CLK_DIV_LEX_VAL         0x10 + +/* CLK_DIV_R0X */ +#define CLK_DIV_R0X_VAL         0x10 + +/* CLK_DIV_L0X */ +#define CLK_DIV_R1X_VAL         0x10 + +/* CLK_DIV_ISP0 */ +#define CLK_DIV_ISP0_VAL        0x31 + +/* CLK_DIV_ISP1 */ +#define CLK_DIV_ISP1_VAL        0x0 + +/* CLK_DIV_ISP2 */ +#define CLK_DIV_ISP2_VAL        0x1 + +/* CLK_SRC_DISP1_0 */ +#define CLK_SRC_DISP1_0_VAL	0x6 + +/* + * DIV_DISP1_0 + * For DP, divisor should be 2 + */ +#define CLK_DIV_DISP1_0_FIMD1	(2 << 0) + +/* CLK_GATE_IP_DISP1 */ +#define CLK_GATE_DP1_ALLOW	(1 << 4) + +#define DDR3PHY_CTRL_PHY_RESET	(1 << 0) +#define DDR3PHY_CTRL_PHY_RESET_OFF	(0 << 0) + +#define PHY_CON0_RESET_VAL	0x17020a40 +#define P0_CMD_EN		(1 << 14) +#define BYTE_RDLVL_EN		(1 << 13) +#define CTRL_SHGATE		(1 << 8) + +#define PHY_CON1_RESET_VAL	0x09210100 +#define CTRL_GATEDURADJ_MASK	(0xf << 20) + +#define PHY_CON2_RESET_VAL	0x00010004 +#define INIT_DESKEW_EN		(1 << 6) +#define RDLVL_GATE_EN		(1 << 24) + +/*ZQ Configurations */ +#define PHY_CON16_RESET_VAL	0x08000304 + +#define ZQ_CLK_DIV_EN		(1 << 18) +#define ZQ_MANUAL_STR		(1 << 1) +#define ZQ_DONE			(1 << 0) + +#define CTRL_RDLVL_GATE_ENABLE	1 +#define CTRL_RDLVL_GATE_DISABLE	1 + +/* Direct Command */ +#define DIRECT_CMD_NOP			0x07000000 +#define DIRECT_CMD_PALL			0x01000000 +#define DIRECT_CMD_ZQINIT		0x0a000000 +#define DIRECT_CMD_CHANNEL_SHIFT	28 +#define DIRECT_CMD_CHIP_SHIFT		20 + +/* DMC PHY Control0 register */ +#define PHY_CONTROL0_RESET_VAL	0x0 +#define MEM_TERM_EN	(1 << 31)	/* Termination enable for memory */ +#define PHY_TERM_EN	(1 << 30)	/* Termination enable for PHY */ +#define DMC_CTRL_SHGATE	(1 << 29)	/* Duration of DQS gating signal */ +#define FP_RSYNC	(1 << 3)	/* Force DLL resyncronization */ + +/* Driver strength for CK, CKE, CS & CA */ +#define IMP_OUTPUT_DRV_40_OHM	0x5 +#define IMP_OUTPUT_DRV_30_OHM	0x7 +#define CA_CK_DRVR_DS_OFFSET	9 +#define CA_CKE_DRVR_DS_OFFSET	6 +#define CA_CS_DRVR_DS_OFFSET	3 +#define CA_ADR_DRVR_DS_OFFSET	0 + +#define PHY_CON42_CTRL_BSTLEN_SHIFT	8 +#define PHY_CON42_CTRL_RDLAT_SHIFT	0 + +struct mem_timings; + +/* Errors that we can encourter in low-level setup */ +enum { +	SETUP_ERR_OK, +	SETUP_ERR_RDLV_COMPLETE_TIMEOUT = -1, +	SETUP_ERR_ZQ_CALIBRATION_FAILURE = -2, +}; + +/* + * Memory variant specific initialization code + * + * @param mem		Memory timings for this memory type. + * @param mem_iv_size	Memory interleaving size is a configurable parameter + *			which the DMC uses to decide how to split a memory + *			chunk into smaller chunks to support concurrent + *			accesses; may vary across boards. + * @param reset         Reset DDR PHY during initialization. + * @return 0 if ok, SETUP_ERR_... if there is a problem + */ +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, +			int reset); + +/* + * Configure ZQ I/O interface + * + * @param mem		Memory timings for this memory type. + * @param phy0_ctrl	Pointer to struct containing PHY0 control reg + * @param phy1_ctrl	Pointer to struct containing PHY1 control reg + * @return 0 if ok, -1 on error + */ +int dmc_config_zq(struct mem_timings *mem, +		  struct exynos5_phy_control *phy0_ctrl, +		  struct exynos5_phy_control *phy1_ctrl); + +/* + * Send NOP and MRS/EMRS Direct commands + * + * @param mem		Memory timings for this memory type. + * @param dmc		Pointer to struct of DMC registers + */ +void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc); + +/* + * Send PALL Direct commands + * + * @param mem		Memory timings for this memory type. + * @param dmc		Pointer to struct of DMC registers + */ +void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc); + +/* + * Configure the memconfig and membaseconfig registers + * + * @param mem		Memory timings for this memory type. + * @param exynos5_dmc	Pointer to struct of DMC registers + */ +void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc); + +/* + * Reset the DLL. This function is common between DDR3 and LPDDR2. + * However, the reset value is different. So we are passing a flag + * ddr_mode to distinguish between LPDDR2 and DDR3. + * + * @param exynos5_dmc	Pointer to struct of DMC registers + * @param ddr_mode	Type of DDR memory + */ +void update_reset_dll(struct exynos5_dmc *, enum ddr_mode); +#endif diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c new file mode 100644 index 000000000..11fe5b8d0 --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -0,0 +1,73 @@ +/* + * Lowlevel setup for EXYNOS5 based board + * + * Copyright (C) 2013 Samsung Electronics + * Rajeshwari Shinde <rajeshwari.s@samsung.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <asm/arch/cpu.h> +#include <asm/arch/dmc.h> +#include <asm/arch/power.h> +#include <asm/arch/tzpc.h> +#include <asm/arch/periph.h> +#include <asm/arch/pinmux.h> +#include "common_setup.h" + +/* These are the things we can do during low-level init */ +enum { +	DO_WAKEUP	= 1 << 0, +	DO_CLOCKS	= 1 << 1, +	DO_MEM_RESET	= 1 << 2, +	DO_UART		= 1 << 3, +}; + +int do_lowlevel_init(void) +{ +	uint32_t reset_status; +	int actions = 0; + +	arch_cpu_init(); + +	reset_status = get_reset_status(); + +	switch (reset_status) { +	case S5P_CHECK_SLEEP: +		actions = DO_CLOCKS | DO_WAKEUP; +		break; +	case S5P_CHECK_DIDLE: +	case S5P_CHECK_LPA: +		actions = DO_WAKEUP; +		break; +	default: +		/* This is a normal boot (not a wake from sleep) */ +		actions = DO_CLOCKS | DO_MEM_RESET; +	} + +	if (actions & DO_CLOCKS) { +		system_clock_init(); +		mem_ctrl_init(actions & DO_MEM_RESET); +		tzpc_init(); +	} + +	return actions & DO_WAKEUP; +} diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index bd499b476..204206234 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -408,9 +408,49 @@ static int exynos4_mmc_config(int peripheral, int flags)  	return 0;  } +static void exynos4_uart_config(int peripheral) +{ +	struct exynos4_gpio_part1 *gpio1 = +		(struct exynos4_gpio_part1 *)samsung_get_base_gpio_part1(); +	struct s5p_gpio_bank *bank; +	int i, start, count; + +	switch (peripheral) { +	case PERIPH_ID_UART0: +		bank = &gpio1->a0; +		start = 0; +		count = 4; +		break; +	case PERIPH_ID_UART1: +		bank = &gpio1->a0; +		start = 4; +		count = 4; +		break; +	case PERIPH_ID_UART2: +		bank = &gpio1->a1; +		start = 0; +		count = 4; +		break; +	case PERIPH_ID_UART3: +		bank = &gpio1->a1; +		start = 4; +		count = 2; +		break; +	} +	for (i = start; i < start + count; i++) { +		s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); +		s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); +	} +}  static int exynos4_pinmux_config(int peripheral, int flags)  {  	switch (peripheral) { +	case PERIPH_ID_UART0: +	case PERIPH_ID_UART1: +	case PERIPH_ID_UART2: +	case PERIPH_ID_UART3: +		exynos4_uart_config(peripheral); +		break;  	case PERIPH_ID_I2C0:  	case PERIPH_ID_I2C1:  	case PERIPH_ID_I2C2: diff --git a/arch/arm/cpu/armv7/exynos/power.c b/arch/arm/cpu/armv7/exynos/power.c index 6375a81fd..5d3bda2ad 100644 --- a/arch/arm/cpu/armv7/exynos/power.c +++ b/arch/arm/cpu/armv7/exynos/power.c @@ -140,3 +140,53 @@ void set_hw_thermal_trip(void)  		setbits_le32(&power->ps_hold_control, POWER_ENABLE_HW_TRIP);  	}  } + +static uint32_t exynos5_get_reset_status(void) +{ +	struct exynos5_power *power = +		(struct exynos5_power *)samsung_get_base_power(); + +	return power->inform1; +} + +static uint32_t exynos4_get_reset_status(void) +{ +	struct exynos4_power *power = +		(struct exynos4_power *)samsung_get_base_power(); + +	return power->inform1; +} + +uint32_t get_reset_status(void) +{ +	if (cpu_is_exynos5()) +		return exynos5_get_reset_status(); +	else +		return  exynos4_get_reset_status(); +} + +static void exynos5_power_exit_wakeup(void) +{ +	struct exynos5_power *power = +		(struct exynos5_power *)samsung_get_base_power(); +	typedef void (*resume_func)(void); + +	((resume_func)power->inform0)(); +} + +static void exynos4_power_exit_wakeup(void) +{ +	struct exynos4_power *power = +		(struct exynos4_power *)samsung_get_base_power(); +	typedef void (*resume_func)(void); + +	((resume_func)power->inform0)(); +} + +void power_exit_wakeup(void) +{ +	if (cpu_is_exynos5()) +		exynos5_power_exit_wakeup(); +	else +		exynos4_power_exit_wakeup(); +} diff --git a/arch/arm/cpu/armv7/exynos/spl_boot.c b/arch/arm/cpu/armv7/exynos/spl_boot.c new file mode 100644 index 000000000..6e8dd3b5d --- /dev/null +++ b/arch/arm/cpu/armv7/exynos/spl_boot.c @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include<common.h> +#include<config.h> + +#include <asm/arch/clock.h> +#include <asm/arch/clk.h> +#include <asm/arch/dmc.h> +#include <asm/arch/power.h> +#include <asm/arch/spl.h> + +#include "common_setup.h" +#include "clock_init.h" + +DECLARE_GLOBAL_DATA_PTR; +#define OM_STAT         (0x1f << 1) + +/* Index into irom ptr table */ +enum index { +	MMC_INDEX, +	EMMC44_INDEX, +	EMMC44_END_INDEX, +	SPI_INDEX, +	USB_INDEX, +}; + +/* IROM Function Pointers Table */ +u32 irom_ptr_table[] = { +	[MMC_INDEX] = 0x02020030,	/* iROM Function Pointer-SDMMC boot */ +	[EMMC44_INDEX] = 0x02020044,	/* iROM Function Pointer-EMMC4.4 boot*/ +	[EMMC44_END_INDEX] = 0x02020048,/* iROM Function Pointer +						-EMMC4.4 end boot operation */ +	[SPI_INDEX] = 0x02020058,	/* iROM Function Pointer-SPI boot */ +	[USB_INDEX] = 0x02020070,	/* iROM Function Pointer-USB boot*/ +	}; + +void *get_irom_func(int index) +{ +	return (void *)*(u32 *)irom_ptr_table[index]; +} + +#ifdef CONFIG_USB_BOOTING +/* + * Set/clear program flow prediction and return the previous state. + */ +static int config_branch_prediction(int set_cr_z) +{ +	unsigned int cr; + +	/* System Control Register: 11th bit Z Branch prediction enable */ +	cr = get_cr(); +	set_cr(set_cr_z ? cr | CR_Z : cr & ~CR_Z); + +	return cr & CR_Z; +} +#endif + +/* +* Copy U-boot from mmc to RAM: +* COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains +* Pointer to API (Data transfer from mmc to ram) +*/ +void copy_uboot_to_ram(void) +{ +	enum boot_mode bootmode = BOOT_MODE_OM; + +	u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL; +	u32 offset = 0, size = 0; +#ifdef CONFIG_SUPPORT_EMMC_BOOT +	u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst); +	void (*end_bootop_from_emmc)(void); +#endif +#ifdef CONFIG_USB_BOOTING +	u32 (*usb_copy)(void); +	int is_cr_z_set; +	unsigned int sec_boot_check; + +	/* Read iRAM location to check for secondary USB boot mode */ +	sec_boot_check = readl(EXYNOS_IRAM_SECONDARY_BASE); +	if (sec_boot_check == EXYNOS_USB_SECONDARY_BOOT) +		bootmode = BOOT_MODE_USB; +#endif + +	if (bootmode == BOOT_MODE_OM) +		bootmode = readl(samsung_get_base_power()) & OM_STAT; + +	switch (bootmode) { +#ifdef CONFIG_SPI_BOOTING +	case BOOT_MODE_SERIAL: +		offset = SPI_FLASH_UBOOT_POS; +		size = CONFIG_BL2_SIZE; +		copy_bl2 = get_irom_func(SPI_INDEX); +		break; +#endif +	case BOOT_MODE_MMC: +		offset = BL2_START_OFFSET; +		size = BL2_SIZE_BLOC_COUNT; +		copy_bl2 = get_irom_func(MMC_INDEX); +		break; +#ifdef CONFIG_SUPPORT_EMMC_BOOT +	case BOOT_MODE_EMMC: +		/* Set the FSYS1 clock divisor value for EMMC boot */ +		emmc_boot_clk_div_set(); + +		copy_bl2_from_emmc = get_irom_func(EMMC44_INDEX); +		end_bootop_from_emmc = get_irom_func(EMMC44_END_INDEX); + +		copy_bl2_from_emmc(BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE); +		end_bootop_from_emmc(); +		break; +#endif +#ifdef CONFIG_USB_BOOTING +	case BOOT_MODE_USB: +		/* +		 * iROM needs program flow prediction to be disabled +		 * before copy from USB device to RAM +		 */ +		is_cr_z_set = config_branch_prediction(0); +		usb_copy = get_irom_func(USB_INDEX); +		usb_copy(); +		config_branch_prediction(is_cr_z_set); +		break; +#endif +	default: +		break; +	} + +	if (copy_bl2) +		copy_bl2(offset, size, CONFIG_SYS_TEXT_BASE); +} + +void memzero(void *s, size_t n) +{ +	char *ptr = s; +	size_t i; + +	for (i = 0; i < n; i++) +		*ptr++ = '\0'; +} + +/** + * Set up the U-Boot global_data pointer + * + * This sets the address of the global data, and sets up basic values. + * + * @param gdp   Value to give to gd + */ +static void setup_global_data(gd_t *gdp) +{ +	gd = gdp; +	memzero((void *)gd, sizeof(gd_t)); +	gd->flags |= GD_FLG_RELOC; +	gd->baudrate = CONFIG_BAUDRATE; +	gd->have_console = 1; +} + +void board_init_f(unsigned long bootflag) +{ +	__aligned(8) gd_t local_gd; +	__attribute__((noreturn)) void (*uboot)(void); + +	setup_global_data(&local_gd); + +	if (do_lowlevel_init()) +		power_exit_wakeup(); + +	copy_uboot_to_ram(); + +	/* Jump to U-Boot image */ +	uboot = (void *)CONFIG_SYS_TEXT_BASE; +	(*uboot)(); +	/* Never returns Here */ +} + +/* Place Holders */ +void board_init_r(gd_t *id, ulong dest_addr) +{ +	/* Function attribute is no-return */ +	/* This Function never executes */ +	while (1) +		; +} +void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {} |