Message ID | 1364290670-7443-4-git-send-email-inderpal.singh@linaro.org |
---|---|
State | New |
Headers | show |
Hi Inderpal Sigh, Most of the files added here are same as in SMDK5250, then can't we use the same code instead of adding a new folder? Regards, Rajeshwari Shinde. On Tue, Mar 26, 2013 at 3:07 PM, Inderpal Singh <inderpal.singh@linaro.org> wrote: > Arndale board is based on samsung's exynos5250 soc. > > Signed-off-by: Inderpal Singh <inderpal.singh@linaro.org> > --- > MAINTAINERS | 4 + > board/samsung/arndale/Makefile | 54 +++ > board/samsung/arndale/arndale.c | 117 ++++++ > board/samsung/arndale/arndale_spl.c | 66 +++ > board/samsung/arndale/clock_init.c | 655 ++++++++++++++++++++++++++++++ > board/samsung/arndale/clock_init.h | 149 +++++++ > board/samsung/arndale/dmc_common.c | 199 +++++++++ > board/samsung/arndale/dmc_init_ddr3.c | 228 +++++++++++ > board/samsung/arndale/lowlevel_init.S | 92 +++++ > board/samsung/arndale/setup.h | 569 ++++++++++++++++++++++++++ > board/samsung/dts/exynos5250-arndale.dts | 36 ++ > boards.cfg | 1 + > include/configs/arndale.h | 39 ++ > tools/Makefile | 2 + > 14 files changed, 2211 insertions(+) > create mode 100644 board/samsung/arndale/Makefile > create mode 100644 board/samsung/arndale/arndale.c > create mode 100644 board/samsung/arndale/arndale_spl.c > create mode 100644 board/samsung/arndale/clock_init.c > create mode 100644 board/samsung/arndale/clock_init.h > create mode 100644 board/samsung/arndale/dmc_common.c > create mode 100644 board/samsung/arndale/dmc_init_ddr3.c > create mode 100644 board/samsung/arndale/lowlevel_init.S > create mode 100644 board/samsung/arndale/setup.h > create mode 100644 board/samsung/dts/exynos5250-arndale.dts > create mode 100644 include/configs/arndale.h > > diff --git a/MAINTAINERS b/MAINTAINERS > index f6723ef..b112581 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -736,6 +736,10 @@ Chander Kashyap <k.chander@samsung.com> > SMDKV310 ARM ARMV7 (EXYNOS4210 SoC) > SMDK5250 ARM ARMV7 (EXYNOS5250 SoC) > > +Inderpal Singh <inderpal.singh@linaro.org> > + > + Arndale ARM ARMV7 (EXYNOS5250 SoC) > + > Lukasz Majewski <l.majewski@samsung.com> > > trats ARM ARMV7 (EXYNOS4210 SoC) > diff --git a/board/samsung/arndale/Makefile b/board/samsung/arndale/Makefile > new file mode 100644 > index 0000000..f65d111 > --- /dev/null > +++ b/board/samsung/arndale/Makefile > @@ -0,0 +1,54 @@ > +# > +# Copyright (C) 2013 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 $(TOPDIR)/config.mk > + > +LIB = $(obj)lib$(BOARD).o > + > +SOBJS := lowlevel_init.o > + > +COBJS := clock_init.o > +COBJS += dmc_common.o dmc_init_ddr3.o > +COBJS += arndale_spl.o > + > +ifndef CONFIG_SPL_BUILD > +COBJS += arndale.o > +endif > + > +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) > +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) > + > +ALL := $(obj).depend $(LIB) > + > +all: $(ALL) > + > +$(LIB): $(OBJS) > + $(call cmd_link_o_target, $(OBJS)) > + > +######################################################################### > + > +# defines $(obj).depend target > +include $(SRCTREE)/rules.mk > + > +sinclude $(obj).depend > + > +######################################################################### > diff --git a/board/samsung/arndale/arndale.c b/board/samsung/arndale/arndale.c > new file mode 100644 > index 0000000..7f8a568 > --- /dev/null > +++ b/board/samsung/arndale/arndale.c > @@ -0,0 +1,117 @@ > +/* > + * Copyright (C) 2013 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/pinmux.h> > +#include <asm/arch/dwmmc.h> > +#include <asm/arch/power.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +int board_init(void) > +{ > + gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL); > + return 0; > +} > + > +int dram_init(void) > +{ > + int i; > + u32 addr; > + > + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { > + addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); > + gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE); > + } > + return 0; > +} > + > +int power_init_board(void) > +{ > + set_ps_hold_ctrl(); > + return 0; > +} > + > +void dram_init_banksize(void) > +{ > + int i; > + u32 addr, size; > + > + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { > + addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); > + size = get_ram_size((long *)addr, SDRAM_BANK_SIZE); > + > + gd->bd->bi_dram[i].start = addr; > + gd->bd->bi_dram[i].size = size; > + } > +} > + > +#ifdef CONFIG_GENERIC_MMC > +int board_mmc_init(bd_t *bis) > +{ > + int ret; > + /* dwmmc initializattion for available channels */ > + ret = exynos_dwmmc_init(gd->fdt_blob); > + if (ret) > + debug("dwmmc init failed\n"); > + > + return ret; > +} > +#endif > + > +static int board_uart_init(void) > +{ > + int err, uart_id, ret = 0; > + > + for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) { > + err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE); > + if (err) { > + debug("UART%d not configured\n", > + (uart_id - PERIPH_ID_UART0)); > + ret |= err; > + } > + } > + return ret; > +} > + > +#ifdef CONFIG_BOARD_EARLY_INIT_F > +int board_early_init_f(void) > +{ > + int err; > + err = board_uart_init(); > + if (err) { > + debug("UART init failed\n"); > + return err; > + } > + return err; > +} > +#endif > + > +#ifdef CONFIG_DISPLAY_BOARDINFO > +int checkboard(void) > +{ > + printf("\nBoard: Arndale\n"); > + > + return 0; > +} > +#endif > + > diff --git a/board/samsung/arndale/arndale_spl.c b/board/samsung/arndale/arndale_spl.c > new file mode 100644 > index 0000000..8135708 > --- /dev/null > +++ b/board/samsung/arndale/arndale_spl.c > @@ -0,0 +1,66 @@ > +/* > + * Copyright (c) 2012 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 > + */ > + > +#include <common.h> > +#include <asm/arch/spl.h> > + > +#define SIGNATURE 0xdeadbeef > + > +/* Parameters of early board initialization in SPL */ > +static struct spl_machine_param machine_param > + __attribute__((section(".machine_param"))) = { > + .signature = SIGNATURE, > + .version = 1, > + .params = "vmubfasirM", > + .size = sizeof(machine_param), > + > + .mem_iv_size = 0x1f, > + .mem_type = DDR_MODE_DDR3, > + > + /* > + * Set uboot_size to 0x100000 bytes. > + * > + * This is an overly conservative value chosen to accommodate all > + * possible U-Boot image. You are advised to set this value to a > + * smaller realistic size via scripts that modifies the .machine_param > + * section of output U-Boot image. > + */ > + .uboot_size = 0x100000, > + > + .boot_source = BOOT_MODE_OM, > + .frequency_mhz = 800, > + .arm_freq_mhz = 1000, > + .serial_base = 0x12c30000, > + .i2c_base = 0x12c60000, > + .mem_manuf = MEM_MANUF_SAMSUNG, > +}; > + > +struct spl_machine_param *spl_get_machine_params(void) > +{ > + if (machine_param.signature != SIGNATURE) { > + /* Will hang if SIGNATURE dont match */ > + while (1) > + ; > + } > + > + return &machine_param; > +} > diff --git a/board/samsung/arndale/clock_init.c b/board/samsung/arndale/clock_init.c > new file mode 100644 > index 0000000..a9b0bbd > --- /dev/null > +++ b/board/samsung/arndale/clock_init.c > @@ -0,0 +1,655 @@ > +/* > + * Clock setup for Arndale board based on EXYNOS5 > + * > + * Copyright (C) 2013 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 "clock_init.h" > +#include "setup.h" > + > +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 > + * @return 0 if all ok > + */ > +static int 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; > + > + return 0; > +} > + > +/* 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; > + > + if (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; > + > + if (!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 *)EXYNOS5_CLOCK_BASE; > + 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_core1, MUX_CPLL_SEL_MASK); > + clrbits_le32(&clk->src_core1, MUX_EPLL_SEL_MASK); > + clrbits_le32(&clk->src_core1, MUX_VPLL_SEL_MASK); > + clrbits_le32(&clk->src_core1, 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) > + ; > + > + /* 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) > + ; > + > + /* 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) > + ; > + > + /* 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) > + ; > + > + /* 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) > + ; > + > + /* 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) > + ; > + > + /* 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) > + ; > + > + 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); > +} > diff --git a/board/samsung/arndale/clock_init.h b/board/samsung/arndale/clock_init.h > new file mode 100644 > index 0000000..5d01a6c > --- /dev/null > +++ b/board/samsung/arndale/clock_init.h > @@ -0,0 +1,149 @@ > +/* > + * 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 __ARNDALE_CLOCK_INIT_H > +#define __ARNDALE_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); > +#endif > diff --git a/board/samsung/arndale/dmc_common.c b/board/samsung/arndale/dmc_common.c > new file mode 100644 > index 0000000..5a51def > --- /dev/null > +++ b/board/samsung/arndale/dmc_common.c > @@ -0,0 +1,199 @@ > +/* > + * Mem setup common file for different types of DDR present on Arndale boards. > + * > + * Copyright (C) 2013 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 "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() > +{ > + 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); > + if (ret) { > + /* will hang if failed to init memory control */ > + while (1) > + ; > + } > + } else { > + /* will hang if unknow memory type */ > + while (1) > + ; > + } > +} > diff --git a/board/samsung/arndale/dmc_init_ddr3.c b/board/samsung/arndale/dmc_init_ddr3.c > new file mode 100644 > index 0000000..ce91451 > --- /dev/null > +++ b/board/samsung/arndale/dmc_init_ddr3.c > @@ -0,0 +1,228 @@ > +/* > + * DDR3 mem setup file for Arndale board based on EXYNOS5 > + * > + * Copyright (C) 2013 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 "setup.h" > +#include "clock_init.h" > + > +#define RDLVL_COMPLETE_TIMEOUT 10000 > + > +static void reset_phy_ctrl(void) > +{ > + struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; > + > + 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) > +{ > + unsigned int val; > + struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl; > + struct exynos5_dmc *dmc; > + int i; > + > + phy0_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY0_BASE; > + phy1_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY1_BASE; > + dmc = (struct exynos5_dmc *)EXYNOS5_DMC_CTRL_BASE; > + > + 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/board/samsung/arndale/lowlevel_init.S b/board/samsung/arndale/lowlevel_init.S > new file mode 100644 > index 0000000..4fa73a7 > --- /dev/null > +++ b/board/samsung/arndale/lowlevel_init.S > @@ -0,0 +1,92 @@ > +/* > + * Lowlevel setup for Arndale board based on Exynos5 > + * > + * Copyright (C) 2013 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 <version.h> > +#include <asm/arch/cpu.h> > + > +_TEXT_BASE: > + .word CONFIG_SYS_TEXT_BASE > + > + .globl lowlevel_init > +lowlevel_init: > + > + /* use iRAM stack in bl2 */ > + ldr sp, =CONFIG_IRAM_STACK > + stmdb r13!, {ip,lr} > + > + /* check reset status */ > + ldr r0, =(EXYNOS5_POWER_BASE + INFORM1_OFFSET) > + ldr r1, [r0] > + > + /* AFTR wakeup reset */ > + ldr r2, =S5P_CHECK_DIDLE > + cmp r1, r2 > + beq exit_wakeup > + > + /* Sleep wakeup reset */ > + ldr r2, =S5P_CHECK_SLEEP > + cmp r1, r2 > + beq wakeup_reset > + > + /* > + * If U-boot is already running in RAM, no need to relocate U-Boot. > + * Memory controller must be configured before relocating U-Boot > + * in ram. > + */ > + ldr r0, =0x0ffffff /* r0 <- Mask Bits*/ > + bic r1, pc, r0 /* pc <- current addr of code */ > + /* r1 <- unmasked bits of pc */ > + ldr r2, _TEXT_BASE /* r2 <- original base addr in ram */ > + bic r2, r2, r0 /* r2 <- unmasked bits of r2*/ > + cmp r1, r2 /* compare r1, r2 */ > + beq 1f /* r0 == r1 then skip sdram init */ > + > + /* init system clock */ > + bl system_clock_init > + > + /* Memory initialize */ > + bl mem_ctrl_init > +1: > + bl arch_cpu_init > + bl tzpc_init > + ldmia r13!, {ip,pc} > + > +wakeup_reset: > + bl system_clock_init > + bl mem_ctrl_init > + bl arch_cpu_init > + bl tzpc_init > + > +exit_wakeup: > + /* Load return address and jump to kernel */ > + ldr r0, =(EXYNOS5_POWER_BASE + INFORM0_OFFSET) > + > + /* r1 = physical address of exynos5_cpu_resume function*/ > + ldr r1, [r0] > + > + /* Jump to kernel */ > + mov pc, r1 > + nop > + nop > diff --git a/board/samsung/arndale/setup.h b/board/samsung/arndale/setup.h > new file mode 100644 > index 0000000..f68dd75 > --- /dev/null > +++ b/board/samsung/arndale/setup.h > @@ -0,0 +1,569 @@ > +/* > + * Machine Specific Values for Arndale board based on EXYNOS5 > + * > + * Copyright (C) 2013 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 _ARNDALE_SETUP_H > +#define _ARNDALE_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 0 > +#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. > + * @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); > + > +/* > + * 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); > + > +void sdelay(unsigned long); > +void mem_ctrl_init(void); > +void system_clock_init(void); > +#endif > diff --git a/board/samsung/dts/exynos5250-arndale.dts b/board/samsung/dts/exynos5250-arndale.dts > new file mode 100644 > index 0000000..9b4d6b2 > --- /dev/null > +++ b/board/samsung/dts/exynos5250-arndale.dts > @@ -0,0 +1,36 @@ > +/* > + * SAMSUNG Arndale board device tree source > + * > + * Copyright (c) 2013 Samsung Electronics Co., Ltd. > + * http://www.samsung.com > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > +*/ > + > +/dts-v1/; > +/include/ ARCH_CPU_DTS > + > +/ { > + model = "SAMSUNG Arndale board based on EXYNOS5250"; > + compatible = "samsung,arndale", "samsung,exynos5250"; > + > + mmc@12200000 { > + samsung,bus-width = <8>; > + samsung,timing = <1 3 3>; > + }; > + > + mmc@12210000 { > + status = "disabled"; > + }; > + > + mmc@12220000 { > + samsung,bus-width = <4>; > + samsung,timing = <1 2 3>; > + }; > + > + mmc@12230000 { > + status = "disabled"; > + }; > +}; > diff --git a/boards.cfg b/boards.cfg > index 54357eb..572b242 100644 > --- a/boards.cfg > +++ b/boards.cfg > @@ -288,6 +288,7 @@ origen arm armv7 origen samsung exynos > s5pc210_universal arm armv7 universal_c210 samsung exynos > snow arm armv7 smdk5250 samsung exynos > smdk5250 arm armv7 smdk5250 samsung exynos > +arndale arm armv7 arndale samsung exynos > smdkv310 arm armv7 smdkv310 samsung exynos > trats arm armv7 trats samsung exynos > harmony arm armv7:arm720t harmony nvidia tegra20 > diff --git a/include/configs/arndale.h b/include/configs/arndale.h > new file mode 100644 > index 0000000..caa83b8 > --- /dev/null > +++ b/include/configs/arndale.h > @@ -0,0 +1,39 @@ > +/* > + * Copyright (C) 2013 Samsung Electronics > + * > + * Configuration settings for the SAMSUNG Arndale board. > + * > + * 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 __CONFIG_ARNDALE_H > +#define __CONFIG_ARNDALE_H > + > +#undef CONFIG_DEFAULT_DEVICE_TREE > +#define CONFIG_DEFAULT_DEVICE_TREE exynos5250-arndale > + > +#define CONFIG_ARNDALE > + > +#define CONFIG_ENV_IS_IN_MMC > +#define CONFIG_SERIAL2 > +#define CONFIG_IDENT_STRING " for Arndale" > + > +#include <configs/exynos5250-dt.h> > + > +#endif /* __CONFIG_ARNDALE_H */ > diff --git a/tools/Makefile b/tools/Makefile > index c5952fc..ab7d339 100644 > --- a/tools/Makefile > +++ b/tools/Makefile > @@ -69,6 +69,7 @@ BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) > BIN_FILES-y += mkenvimage$(SFX) > BIN_FILES-y += mkimage$(SFX) > BIN_FILES-$(CONFIG_SMDK5250) += mksmdk5250spl$(SFX) > +BIN_FILES-$(CONFIG_ARNDALE) += mkarndalespl$(SFX) > BIN_FILES-$(CONFIG_MX23) += mxsboot$(SFX) > BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX) > BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) > @@ -99,6 +100,7 @@ NOPED_OBJ_FILES-y += omapimage.o > NOPED_OBJ_FILES-y += mkenvimage.o > NOPED_OBJ_FILES-y += mkimage.o > OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o > +OBJ_FILES-$(CONFIG_ARNDALE) += mkexynosspl.o > OBJ_FILES-$(CONFIG_MX23) += mxsboot.o > OBJ_FILES-$(CONFIG_MX28) += mxsboot.o > OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o > -- > 1.7.9.5 > > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > http://lists.denx.de/mailman/listinfo/u-boot
Dear Inderpal Singh,
In message <1364290670-7443-4-git-send-email-inderpal.singh@linaro.org> you wrote:
> Arndale board is based on samsung's exynos5250 soc.
WARNING: Avoid CamelCase: <DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED>
#618: FILE: board/samsung/arndale/clock_init.c:213:
+ .memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED |
WARNING: Avoid CamelCase: <DMC_MEMBASECONFIGx_CHIP_BASE>
#1860: FILE: board/samsung/arndale/setup.h:102:
+#define DMC_MEMBASECONFIGx_CHIP_BASE(x) (x << 16)
WARNING: Avoid CamelCase: <DMC_MEMBASECONFIGx_CHIP_MASK>
#1861: FILE: board/samsung/arndale/setup.h:103:
+#define DMC_MEMBASECONFIGx_CHIP_MASK(x) (x << 0)
ERROR: Macros with complex values should be enclosed in parenthesis
#2116: FILE: board/samsung/arndale/setup.h:358:
+#define SCLK_SRC_ISP_VAL (SPI1_ISP_SEL << 4) \
+ | (SPI0_ISP_SEL << 0)
ERROR: Macros with complex values should be enclosed in parenthesis
#2122: FILE: board/samsung/arndale/setup.h:364:
+#define SCLK_DIV_ISP_VAL (SPI1_ISP_RATIO << 12) \
+ | (SPI0_ISP_RATIO << 0)
ERROR: Macros with complex values should be enclosed in parenthesis
#2416: FILE: include/configs/arndale.h:29:
+#define CONFIG_DEFAULT_DEVICE_TREE exynos5250-arndale
total: 3 errors, 3 warnings, 2235 lines checked
/home/wd/Mail/U-Boot/7161 has style problems, please review.
Best regards,
Wolfgang Denk
Hi Rajeshwari, On 26 March 2013 16:46, Rajeshwari Birje <rajeshwari.birje@gmail.com> wrote: > Hi Inderpal Sigh, > > Most of the files added here are same as in SMDK5250, then can't we > use the same code instead of adding a new folder? > I had thought about it, in fact I had sent a patch few days back to use the same folder as smdk5250. But, there could be few board specific things like gpios etc which I think should be done in board specific folder. Hence this approach. Thanks, Inder > Regards, > Rajeshwari Shinde. > > On Tue, Mar 26, 2013 at 3:07 PM, Inderpal Singh > <inderpal.singh@linaro.org> wrote: >> Arndale board is based on samsung's exynos5250 soc. >> >> Signed-off-by: Inderpal Singh <inderpal.singh@linaro.org> >> --- >> MAINTAINERS | 4 + >> board/samsung/arndale/Makefile | 54 +++ >> board/samsung/arndale/arndale.c | 117 ++++++ >> board/samsung/arndale/arndale_spl.c | 66 +++ >> board/samsung/arndale/clock_init.c | 655 ++++++++++++++++++++++++++++++ >> board/samsung/arndale/clock_init.h | 149 +++++++ >> board/samsung/arndale/dmc_common.c | 199 +++++++++ >> board/samsung/arndale/dmc_init_ddr3.c | 228 +++++++++++ >> board/samsung/arndale/lowlevel_init.S | 92 +++++ >> board/samsung/arndale/setup.h | 569 ++++++++++++++++++++++++++ >> board/samsung/dts/exynos5250-arndale.dts | 36 ++ >> boards.cfg | 1 + >> include/configs/arndale.h | 39 ++ >> tools/Makefile | 2 + >> 14 files changed, 2211 insertions(+) >> create mode 100644 board/samsung/arndale/Makefile >> create mode 100644 board/samsung/arndale/arndale.c >> create mode 100644 board/samsung/arndale/arndale_spl.c >> create mode 100644 board/samsung/arndale/clock_init.c >> create mode 100644 board/samsung/arndale/clock_init.h >> create mode 100644 board/samsung/arndale/dmc_common.c >> create mode 100644 board/samsung/arndale/dmc_init_ddr3.c >> create mode 100644 board/samsung/arndale/lowlevel_init.S >> create mode 100644 board/samsung/arndale/setup.h >> create mode 100644 board/samsung/dts/exynos5250-arndale.dts >> create mode 100644 include/configs/arndale.h >> >> diff --git a/MAINTAINERS b/MAINTAINERS >> index f6723ef..b112581 100644 >> --- a/MAINTAINERS >> +++ b/MAINTAINERS >> @@ -736,6 +736,10 @@ Chander Kashyap <k.chander@samsung.com> >> SMDKV310 ARM ARMV7 (EXYNOS4210 SoC) >> SMDK5250 ARM ARMV7 (EXYNOS5250 SoC) >> >> +Inderpal Singh <inderpal.singh@linaro.org> >> + >> + Arndale ARM ARMV7 (EXYNOS5250 SoC) >> + >> Lukasz Majewski <l.majewski@samsung.com> >> >> trats ARM ARMV7 (EXYNOS4210 SoC) >> diff --git a/board/samsung/arndale/Makefile b/board/samsung/arndale/Makefile >> new file mode 100644 >> index 0000000..f65d111 >> --- /dev/null >> +++ b/board/samsung/arndale/Makefile >> @@ -0,0 +1,54 @@ >> +# >> +# Copyright (C) 2013 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 $(TOPDIR)/config.mk >> + >> +LIB = $(obj)lib$(BOARD).o >> + >> +SOBJS := lowlevel_init.o >> + >> +COBJS := clock_init.o >> +COBJS += dmc_common.o dmc_init_ddr3.o >> +COBJS += arndale_spl.o >> + >> +ifndef CONFIG_SPL_BUILD >> +COBJS += arndale.o >> +endif >> + >> +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) >> +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) >> + >> +ALL := $(obj).depend $(LIB) >> + >> +all: $(ALL) >> + >> +$(LIB): $(OBJS) >> + $(call cmd_link_o_target, $(OBJS)) >> + >> +######################################################################### >> + >> +# defines $(obj).depend target >> +include $(SRCTREE)/rules.mk >> + >> +sinclude $(obj).depend >> + >> +######################################################################### >> diff --git a/board/samsung/arndale/arndale.c b/board/samsung/arndale/arndale.c >> new file mode 100644 >> index 0000000..7f8a568 >> --- /dev/null >> +++ b/board/samsung/arndale/arndale.c >> @@ -0,0 +1,117 @@ >> +/* >> + * Copyright (C) 2013 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/pinmux.h> >> +#include <asm/arch/dwmmc.h> >> +#include <asm/arch/power.h> >> + >> +DECLARE_GLOBAL_DATA_PTR; >> + >> +int board_init(void) >> +{ >> + gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL); >> + return 0; >> +} >> + >> +int dram_init(void) >> +{ >> + int i; >> + u32 addr; >> + >> + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { >> + addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); >> + gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE); >> + } >> + return 0; >> +} >> + >> +int power_init_board(void) >> +{ >> + set_ps_hold_ctrl(); >> + return 0; >> +} >> + >> +void dram_init_banksize(void) >> +{ >> + int i; >> + u32 addr, size; >> + >> + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { >> + addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); >> + size = get_ram_size((long *)addr, SDRAM_BANK_SIZE); >> + >> + gd->bd->bi_dram[i].start = addr; >> + gd->bd->bi_dram[i].size = size; >> + } >> +} >> + >> +#ifdef CONFIG_GENERIC_MMC >> +int board_mmc_init(bd_t *bis) >> +{ >> + int ret; >> + /* dwmmc initializattion for available channels */ >> + ret = exynos_dwmmc_init(gd->fdt_blob); >> + if (ret) >> + debug("dwmmc init failed\n"); >> + >> + return ret; >> +} >> +#endif >> + >> +static int board_uart_init(void) >> +{ >> + int err, uart_id, ret = 0; >> + >> + for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) { >> + err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE); >> + if (err) { >> + debug("UART%d not configured\n", >> + (uart_id - PERIPH_ID_UART0)); >> + ret |= err; >> + } >> + } >> + return ret; >> +} >> + >> +#ifdef CONFIG_BOARD_EARLY_INIT_F >> +int board_early_init_f(void) >> +{ >> + int err; >> + err = board_uart_init(); >> + if (err) { >> + debug("UART init failed\n"); >> + return err; >> + } >> + return err; >> +} >> +#endif >> + >> +#ifdef CONFIG_DISPLAY_BOARDINFO >> +int checkboard(void) >> +{ >> + printf("\nBoard: Arndale\n"); >> + >> + return 0; >> +} >> +#endif >> + >> diff --git a/board/samsung/arndale/arndale_spl.c b/board/samsung/arndale/arndale_spl.c >> new file mode 100644 >> index 0000000..8135708 >> --- /dev/null >> +++ b/board/samsung/arndale/arndale_spl.c >> @@ -0,0 +1,66 @@ >> +/* >> + * Copyright (c) 2012 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 >> + */ >> + >> +#include <common.h> >> +#include <asm/arch/spl.h> >> + >> +#define SIGNATURE 0xdeadbeef >> + >> +/* Parameters of early board initialization in SPL */ >> +static struct spl_machine_param machine_param >> + __attribute__((section(".machine_param"))) = { >> + .signature = SIGNATURE, >> + .version = 1, >> + .params = "vmubfasirM", >> + .size = sizeof(machine_param), >> + >> + .mem_iv_size = 0x1f, >> + .mem_type = DDR_MODE_DDR3, >> + >> + /* >> + * Set uboot_size to 0x100000 bytes. >> + * >> + * This is an overly conservative value chosen to accommodate all >> + * possible U-Boot image. You are advised to set this value to a >> + * smaller realistic size via scripts that modifies the .machine_param >> + * section of output U-Boot image. >> + */ >> + .uboot_size = 0x100000, >> + >> + .boot_source = BOOT_MODE_OM, >> + .frequency_mhz = 800, >> + .arm_freq_mhz = 1000, >> + .serial_base = 0x12c30000, >> + .i2c_base = 0x12c60000, >> + .mem_manuf = MEM_MANUF_SAMSUNG, >> +}; >> + >> +struct spl_machine_param *spl_get_machine_params(void) >> +{ >> + if (machine_param.signature != SIGNATURE) { >> + /* Will hang if SIGNATURE dont match */ >> + while (1) >> + ; >> + } >> + >> + return &machine_param; >> +} >> diff --git a/board/samsung/arndale/clock_init.c b/board/samsung/arndale/clock_init.c >> new file mode 100644 >> index 0000000..a9b0bbd >> --- /dev/null >> +++ b/board/samsung/arndale/clock_init.c >> @@ -0,0 +1,655 @@ >> +/* >> + * Clock setup for Arndale board based on EXYNOS5 >> + * >> + * Copyright (C) 2013 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 "clock_init.h" >> +#include "setup.h" >> + >> +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 >> + * @return 0 if all ok >> + */ >> +static int 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; >> + >> + return 0; >> +} >> + >> +/* 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; >> + >> + if (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; >> + >> + if (!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 *)EXYNOS5_CLOCK_BASE; >> + 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_core1, MUX_CPLL_SEL_MASK); >> + clrbits_le32(&clk->src_core1, MUX_EPLL_SEL_MASK); >> + clrbits_le32(&clk->src_core1, MUX_VPLL_SEL_MASK); >> + clrbits_le32(&clk->src_core1, 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) >> + ; >> + >> + /* 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) >> + ; >> + >> + /* 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) >> + ; >> + >> + /* 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) >> + ; >> + >> + /* 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) >> + ; >> + >> + /* 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) >> + ; >> + >> + /* 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) >> + ; >> + >> + 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); >> +} >> diff --git a/board/samsung/arndale/clock_init.h b/board/samsung/arndale/clock_init.h >> new file mode 100644 >> index 0000000..5d01a6c >> --- /dev/null >> +++ b/board/samsung/arndale/clock_init.h >> @@ -0,0 +1,149 @@ >> +/* >> + * 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 __ARNDALE_CLOCK_INIT_H >> +#define __ARNDALE_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); >> +#endif >> diff --git a/board/samsung/arndale/dmc_common.c b/board/samsung/arndale/dmc_common.c >> new file mode 100644 >> index 0000000..5a51def >> --- /dev/null >> +++ b/board/samsung/arndale/dmc_common.c >> @@ -0,0 +1,199 @@ >> +/* >> + * Mem setup common file for different types of DDR present on Arndale boards. >> + * >> + * Copyright (C) 2013 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 "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() >> +{ >> + 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); >> + if (ret) { >> + /* will hang if failed to init memory control */ >> + while (1) >> + ; >> + } >> + } else { >> + /* will hang if unknow memory type */ >> + while (1) >> + ; >> + } >> +} >> diff --git a/board/samsung/arndale/dmc_init_ddr3.c b/board/samsung/arndale/dmc_init_ddr3.c >> new file mode 100644 >> index 0000000..ce91451 >> --- /dev/null >> +++ b/board/samsung/arndale/dmc_init_ddr3.c >> @@ -0,0 +1,228 @@ >> +/* >> + * DDR3 mem setup file for Arndale board based on EXYNOS5 >> + * >> + * Copyright (C) 2013 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 "setup.h" >> +#include "clock_init.h" >> + >> +#define RDLVL_COMPLETE_TIMEOUT 10000 >> + >> +static void reset_phy_ctrl(void) >> +{ >> + struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; >> + >> + 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) >> +{ >> + unsigned int val; >> + struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl; >> + struct exynos5_dmc *dmc; >> + int i; >> + >> + phy0_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY0_BASE; >> + phy1_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY1_BASE; >> + dmc = (struct exynos5_dmc *)EXYNOS5_DMC_CTRL_BASE; >> + >> + 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/board/samsung/arndale/lowlevel_init.S b/board/samsung/arndale/lowlevel_init.S >> new file mode 100644 >> index 0000000..4fa73a7 >> --- /dev/null >> +++ b/board/samsung/arndale/lowlevel_init.S >> @@ -0,0 +1,92 @@ >> +/* >> + * Lowlevel setup for Arndale board based on Exynos5 >> + * >> + * Copyright (C) 2013 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 <version.h> >> +#include <asm/arch/cpu.h> >> + >> +_TEXT_BASE: >> + .word CONFIG_SYS_TEXT_BASE >> + >> + .globl lowlevel_init >> +lowlevel_init: >> + >> + /* use iRAM stack in bl2 */ >> + ldr sp, =CONFIG_IRAM_STACK >> + stmdb r13!, {ip,lr} >> + >> + /* check reset status */ >> + ldr r0, =(EXYNOS5_POWER_BASE + INFORM1_OFFSET) >> + ldr r1, [r0] >> + >> + /* AFTR wakeup reset */ >> + ldr r2, =S5P_CHECK_DIDLE >> + cmp r1, r2 >> + beq exit_wakeup >> + >> + /* Sleep wakeup reset */ >> + ldr r2, =S5P_CHECK_SLEEP >> + cmp r1, r2 >> + beq wakeup_reset >> + >> + /* >> + * If U-boot is already running in RAM, no need to relocate U-Boot. >> + * Memory controller must be configured before relocating U-Boot >> + * in ram. >> + */ >> + ldr r0, =0x0ffffff /* r0 <- Mask Bits*/ >> + bic r1, pc, r0 /* pc <- current addr of code */ >> + /* r1 <- unmasked bits of pc */ >> + ldr r2, _TEXT_BASE /* r2 <- original base addr in ram */ >> + bic r2, r2, r0 /* r2 <- unmasked bits of r2*/ >> + cmp r1, r2 /* compare r1, r2 */ >> + beq 1f /* r0 == r1 then skip sdram init */ >> + >> + /* init system clock */ >> + bl system_clock_init >> + >> + /* Memory initialize */ >> + bl mem_ctrl_init >> +1: >> + bl arch_cpu_init >> + bl tzpc_init >> + ldmia r13!, {ip,pc} >> + >> +wakeup_reset: >> + bl system_clock_init >> + bl mem_ctrl_init >> + bl arch_cpu_init >> + bl tzpc_init >> + >> +exit_wakeup: >> + /* Load return address and jump to kernel */ >> + ldr r0, =(EXYNOS5_POWER_BASE + INFORM0_OFFSET) >> + >> + /* r1 = physical address of exynos5_cpu_resume function*/ >> + ldr r1, [r0] >> + >> + /* Jump to kernel */ >> + mov pc, r1 >> + nop >> + nop >> diff --git a/board/samsung/arndale/setup.h b/board/samsung/arndale/setup.h >> new file mode 100644 >> index 0000000..f68dd75 >> --- /dev/null >> +++ b/board/samsung/arndale/setup.h >> @@ -0,0 +1,569 @@ >> +/* >> + * Machine Specific Values for Arndale board based on EXYNOS5 >> + * >> + * Copyright (C) 2013 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 _ARNDALE_SETUP_H >> +#define _ARNDALE_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 0 >> +#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. >> + * @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); >> + >> +/* >> + * 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); >> + >> +void sdelay(unsigned long); >> +void mem_ctrl_init(void); >> +void system_clock_init(void); >> +#endif >> diff --git a/board/samsung/dts/exynos5250-arndale.dts b/board/samsung/dts/exynos5250-arndale.dts >> new file mode 100644 >> index 0000000..9b4d6b2 >> --- /dev/null >> +++ b/board/samsung/dts/exynos5250-arndale.dts >> @@ -0,0 +1,36 @@ >> +/* >> + * SAMSUNG Arndale board device tree source >> + * >> + * Copyright (c) 2013 Samsung Electronics Co., Ltd. >> + * http://www.samsung.com >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> +*/ >> + >> +/dts-v1/; >> +/include/ ARCH_CPU_DTS >> + >> +/ { >> + model = "SAMSUNG Arndale board based on EXYNOS5250"; >> + compatible = "samsung,arndale", "samsung,exynos5250"; >> + >> + mmc@12200000 { >> + samsung,bus-width = <8>; >> + samsung,timing = <1 3 3>; >> + }; >> + >> + mmc@12210000 { >> + status = "disabled"; >> + }; >> + >> + mmc@12220000 { >> + samsung,bus-width = <4>; >> + samsung,timing = <1 2 3>; >> + }; >> + >> + mmc@12230000 { >> + status = "disabled"; >> + }; >> +}; >> diff --git a/boards.cfg b/boards.cfg >> index 54357eb..572b242 100644 >> --- a/boards.cfg >> +++ b/boards.cfg >> @@ -288,6 +288,7 @@ origen arm armv7 origen samsung exynos >> s5pc210_universal arm armv7 universal_c210 samsung exynos >> snow arm armv7 smdk5250 samsung exynos >> smdk5250 arm armv7 smdk5250 samsung exynos >> +arndale arm armv7 arndale samsung exynos >> smdkv310 arm armv7 smdkv310 samsung exynos >> trats arm armv7 trats samsung exynos >> harmony arm armv7:arm720t harmony nvidia tegra20 >> diff --git a/include/configs/arndale.h b/include/configs/arndale.h >> new file mode 100644 >> index 0000000..caa83b8 >> --- /dev/null >> +++ b/include/configs/arndale.h >> @@ -0,0 +1,39 @@ >> +/* >> + * Copyright (C) 2013 Samsung Electronics >> + * >> + * Configuration settings for the SAMSUNG Arndale board. >> + * >> + * 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 __CONFIG_ARNDALE_H >> +#define __CONFIG_ARNDALE_H >> + >> +#undef CONFIG_DEFAULT_DEVICE_TREE >> +#define CONFIG_DEFAULT_DEVICE_TREE exynos5250-arndale >> + >> +#define CONFIG_ARNDALE >> + >> +#define CONFIG_ENV_IS_IN_MMC >> +#define CONFIG_SERIAL2 >> +#define CONFIG_IDENT_STRING " for Arndale" >> + >> +#include <configs/exynos5250-dt.h> >> + >> +#endif /* __CONFIG_ARNDALE_H */ >> diff --git a/tools/Makefile b/tools/Makefile >> index c5952fc..ab7d339 100644 >> --- a/tools/Makefile >> +++ b/tools/Makefile >> @@ -69,6 +69,7 @@ BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) >> BIN_FILES-y += mkenvimage$(SFX) >> BIN_FILES-y += mkimage$(SFX) >> BIN_FILES-$(CONFIG_SMDK5250) += mksmdk5250spl$(SFX) >> +BIN_FILES-$(CONFIG_ARNDALE) += mkarndalespl$(SFX) >> BIN_FILES-$(CONFIG_MX23) += mxsboot$(SFX) >> BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX) >> BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) >> @@ -99,6 +100,7 @@ NOPED_OBJ_FILES-y += omapimage.o >> NOPED_OBJ_FILES-y += mkenvimage.o >> NOPED_OBJ_FILES-y += mkimage.o >> OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o >> +OBJ_FILES-$(CONFIG_ARNDALE) += mkexynosspl.o >> OBJ_FILES-$(CONFIG_MX23) += mxsboot.o >> OBJ_FILES-$(CONFIG_MX28) += mxsboot.o >> OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o >> -- >> 1.7.9.5 >> >> _______________________________________________ >> U-Boot mailing list >> U-Boot@lists.denx.de >> http://lists.denx.de/mailman/listinfo/u-boot > > > > -- > Regards, > Rajeshwari Shinde
diff --git a/MAINTAINERS b/MAINTAINERS index f6723ef..b112581 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -736,6 +736,10 @@ Chander Kashyap <k.chander@samsung.com> SMDKV310 ARM ARMV7 (EXYNOS4210 SoC) SMDK5250 ARM ARMV7 (EXYNOS5250 SoC) +Inderpal Singh <inderpal.singh@linaro.org> + + Arndale ARM ARMV7 (EXYNOS5250 SoC) + Lukasz Majewski <l.majewski@samsung.com> trats ARM ARMV7 (EXYNOS4210 SoC) diff --git a/board/samsung/arndale/Makefile b/board/samsung/arndale/Makefile new file mode 100644 index 0000000..f65d111 --- /dev/null +++ b/board/samsung/arndale/Makefile @@ -0,0 +1,54 @@ +# +# Copyright (C) 2013 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).o + +SOBJS := lowlevel_init.o + +COBJS := clock_init.o +COBJS += dmc_common.o dmc_init_ddr3.o +COBJS += arndale_spl.o + +ifndef CONFIG_SPL_BUILD +COBJS += arndale.o +endif + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) + +ALL := $(obj).depend $(LIB) + +all: $(ALL) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/samsung/arndale/arndale.c b/board/samsung/arndale/arndale.c new file mode 100644 index 0000000..7f8a568 --- /dev/null +++ b/board/samsung/arndale/arndale.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2013 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/pinmux.h> +#include <asm/arch/dwmmc.h> +#include <asm/arch/power.h> + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL); + return 0; +} + +int dram_init(void) +{ + int i; + u32 addr; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); + gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE); + } + return 0; +} + +int power_init_board(void) +{ + set_ps_hold_ctrl(); + return 0; +} + +void dram_init_banksize(void) +{ + int i; + u32 addr, size; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); + size = get_ram_size((long *)addr, SDRAM_BANK_SIZE); + + gd->bd->bi_dram[i].start = addr; + gd->bd->bi_dram[i].size = size; + } +} + +#ifdef CONFIG_GENERIC_MMC +int board_mmc_init(bd_t *bis) +{ + int ret; + /* dwmmc initializattion for available channels */ + ret = exynos_dwmmc_init(gd->fdt_blob); + if (ret) + debug("dwmmc init failed\n"); + + return ret; +} +#endif + +static int board_uart_init(void) +{ + int err, uart_id, ret = 0; + + for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) { + err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE); + if (err) { + debug("UART%d not configured\n", + (uart_id - PERIPH_ID_UART0)); + ret |= err; + } + } + return ret; +} + +#ifdef CONFIG_BOARD_EARLY_INIT_F +int board_early_init_f(void) +{ + int err; + err = board_uart_init(); + if (err) { + debug("UART init failed\n"); + return err; + } + return err; +} +#endif + +#ifdef CONFIG_DISPLAY_BOARDINFO +int checkboard(void) +{ + printf("\nBoard: Arndale\n"); + + return 0; +} +#endif + diff --git a/board/samsung/arndale/arndale_spl.c b/board/samsung/arndale/arndale_spl.c new file mode 100644 index 0000000..8135708 --- /dev/null +++ b/board/samsung/arndale/arndale_spl.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012 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 + */ + +#include <common.h> +#include <asm/arch/spl.h> + +#define SIGNATURE 0xdeadbeef + +/* Parameters of early board initialization in SPL */ +static struct spl_machine_param machine_param + __attribute__((section(".machine_param"))) = { + .signature = SIGNATURE, + .version = 1, + .params = "vmubfasirM", + .size = sizeof(machine_param), + + .mem_iv_size = 0x1f, + .mem_type = DDR_MODE_DDR3, + + /* + * Set uboot_size to 0x100000 bytes. + * + * This is an overly conservative value chosen to accommodate all + * possible U-Boot image. You are advised to set this value to a + * smaller realistic size via scripts that modifies the .machine_param + * section of output U-Boot image. + */ + .uboot_size = 0x100000, + + .boot_source = BOOT_MODE_OM, + .frequency_mhz = 800, + .arm_freq_mhz = 1000, + .serial_base = 0x12c30000, + .i2c_base = 0x12c60000, + .mem_manuf = MEM_MANUF_SAMSUNG, +}; + +struct spl_machine_param *spl_get_machine_params(void) +{ + if (machine_param.signature != SIGNATURE) { + /* Will hang if SIGNATURE dont match */ + while (1) + ; + } + + return &machine_param; +} diff --git a/board/samsung/arndale/clock_init.c b/board/samsung/arndale/clock_init.c new file mode 100644 index 0000000..a9b0bbd --- /dev/null +++ b/board/samsung/arndale/clock_init.c @@ -0,0 +1,655 @@ +/* + * Clock setup for Arndale board based on EXYNOS5 + * + * Copyright (C) 2013 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 "clock_init.h" +#include "setup.h" + +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 + * @return 0 if all ok + */ +static int 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; + + return 0; +} + +/* 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; + + if (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; + + if (!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 *)EXYNOS5_CLOCK_BASE; + 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_core1, MUX_CPLL_SEL_MASK); + clrbits_le32(&clk->src_core1, MUX_EPLL_SEL_MASK); + clrbits_le32(&clk->src_core1, MUX_VPLL_SEL_MASK); + clrbits_le32(&clk->src_core1, 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) + ; + + /* 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) + ; + + /* 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) + ; + + /* 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) + ; + + /* 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) + ; + + /* 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) + ; + + /* 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) + ; + + 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); +} diff --git a/board/samsung/arndale/clock_init.h b/board/samsung/arndale/clock_init.h new file mode 100644 index 0000000..5d01a6c --- /dev/null +++ b/board/samsung/arndale/clock_init.h @@ -0,0 +1,149 @@ +/* + * 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 __ARNDALE_CLOCK_INIT_H +#define __ARNDALE_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); +#endif diff --git a/board/samsung/arndale/dmc_common.c b/board/samsung/arndale/dmc_common.c new file mode 100644 index 0000000..5a51def --- /dev/null +++ b/board/samsung/arndale/dmc_common.c @@ -0,0 +1,199 @@ +/* + * Mem setup common file for different types of DDR present on Arndale boards. + * + * Copyright (C) 2013 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 "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() +{ + 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); + if (ret) { + /* will hang if failed to init memory control */ + while (1) + ; + } + } else { + /* will hang if unknow memory type */ + while (1) + ; + } +} diff --git a/board/samsung/arndale/dmc_init_ddr3.c b/board/samsung/arndale/dmc_init_ddr3.c new file mode 100644 index 0000000..ce91451 --- /dev/null +++ b/board/samsung/arndale/dmc_init_ddr3.c @@ -0,0 +1,228 @@ +/* + * DDR3 mem setup file for Arndale board based on EXYNOS5 + * + * Copyright (C) 2013 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 "setup.h" +#include "clock_init.h" + +#define RDLVL_COMPLETE_TIMEOUT 10000 + +static void reset_phy_ctrl(void) +{ + struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; + + 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) +{ + unsigned int val; + struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl; + struct exynos5_dmc *dmc; + int i; + + phy0_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY0_BASE; + phy1_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY1_BASE; + dmc = (struct exynos5_dmc *)EXYNOS5_DMC_CTRL_BASE; + + 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/board/samsung/arndale/lowlevel_init.S b/board/samsung/arndale/lowlevel_init.S new file mode 100644 index 0000000..4fa73a7 --- /dev/null +++ b/board/samsung/arndale/lowlevel_init.S @@ -0,0 +1,92 @@ +/* + * Lowlevel setup for Arndale board based on Exynos5 + * + * Copyright (C) 2013 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 <version.h> +#include <asm/arch/cpu.h> + +_TEXT_BASE: + .word CONFIG_SYS_TEXT_BASE + + .globl lowlevel_init +lowlevel_init: + + /* use iRAM stack in bl2 */ + ldr sp, =CONFIG_IRAM_STACK + stmdb r13!, {ip,lr} + + /* check reset status */ + ldr r0, =(EXYNOS5_POWER_BASE + INFORM1_OFFSET) + ldr r1, [r0] + + /* AFTR wakeup reset */ + ldr r2, =S5P_CHECK_DIDLE + cmp r1, r2 + beq exit_wakeup + + /* Sleep wakeup reset */ + ldr r2, =S5P_CHECK_SLEEP + cmp r1, r2 + beq wakeup_reset + + /* + * If U-boot is already running in RAM, no need to relocate U-Boot. + * Memory controller must be configured before relocating U-Boot + * in ram. + */ + ldr r0, =0x0ffffff /* r0 <- Mask Bits*/ + bic r1, pc, r0 /* pc <- current addr of code */ + /* r1 <- unmasked bits of pc */ + ldr r2, _TEXT_BASE /* r2 <- original base addr in ram */ + bic r2, r2, r0 /* r2 <- unmasked bits of r2*/ + cmp r1, r2 /* compare r1, r2 */ + beq 1f /* r0 == r1 then skip sdram init */ + + /* init system clock */ + bl system_clock_init + + /* Memory initialize */ + bl mem_ctrl_init +1: + bl arch_cpu_init + bl tzpc_init + ldmia r13!, {ip,pc} + +wakeup_reset: + bl system_clock_init + bl mem_ctrl_init + bl arch_cpu_init + bl tzpc_init + +exit_wakeup: + /* Load return address and jump to kernel */ + ldr r0, =(EXYNOS5_POWER_BASE + INFORM0_OFFSET) + + /* r1 = physical address of exynos5_cpu_resume function*/ + ldr r1, [r0] + + /* Jump to kernel */ + mov pc, r1 + nop + nop diff --git a/board/samsung/arndale/setup.h b/board/samsung/arndale/setup.h new file mode 100644 index 0000000..f68dd75 --- /dev/null +++ b/board/samsung/arndale/setup.h @@ -0,0 +1,569 @@ +/* + * Machine Specific Values for Arndale board based on EXYNOS5 + * + * Copyright (C) 2013 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 _ARNDALE_SETUP_H +#define _ARNDALE_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 0 +#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. + * @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); + +/* + * 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); + +void sdelay(unsigned long); +void mem_ctrl_init(void); +void system_clock_init(void); +#endif diff --git a/board/samsung/dts/exynos5250-arndale.dts b/board/samsung/dts/exynos5250-arndale.dts new file mode 100644 index 0000000..9b4d6b2 --- /dev/null +++ b/board/samsung/dts/exynos5250-arndale.dts @@ -0,0 +1,36 @@ +/* + * SAMSUNG Arndale board device tree source + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/dts-v1/; +/include/ ARCH_CPU_DTS + +/ { + model = "SAMSUNG Arndale board based on EXYNOS5250"; + compatible = "samsung,arndale", "samsung,exynos5250"; + + mmc@12200000 { + samsung,bus-width = <8>; + samsung,timing = <1 3 3>; + }; + + mmc@12210000 { + status = "disabled"; + }; + + mmc@12220000 { + samsung,bus-width = <4>; + samsung,timing = <1 2 3>; + }; + + mmc@12230000 { + status = "disabled"; + }; +}; diff --git a/boards.cfg b/boards.cfg index 54357eb..572b242 100644 --- a/boards.cfg +++ b/boards.cfg @@ -288,6 +288,7 @@ origen arm armv7 origen samsung exynos s5pc210_universal arm armv7 universal_c210 samsung exynos snow arm armv7 smdk5250 samsung exynos smdk5250 arm armv7 smdk5250 samsung exynos +arndale arm armv7 arndale samsung exynos smdkv310 arm armv7 smdkv310 samsung exynos trats arm armv7 trats samsung exynos harmony arm armv7:arm720t harmony nvidia tegra20 diff --git a/include/configs/arndale.h b/include/configs/arndale.h new file mode 100644 index 0000000..caa83b8 --- /dev/null +++ b/include/configs/arndale.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2013 Samsung Electronics + * + * Configuration settings for the SAMSUNG Arndale board. + * + * 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 __CONFIG_ARNDALE_H +#define __CONFIG_ARNDALE_H + +#undef CONFIG_DEFAULT_DEVICE_TREE +#define CONFIG_DEFAULT_DEVICE_TREE exynos5250-arndale + +#define CONFIG_ARNDALE + +#define CONFIG_ENV_IS_IN_MMC +#define CONFIG_SERIAL2 +#define CONFIG_IDENT_STRING " for Arndale" + +#include <configs/exynos5250-dt.h> + +#endif /* __CONFIG_ARNDALE_H */ diff --git a/tools/Makefile b/tools/Makefile index c5952fc..ab7d339 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -69,6 +69,7 @@ BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) BIN_FILES-y += mkenvimage$(SFX) BIN_FILES-y += mkimage$(SFX) BIN_FILES-$(CONFIG_SMDK5250) += mksmdk5250spl$(SFX) +BIN_FILES-$(CONFIG_ARNDALE) += mkarndalespl$(SFX) BIN_FILES-$(CONFIG_MX23) += mxsboot$(SFX) BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX) BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) @@ -99,6 +100,7 @@ NOPED_OBJ_FILES-y += omapimage.o NOPED_OBJ_FILES-y += mkenvimage.o NOPED_OBJ_FILES-y += mkimage.o OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o +OBJ_FILES-$(CONFIG_ARNDALE) += mkexynosspl.o OBJ_FILES-$(CONFIG_MX23) += mxsboot.o OBJ_FILES-$(CONFIG_MX28) += mxsboot.o OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
Arndale board is based on samsung's exynos5250 soc. Signed-off-by: Inderpal Singh <inderpal.singh@linaro.org> --- MAINTAINERS | 4 + board/samsung/arndale/Makefile | 54 +++ board/samsung/arndale/arndale.c | 117 ++++++ board/samsung/arndale/arndale_spl.c | 66 +++ board/samsung/arndale/clock_init.c | 655 ++++++++++++++++++++++++++++++ board/samsung/arndale/clock_init.h | 149 +++++++ board/samsung/arndale/dmc_common.c | 199 +++++++++ board/samsung/arndale/dmc_init_ddr3.c | 228 +++++++++++ board/samsung/arndale/lowlevel_init.S | 92 +++++ board/samsung/arndale/setup.h | 569 ++++++++++++++++++++++++++ board/samsung/dts/exynos5250-arndale.dts | 36 ++ boards.cfg | 1 + include/configs/arndale.h | 39 ++ tools/Makefile | 2 + 14 files changed, 2211 insertions(+) create mode 100644 board/samsung/arndale/Makefile create mode 100644 board/samsung/arndale/arndale.c create mode 100644 board/samsung/arndale/arndale_spl.c create mode 100644 board/samsung/arndale/clock_init.c create mode 100644 board/samsung/arndale/clock_init.h create mode 100644 board/samsung/arndale/dmc_common.c create mode 100644 board/samsung/arndale/dmc_init_ddr3.c create mode 100644 board/samsung/arndale/lowlevel_init.S create mode 100644 board/samsung/arndale/setup.h create mode 100644 board/samsung/dts/exynos5250-arndale.dts create mode 100644 include/configs/arndale.h