From 060c227a2861b0702e34eabe08eea9cc5bb68b45 Mon Sep 17 00:00:00 2001 From: Rajeshwari Birje Date: Thu, 26 Dec 2013 09:44:21 +0530 Subject: Exynos5420: Add clock initialization for 5420 This patch adds code for clock initialization and clock settings of various IP's and controllers, required for Exynos5420 Signed-off-by: Rajeshwari S Shinde Signed-off-by: Akshay Saraswat Acked-by: Simon Glass Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/clock.c | 279 +++++++++- arch/arm/cpu/armv7/exynos/clock_init.h | 17 + arch/arm/cpu/armv7/exynos/clock_init_exynos5.c | 352 +++++++++++- arch/arm/cpu/armv7/exynos/exynos5_setup.h | 738 +++++++++++++++++++------ 4 files changed, 1184 insertions(+), 202 deletions(-) (limited to 'arch/arm/cpu/armv7') diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 84a50470aa..5bde9d180b 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -96,7 +96,7 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k) freq = CONFIG_SYS_CLK_FREQ; - if (pllreg == EPLL) { + if (pllreg == EPLL || pllreg == RPLL) { k = k & 0xffff; /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */ fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s))); @@ -117,7 +117,7 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k) div = PLL_DIV_1024; else if (proid_is_exynos4412()) div = PLL_DIV_65535; - else if (proid_is_exynos5250()) + else if (proid_is_exynos5250() || proid_is_exynos5420()) div = PLL_DIV_65536; else return 0; @@ -362,6 +362,43 @@ unsigned long clock_get_periph_rate(int peripheral) return 0; } +/* exynos5420: return pll clock frequency */ +static unsigned long exynos5420_get_pll_clk(int pllreg) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long r, k = 0; + + switch (pllreg) { + case APLL: + r = readl(&clk->apll_con0); + break; + case MPLL: + r = readl(&clk->mpll_con0); + break; + case EPLL: + r = readl(&clk->epll_con0); + k = readl(&clk->epll_con1); + break; + case VPLL: + r = readl(&clk->vpll_con0); + k = readl(&clk->vpll_con1); + break; + case BPLL: + r = readl(&clk->bpll_con0); + break; + case RPLL: + r = readl(&clk->rpll_con0); + k = readl(&clk->rpll_con1); + break; + default: + printf("Unsupported PLL (%d)\n", pllreg); + return 0; + } + + return exynos_get_pll_clk(pllreg, r, k); +} + /* exynos4: return ARM clock frequency */ static unsigned long exynos4_get_arm_clk(void) { @@ -485,6 +522,27 @@ static unsigned long exynos4x12_get_pwm_clk(void) return pclk; } +/* exynos5420: return pwm clock frequency */ +static unsigned long exynos5420_get_pwm_clk(void) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long pclk, sclk; + unsigned int ratio; + + /* + * CLK_DIV_PERIC0 + * PWM_RATIO [31:28] + */ + ratio = readl(&clk->div_peric0); + ratio = (ratio >> 28) & 0xf; + sclk = get_pll_clk(MPLL); + + pclk = sclk / (ratio + 1); + + return pclk; +} + /* exynos4: return uart clock frequency */ static unsigned long exynos4_get_uart_clk(int dev_index) { @@ -624,6 +682,53 @@ static unsigned long exynos5_get_uart_clk(int dev_index) return uclk; } +/* exynos5420: return uart clock frequency */ +static unsigned long exynos5420_get_uart_clk(int dev_index) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long uclk, sclk; + unsigned int sel; + unsigned int ratio; + + /* + * CLK_SRC_PERIC0 + * UART0_SEL [6:4] + * UART1_SEL [10:8] + * UART2_SEL [14:12] + * UART3_SEL [18:16] + * generalised calculation as follows + * sel = (sel >> ((dev_index * 4) + 4)) & mask; + */ + sel = readl(&clk->src_peric0); + sel = (sel >> ((dev_index * 4) + 4)) & 0x7; + + if (sel == 0x3) + sclk = get_pll_clk(MPLL); + else if (sel == 0x6) + sclk = get_pll_clk(EPLL); + else if (sel == 0x7) + sclk = get_pll_clk(RPLL); + else + return 0; + + /* + * CLK_DIV_PERIC0 + * UART0_RATIO [11:8] + * UART1_RATIO [15:12] + * UART2_RATIO [19:16] + * UART3_RATIO [23:20] + * generalised calculation as follows + * ratio = (ratio >> ((dev_index * 4) + 8)) & mask; + */ + ratio = readl(&clk->div_peric0); + ratio = (ratio >> ((dev_index * 4) + 8)) & 0xf; + + uclk = sclk / (ratio + 1); + + return uclk; +} + static unsigned long exynos4_get_mmc_clk(int dev_index) { struct exynos4_clock *clk = @@ -718,6 +823,47 @@ static unsigned long exynos5_get_mmc_clk(int dev_index) return uclk; } +static unsigned long exynos5420_get_mmc_clk(int dev_index) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long uclk, sclk; + unsigned int sel, ratio; + + /* + * CLK_SRC_FSYS + * MMC0_SEL [10:8] + * MMC1_SEL [14:12] + * MMC2_SEL [18:16] + * generalised calculation as follows + * sel = (sel >> ((dev_index * 4) + 8)) & mask + */ + sel = readl(&clk->src_fsys); + sel = (sel >> ((dev_index * 4) + 8)) & 0x7; + + if (sel == 0x3) + sclk = get_pll_clk(MPLL); + else if (sel == 0x6) + sclk = get_pll_clk(EPLL); + else + return 0; + + /* + * CLK_DIV_FSYS1 + * MMC0_RATIO [9:0] + * MMC1_RATIO [19:10] + * MMC2_RATIO [29:20] + * generalised calculation as follows + * ratio = (ratio >> (dev_index * 10)) & mask + */ + ratio = readl(&clk->div_fsys1); + ratio = (ratio >> (dev_index * 10)) & 0x3ff; + + uclk = (sclk / (ratio + 1)); + + return uclk; +} + /* exynos4: set the mmc clock */ static void exynos4_set_mmc_clk(int dev_index, unsigned int div) { @@ -804,6 +950,29 @@ static void exynos5_set_mmc_clk(int dev_index, unsigned int div) writel(val, addr); } +/* exynos5: set the mmc clock */ +static void exynos5420_set_mmc_clk(int dev_index, unsigned int div) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned int addr; + unsigned int val, shift; + + /* + * CLK_DIV_FSYS1 + * MMC0_RATIO [9:0] + * MMC1_RATIO [19:10] + * MMC2_RATIO [29:20] + */ + addr = (unsigned int)&clk->div_fsys1; + shift = dev_index * 10; + + val = readl(addr); + val &= ~(0x3ff << shift); + val |= (div & 0x3ff) << shift; + writel(val, addr); +} + /* get_lcd_clk: return lcd clock frequency */ static unsigned long exynos4_get_lcd_clk(void) { @@ -1324,6 +1493,71 @@ static int exynos5_set_spi_clk(enum periph_id periph_id, return 0; } +static int exynos5420_set_spi_clk(enum periph_id periph_id, + unsigned int rate) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + int main; + unsigned int fine; + unsigned shift, pre_shift; + unsigned div_mask = 0xf, pre_div_mask = 0xff; + u32 *reg; + u32 *pre_reg; + + main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine); + if (main < 0) { + debug("%s: Cannot set clock rate for periph %d", + __func__, periph_id); + return -1; + } + main = main - 1; + fine = fine - 1; + + switch (periph_id) { + case PERIPH_ID_SPI0: + reg = &clk->div_peric1; + shift = 20; + pre_reg = &clk->div_peric4; + pre_shift = 8; + break; + case PERIPH_ID_SPI1: + reg = &clk->div_peric1; + shift = 24; + pre_reg = &clk->div_peric4; + pre_shift = 16; + break; + case PERIPH_ID_SPI2: + reg = &clk->div_peric1; + shift = 28; + pre_reg = &clk->div_peric4; + pre_shift = 24; + break; + case PERIPH_ID_SPI3: + reg = &clk->div_isp1; + shift = 16; + pre_reg = &clk->div_isp1; + pre_shift = 0; + break; + case PERIPH_ID_SPI4: + reg = &clk->div_isp1; + shift = 20; + pre_reg = &clk->div_isp1; + pre_shift = 8; + break; + default: + debug("%s: Unsupported peripheral ID %d\n", __func__, + periph_id); + return -1; + } + + clrsetbits_le32(reg, div_mask << shift, (main & div_mask) << shift); + clrsetbits_le32(pre_reg, pre_div_mask << pre_shift, + (fine & pre_div_mask) << pre_shift); + + return 0; +} + static unsigned long exynos4_get_i2c_clk(void) { struct exynos4_clock *clk = @@ -1341,9 +1575,11 @@ static unsigned long exynos4_get_i2c_clk(void) unsigned long get_pll_clk(int pllreg) { - if (cpu_is_exynos5()) + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_get_pll_clk(pllreg); return exynos5_get_pll_clk(pllreg); - else { + } else { if (proid_is_exynos4412()) return exynos4x12_get_pll_clk(pllreg); return exynos4_get_pll_clk(pllreg); @@ -1375,9 +1611,11 @@ unsigned long get_i2c_clk(void) unsigned long get_pwm_clk(void) { - if (cpu_is_exynos5()) + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_get_pwm_clk(); return clock_get_periph_rate(PERIPH_ID_PWM0); - else { + } else { if (proid_is_exynos4412()) return exynos4x12_get_pwm_clk(); return exynos4_get_pwm_clk(); @@ -1386,9 +1624,11 @@ unsigned long get_pwm_clk(void) unsigned long get_uart_clk(int dev_index) { - if (cpu_is_exynos5()) + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_get_uart_clk(dev_index); return exynos5_get_uart_clk(dev_index); - else { + } else { if (proid_is_exynos4412()) return exynos4x12_get_uart_clk(dev_index); return exynos4_get_uart_clk(dev_index); @@ -1397,17 +1637,23 @@ unsigned long get_uart_clk(int dev_index) unsigned long get_mmc_clk(int dev_index) { - if (cpu_is_exynos5()) + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_get_mmc_clk(dev_index); return exynos5_get_mmc_clk(dev_index); - else + } else { return exynos4_get_mmc_clk(dev_index); + } } void set_mmc_clk(int dev_index, unsigned int div) { - if (cpu_is_exynos5()) - exynos5_set_mmc_clk(dev_index, div); - else { + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + exynos5420_set_mmc_clk(dev_index, div); + else + exynos5_set_mmc_clk(dev_index, div); + } else { if (proid_is_exynos4412()) exynos4x12_set_mmc_clk(dev_index, div); else @@ -1439,10 +1685,13 @@ void set_mipi_clk(void) int set_spi_clk(int periph_id, unsigned int rate) { - if (cpu_is_exynos5()) + if (cpu_is_exynos5()) { + if (proid_is_exynos5420()) + return exynos5420_set_spi_clk(periph_id, rate); return exynos5_set_spi_clk(periph_id, rate); - else + } else { return 0; + } } int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq, diff --git a/arch/arm/cpu/armv7/exynos/clock_init.h b/arch/arm/cpu/armv7/exynos/clock_init.h index c28ff3ab14..a875d0b48f 100644 --- a/arch/arm/cpu/armv7/exynos/clock_init.h +++ b/arch/arm/cpu/armv7/exynos/clock_init.h @@ -10,7 +10,11 @@ #define __EXYNOS_CLOCK_INIT_H enum { +#ifdef CONFIG_EXYNOS5420 + MEM_TIMINGS_MSR_COUNT = 5, +#else MEM_TIMINGS_MSR_COUNT = 4, +#endif }; /* These are the ratio's for configuring ARM clock */ @@ -59,6 +63,18 @@ struct mem_timings { unsigned bpll_mdiv; unsigned bpll_pdiv; unsigned bpll_sdiv; + unsigned kpll_mdiv; + unsigned kpll_pdiv; + unsigned kpll_sdiv; + unsigned dpll_mdiv; + unsigned dpll_pdiv; + unsigned dpll_sdiv; + unsigned ipll_mdiv; + unsigned ipll_pdiv; + unsigned ipll_sdiv; + unsigned spll_mdiv; + unsigned spll_pdiv; + unsigned spll_sdiv; unsigned pclk_cdrex_ratio; unsigned direct_cmd_msr[MEM_TIMINGS_MSR_COUNT]; @@ -115,6 +131,7 @@ struct mem_timings { 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 */ + uint8_t read_leveling_enable; /* check h/w read leveling is enabled */ }; /** diff --git a/arch/arm/cpu/armv7/exynos/clock_init_exynos5.c b/arch/arm/cpu/armv7/exynos/clock_init_exynos5.c index a24c2f3875..1d6977fa43 100644 --- a/arch/arm/cpu/armv7/exynos/clock_init_exynos5.c +++ b/arch/arm/cpu/armv7/exynos/clock_init_exynos5.c @@ -24,6 +24,24 @@ DECLARE_GLOBAL_DATA_PTR; struct arm_clk_ratios arm_clk_ratios[] = { +#ifdef CONFIG_EXYNOS5420 + { + .arm_freq_mhz = 900, + + .apll_mdiv = 0x96, + .apll_pdiv = 0x2, + .apll_sdiv = 0x1, + + .arm2_ratio = 0x0, + .apll_ratio = 0x3, + .pclk_dbg_ratio = 0x6, + .atb_ratio = 0x6, + .periph_ratio = 0x7, + .acp_ratio = 0x0, + .cpud_ratio = 0x2, + .arm_ratio = 0x0, + } +#else { .arm_freq_mhz = 600, @@ -115,8 +133,133 @@ struct arm_clk_ratios arm_clk_ratios[] = { .cpud_ratio = 0x3, .arm_ratio = 0x0, } +#endif }; + struct mem_timings mem_timings[] = { +#ifdef CONFIG_EXYNOS5420 + { + .mem_manuf = MEM_MANUF_SAMSUNG, + .mem_type = DDR_MODE_DDR3, + .frequency_mhz = 800, + + /* MPLL @800MHz*/ + .mpll_mdiv = 0xc8, + .mpll_pdiv = 0x3, + .mpll_sdiv = 0x1, + /* CPLL @666MHz */ + .cpll_mdiv = 0xde, + .cpll_pdiv = 0x4, + .cpll_sdiv = 0x1, + /* EPLL @600MHz */ + .epll_mdiv = 0x64, + .epll_pdiv = 0x2, + .epll_sdiv = 0x1, + /* VPLL @430MHz */ + .vpll_mdiv = 0xd7, + .vpll_pdiv = 0x3, + .vpll_sdiv = 0x2, + /* BPLL @800MHz */ + .bpll_mdiv = 0xc8, + .bpll_pdiv = 0x3, + .bpll_sdiv = 0x1, + /* KPLL @600MHz */ + .kpll_mdiv = 0x190, + .kpll_pdiv = 0x4, + .kpll_sdiv = 0x2, + /* DPLL @600MHz */ + .dpll_mdiv = 0x190, + .dpll_pdiv = 0x4, + .dpll_sdiv = 0x2, + /* IPLL @370MHz */ + .ipll_mdiv = 0xb9, + .ipll_pdiv = 0x3, + .ipll_sdiv = 0x2, + /* SPLL @400MHz */ + .spll_mdiv = 0xc8, + .spll_pdiv = 0x3, + .spll_sdiv = 0x2, + + .direct_cmd_msr = { + 0x00020018, 0x00030000, 0x00010046, 0x00000d70, + 0x00000c70 + }, + .timing_ref = 0x000000bb, + .timing_row = 0x6836650f, + .timing_data = 0x3630580b, + .timing_power = 0x41000a26, + .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 = 0x7, + .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_DISABLE | + 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_MEMCONFIG_CHIP_MAP_SPLIT | + DMC_MEMCONFIGX_CHIP_COL_10 | + DMC_MEMCONFIGX_CHIP_ROW_15 | + DMC_MEMCONFIGX_CHIP_BANK_8, + .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 = 1, + .chips_per_channel = 1, + .chips_to_configure = 1, + .send_zq_init = 1, + .gate_leveling_enable = 1, + .read_leveling_enable = 0, + } +#else { .mem_manuf = MEM_MANUF_ELPIDA, .mem_type = DDR_MODE_DDR3, @@ -324,6 +467,7 @@ struct mem_timings mem_timings[] = { .impedance = IMP_OUTPUT_DRV_40_OHM, .gate_leveling_enable = 1, } +#endif }; /** @@ -399,7 +543,7 @@ struct mem_timings *clock_get_mem_timings(void) return NULL; } -void system_clock_init() +static void exynos5250_system_clock_init(void) { struct exynos5_clock *clk = (struct exynos5_clock *)samsung_get_base_clock(); @@ -436,19 +580,13 @@ void system_clock_init() } 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(mem->apll_pdiv * PLL_LOCK_FACTOR, &clk->apll_lock); + writel(mem->mpll_pdiv * PLL_LOCK_FACTOR, &clk->mpll_lock); + writel(mem->bpll_pdiv * PLL_LOCK_FACTOR, &clk->bpll_lock); + writel(mem->cpll_pdiv * PLL_LOCK_FACTOR, &clk->cpll_lock); + writel(mem->gpll_pdiv * PLL_X_LOCK_FACTOR, &clk->gpll_lock); + writel(mem->epll_pdiv * PLL_X_LOCK_FACTOR, &clk->epll_lock); + writel(mem->vpll_pdiv * PLL_X_LOCK_FACTOR, &clk->vpll_lock); writel(CLK_REG_DISABLE, &clk->pll_div2_sel); @@ -640,6 +778,192 @@ void system_clock_init() writel(val, &clk->div_fsys2); } +static void exynos5420_system_clock_init(void) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + struct mem_timings *mem; + struct arm_clk_ratios *arm_clk_ratio; + u32 val; + + mem = clock_get_mem_timings(); + arm_clk_ratio = get_arm_ratios(); + + /* PLL locktime */ + writel(arm_clk_ratio->apll_pdiv * PLL_LOCK_FACTOR, &clk->apll_lock); + writel(mem->mpll_pdiv * PLL_LOCK_FACTOR, &clk->mpll_lock); + writel(mem->bpll_pdiv * PLL_LOCK_FACTOR, &clk->bpll_lock); + writel(mem->cpll_pdiv * PLL_LOCK_FACTOR, &clk->cpll_lock); + writel(mem->dpll_pdiv * PLL_LOCK_FACTOR, &clk->dpll_lock); + writel(mem->epll_pdiv * PLL_X_LOCK_FACTOR, &clk->epll_lock); + writel(mem->vpll_pdiv * PLL_LOCK_FACTOR, &clk->vpll_lock); + writel(mem->ipll_pdiv * PLL_LOCK_FACTOR, &clk->ipll_lock); + writel(mem->spll_pdiv * PLL_LOCK_FACTOR, &clk->spll_lock); + writel(mem->kpll_pdiv * PLL_LOCK_FACTOR, &clk->kpll_lock); + + setbits_le32(&clk->src_cpu, MUX_HPM_SEL_MASK); + + writel(0, &clk->src_top6); + + writel(0, &clk->src_cdrex); + writel(SRC_KFC_HPM_SEL, &clk->src_kfc); + writel(HPM_RATIO, &clk->div_cpu1); + writel(CLK_DIV_CPU0_VAL, &clk->div_cpu0); + + /* switch A15 clock source to OSC clock before changing APLL */ + clrbits_le32(&clk->src_cpu, APLL_FOUT); + + /* 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) & PLL_LOCKED) == 0) + ; + + /* now it is safe to switch to APLL */ + setbits_le32(&clk->src_cpu, APLL_FOUT); + + writel(SRC_KFC_HPM_SEL, &clk->src_kfc); + writel(CLK_DIV_KFC_VAL, &clk->div_kfc0); + + /* switch A7 clock source to OSC clock before changing KPLL */ + clrbits_le32(&clk->src_kfc, KPLL_FOUT); + + /* Set KPLL*/ + writel(KPLL_CON1_VAL, &clk->kpll_con1); + val = set_pll(mem->kpll_mdiv, mem->kpll_pdiv, mem->kpll_sdiv); + writel(val, &clk->kpll_con0); + while ((readl(&clk->kpll_con0) & PLL_LOCKED) == 0) + ; + + /* now it is safe to switch to KPLL */ + setbits_le32(&clk->src_kfc, KPLL_FOUT); + + /* 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) & PLL_LOCKED) == 0) + ; + + /* Set DPLL */ + writel(DPLL_CON1_VAL, &clk->dpll_con1); + val = set_pll(mem->dpll_mdiv, mem->dpll_pdiv, mem->dpll_sdiv); + writel(val, &clk->dpll_con0); + while ((readl(&clk->dpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set EPLL */ + writel(EPLL_CON2_VAL, &clk->epll_con2); + writel(EPLL_CON1_VAL, &clk->epll_con1); + val = set_pll(mem->epll_mdiv, mem->epll_pdiv, mem->epll_sdiv); + writel(val, &clk->epll_con0); + while ((readl(&clk->epll_con0) & PLL_LOCKED) == 0) + ; + + /* Set CPLL */ + writel(CPLL_CON1_VAL, &clk->cpll_con1); + val = set_pll(mem->cpll_mdiv, mem->cpll_pdiv, mem->cpll_sdiv); + writel(val, &clk->cpll_con0); + while ((readl(&clk->cpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set IPLL */ + writel(IPLL_CON1_VAL, &clk->ipll_con1); + val = set_pll(mem->ipll_mdiv, mem->ipll_pdiv, mem->ipll_sdiv); + writel(val, &clk->ipll_con0); + while ((readl(&clk->ipll_con0) & PLL_LOCKED) == 0) + ; + + /* Set VPLL */ + 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) & PLL_LOCKED) == 0) + ; + + /* Set BPLL */ + writel(BPLL_CON1_VAL, &clk->bpll_con1); + val = set_pll(mem->bpll_mdiv, mem->bpll_pdiv, mem->bpll_sdiv); + writel(val, &clk->bpll_con0); + while ((readl(&clk->bpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set SPLL */ + writel(SPLL_CON1_VAL, &clk->spll_con1); + val = set_pll(mem->spll_mdiv, mem->spll_pdiv, mem->spll_sdiv); + writel(val, &clk->spll_con0); + while ((readl(&clk->spll_con0) & PLL_LOCKED) == 0) + ; + + writel(CLK_DIV_CDREX0_VAL, &clk->div_cdrex0); + writel(CLK_DIV_CDREX1_VAL, &clk->div_cdrex1); + + writel(CLK_SRC_TOP0_VAL, &clk->src_top0); + writel(CLK_SRC_TOP1_VAL, &clk->src_top1); + writel(CLK_SRC_TOP2_VAL, &clk->src_top2); + writel(CLK_SRC_TOP7_VAL, &clk->src_top7); + + writel(CLK_DIV_TOP0_VAL, &clk->div_top0); + writel(CLK_DIV_TOP1_VAL, &clk->div_top1); + writel(CLK_DIV_TOP2_VAL, &clk->div_top2); + + writel(0, &clk->src_top10); + writel(0, &clk->src_top11); + writel(0, &clk->src_top12); + + writel(CLK_SRC_TOP3_VAL, &clk->src_top3); + writel(CLK_SRC_TOP4_VAL, &clk->src_top4); + writel(CLK_SRC_TOP5_VAL, &clk->src_top5); + + /* DISP1 BLK CLK SELECTION */ + writel(CLK_SRC_DISP1_0_VAL, &clk->src_disp10); + writel(CLK_DIV_DISP1_0_VAL, &clk->div_disp10); + + /* AUDIO BLK */ + writel(AUDIO0_SEL_EPLL, &clk->src_mau); + writel(DIV_MAU_VAL, &clk->div_mau); + + /* FSYS */ + writel(CLK_SRC_FSYS0_VAL, &clk->src_fsys); + writel(CLK_DIV_FSYS0_VAL, &clk->div_fsys0); + writel(CLK_DIV_FSYS1_VAL, &clk->div_fsys1); + writel(CLK_DIV_FSYS2_VAL, &clk->div_fsys2); + + writel(CLK_SRC_ISP_VAL, &clk->src_isp); + writel(CLK_DIV_ISP0_VAL, &clk->div_isp0); + writel(CLK_DIV_ISP1_VAL, &clk->div_isp1); + + writel(CLK_SRC_PERIC0_VAL, &clk->src_peric0); + writel(CLK_SRC_PERIC1_VAL, &clk->src_peric1); + + writel(CLK_DIV_PERIC0_VAL, &clk->div_peric0); + 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(CLK_DIV_PERIC4_VAL, &clk->div_peric4); + + writel(CLK_DIV_CPERI1_VAL, &clk->div_cperi1); + + writel(CLK_DIV2_RATIO, &clk->clkdiv2_ratio); + writel(CLK_DIV4_RATIO, &clk->clkdiv4_ratio); + writel(CLK_DIV_G2D, &clk->div_g2d); + + writel(CLK_SRC_TOP6_VAL, &clk->src_top6); + writel(CLK_SRC_CDREX_VAL, &clk->src_cdrex); + writel(CLK_SRC_KFC_VAL, &clk->src_kfc); +} + +void system_clock_init(void) +{ + if (proid_is_exynos5420()) + exynos5420_system_clock_init(); + else + exynos5250_system_clock_init(); +} + void clock_init_dp_clock(void) { struct exynos5_clock *clk = diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index 696b386759..c8d6515044 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -12,42 +12,16 @@ #include #include -/* 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 +#define NOT_AVAILABLE 0 +#define DATA_MASK 0xFFFFF -/* BPLL_CON1 */ -#define BPLL_CON1_VAL 0x00203800 +#define ENABLE_BIT 0x1 +#define DISABLE_BIT 0x0 +#define CA_SWAP_EN (1 << 0) /* 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) @@ -78,6 +52,7 @@ /* MEMCONFIG0 register bit fields */ #define DMC_MEMCONFIGX_CHIP_MAP_INTERLEAVED (1 << 12) +#define DMC_MEMCONFIG_CHIP_MAP_SPLIT (2 << 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) @@ -90,6 +65,17 @@ DMC_MEMBASECONFIGX_CHIP_MASK(0x780) \ ) +/* + * As we use channel interleaving, therefore value of the base address + * register must be set as half of the bus base address + * RAM start addess is 0x2000_0000 which means chip_base is 0x20, so + * we need to set half 0x10 to the membaseconfigx registers + * see exynos5420 UM section 17.17.3.21 for more. + */ +#define DMC_CHIP_BASE_0 0x10 +#define DMC_CHIP_BASE_1 0x50 +#define DMC_CHIP_MASK 0x7C0 + #define DMC_MEMBASECONFIG0_VAL DMC_MEMBASECONFIG_VAL(0x40) #define DMC_MEMBASECONFIG1_VAL DMC_MEMBASECONFIG_VAL(0x80) @@ -113,29 +99,24 @@ /* COJCONTROL register bit fields */ #define DMC_CONCONTROL_IO_PD_CON_DISABLE (0 << 3) +#define DMC_CONCONTROL_IO_PD_CON_ENABLE (1 << 3) #define DMC_CONCONTROL_AREF_EN_DISABLE (0 << 5) +#define DMC_CONCONTROL_AREF_EN_ENABLE (1 << 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)) +#define DMC_CONCONTROL_VAL 0x1FFF2101 +#define DREX_CONCONTROL_VAL DMC_CONCONTROL_VAL \ + | DMC_CONCONTROL_AREF_EN_ENABLE \ + | DMC_CONCONTROL_IO_PD_CON_ENABLE -/* CLK_FSYS */ -#define CLK_SRC_FSYS0_VAL 0x66666 -#define CLK_DIV_FSYS0_VAL 0x0BB00000 +#define DMC_CONCONTROL_IO_PD_CON(x) (x << 6) -/* CLK_DIV_CPU1 */ +/* CLK_DIV_CPU1 */ #define HPM_RATIO 0x2 #define COPY_RATIO 0x0 @@ -164,10 +145,367 @@ /* CLK_DIV_SYSLFT */ #define CLK_DIV_SYSLFT_VAL 0x00000311 +#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 PLL_LOCKED (1 << 29) +#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 + +/* 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_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_ISP2 */ +#define CLK_DIV_ISP2_VAL 0x1 + +/* CLK_SRC_KFC */ +#define SRC_KFC_HPM_SEL (1 << 15) + +/* CLK_SRC_KFC */ +#define CLK_SRC_KFC_VAL 0x00008001 + +/* CLK_DIV_KFC */ +#define CLK_DIV_KFC_VAL 0x03300110 + +/* CLK_DIV2_RATIO */ +#define CLK_DIV2_RATIO 0x10111150 + +/* CLK_DIV4_RATIO */ +#define CLK_DIV4_RATIO 0x00000003 + +/* CLK_DIV_G2D */ +#define CLK_DIV_G2D 0x00000010 + +/* + * 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) + +/* AUDIO CLK SEL */ +#define AUDIO0_SEL_EPLL (0x6 << 28) +#define AUDIO0_RATIO 0x5 +#define PCM0_RATIO 0x3 +#define DIV_MAU_VAL (PCM0_RATIO << 24 | AUDIO0_RATIO << 20) + +/* CLK_SRC_CDREX */ +#define MUX_MCLK_CDR_MSPLL (1 << 4) +#define MUX_BPLL_SEL_FOUTBPLL (1 << 0) +#define BPLL_SEL_MASK 0x7 +#define FOUTBPLL 2 + +#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 RDLVL_PASS_ADJ_VAL 0x6 +#define RDLVL_PASS_ADJ_OFFSET 16 +#define CTRL_GATEDURADJ_MASK (0xf << 20) +#define READ_LEVELLING_DDR3 0x0100 + +#define PHY_CON2_RESET_VAL 0x00010004 +#define INIT_DESKEW_EN (1 << 6) +#define DLL_DESKEW_EN (1 << 12) +#define RDLVL_GATE_EN (1 << 24) +#define RDLVL_EN (1 << 25) +#define RDLVL_INCR_ADJ (0x1 << 16) + +/* DREX_PAUSE */ +#define DREX_PAUSE_EN (1 << 0) + +#define BYPASS_EN (1 << 22) + +/* MEMMORY VAL */ +#define PHY_CON0_VAL 0x17021A00 + +#define PHY_CON12_RESET_VAL 0x10100070 +#define PHY_CON12_VAL 0x10107F50 +#define CTRL_START (1 << 6) +#define CTRL_DLL_ON (1 << 5) +#define CTRL_FORCE_MASK (0x7F << 8) +#define CTRL_LOCK_COARSE_MASK (0x7F << 10) + +#define CTRL_OFFSETD_RESET_VAL 0x8 +#define CTRL_OFFSETD_VAL 0x7F + +#define CTRL_OFFSETR0 0x7F +#define CTRL_OFFSETR1 0x7F +#define CTRL_OFFSETR2 0x7F +#define CTRL_OFFSETR3 0x7F +#define PHY_CON4_VAL (CTRL_OFFSETR0 << 0 | \ + CTRL_OFFSETR1 << 8 | \ + CTRL_OFFSETR2 << 16 | \ + CTRL_OFFSETR3 << 24) +#define PHY_CON4_RESET_VAL 0x08080808 + +#define CTRL_OFFSETW0 0x7F +#define CTRL_OFFSETW1 0x7F +#define CTRL_OFFSETW2 0x7F +#define CTRL_OFFSETW3 0x7F +#define PHY_CON6_VAL (CTRL_OFFSETW0 << 0 | \ + CTRL_OFFSETW1 << 8 | \ + CTRL_OFFSETW2 << 16 | \ + CTRL_OFFSETW3 << 24) +#define PHY_CON6_RESET_VAL 0x08080808 + +#define PHY_CON14_RESET_VAL 0x001F0000 +#define CTRL_PULLD_DQS 0xF +#define CTRL_PULLD_DQS_OFFSET 0 + +/* ZQ Configurations */ +#define PHY_CON16_RESET_VAL 0x08000304 + +#define ZQ_CLK_EN (1 << 27) +#define ZQ_CLK_DIV_EN (1 << 18) +#define ZQ_MANUAL_STR (1 << 1) +#define ZQ_DONE (1 << 0) +#define ZQ_MODE_DDS_OFFSET 24 + +#define CTRL_RDLVL_GATE_ENABLE 1 +#define CTRL_RDLVL_GATE_DISABLE 0 +#define CTRL_RDLVL_DATA_ENABLE 2 + +/* 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 +#define DIRECT_CMD_BANK_SHIFT 16 +#define DIRECT_CMD_REFA (5 << 24) +#define DIRECT_CMD_MRS1 0x71C00 +#define DIRECT_CMD_MRS2 0x10BFC +#define DIRECT_CMD_MRS3 0x0050C +#define DIRECT_CMD_MRS4 0x00868 +#define DIRECT_CMD_MRS5 0x00C04 + +/* Drive Strength */ +#define IMPEDANCE_48_OHM 4 +#define IMPEDANCE_40_OHM 5 +#define IMPEDANCE_34_OHM 6 +#define IMPEDANCE_30_OHM 7 +#define PHY_CON39_VAL_48_OHM 0x09240924 +#define PHY_CON39_VAL_40_OHM 0x0B6D0B6D +#define PHY_CON39_VAL_34_OHM 0x0DB60DB6 +#define PHY_CON39_VAL_30_OHM 0x0FFF0FFF + +#define CTRL_BSTLEN_OFFSET 8 +#define CTRL_RDLAT_OFFSET 0 + +#define CMD_DEFAULT_LPDDR3 0xF +#define CMD_DEFUALT_OFFSET 0 +#define T_WRDATA_EN 0x7 +#define T_WRDATA_EN_DDR3 0x8 +#define T_WRDATA_EN_OFFSET 16 +#define T_WRDATA_EN_MASK 0x1f + +#define PHY_CON31_VAL 0x0C183060 +#define PHY_CON32_VAL 0x60C18306 +#define PHY_CON33_VAL 0x00000030 + +#define PHY_CON31_RESET_VAL 0x0 +#define PHY_CON32_RESET_VAL 0x0 +#define PHY_CON33_RESET_VAL 0x0 + +#define SL_DLL_DYN_CON_EN (1 << 1) +#define FP_RESYNC (1 << 3) +#define CTRL_START (1 << 6) + +#define DMC_AREF_EN (1 << 5) +#define DMC_CONCONTROL_EMPTY (1 << 8) +#define DFI_INIT_START (1 << 28) + +#define DMC_MEMCONTROL_VAL 0x00312700 +#define CLK_STOP_EN (1 << 0) +#define DPWRDN_EN (1 << 1) +#define DSREF_EN (1 << 5) + +#define MEMBASECONFIG_CHIP_MASK_VAL 0x7E0 +#define MEMBASECONFIG_CHIP_MASK_OFFSET 0 +#define MEMBASECONFIG0_CHIP_BASE_VAL 0x20 +#define MEMBASECONFIG1_CHIP_BASE_VAL 0x40 +#define CHIP_BASE_OFFSET 16 + +#define MEMCONFIG_VAL 0x1323 +#define PRECHCONFIG_DEFAULT_VAL 0xFF000000 +#define PWRDNCONFIG_DEFAULT_VAL 0xFFFF00FF + +#define TIMINGAREF_VAL 0x5d +#define TIMINGROW_VAL 0x345A8692 +#define TIMINGDATA_VAL 0x3630065C +#define TIMINGPOWER_VAL 0x50380336 +#define DFI_INIT_COMPLETE (1 << 3) + +#define BRBRSVCONTROL_VAL 0x00000033 +#define BRBRSVCONFIG_VAL 0x88778877 + +/* Clock Gating Control (CGCONTROL) register */ +#define MEMIF_CG_EN (1 << 3) /* Memory interface clock gating */ +#define SCG_CG_EN (1 << 2) /* Scheduler clock gating */ +#define BUSIF_WR_CG_EN (1 << 1) /* Bus interface write channel clock gating */ +#define BUSIF_RD_CG_EN (1 << 0) /* Bus interface read channel clock gating */ +#define DMC_INTERNAL_CG (MEMIF_CG_EN | SCG_CG_EN | \ + BUSIF_WR_CG_EN | BUSIF_RD_CG_EN) + +/* 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 DA_3_DS_OFFSET 25 +#define DA_2_DS_OFFSET 22 +#define DA_1_DS_OFFSET 19 +#define DA_0_DS_OFFSET 16 +#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 + +/* + * Definitions that differ with SoC's. + * Below is the part defining macros for smdk5250. + * Else part introduces macros for smdk5420. + */ +#ifndef CONFIG_SMDK5420 + +/* APLL_CON1 */ +#define APLL_CON1_VAL (0x00203800) + +/* MPLL_CON1 */ +#define MPLL_CON1_VAL (0x00203800) + +/* CPLL_CON1 */ +#define CPLL_CON1_VAL (0x00203800) + +/* DPLL_CON1 */ +#define DPLL_CON1_VAL (NOT_AVAILABLE) + +/* 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 + +/* RPLL_CON1, CON2 */ +#define RPLL_CON1_VAL NOT_AVAILABLE +#define RPLL_CON2_VAL NOT_AVAILABLE + +/* BPLL_CON1 */ +#define BPLL_CON1_VAL 0x00203800 + +/* SPLL_CON1 */ +#define SPLL_CON1_VAL NOT_AVAILABLE + +/* IPLL_CON1 */ +#define IPLL_CON1_VAL NOT_AVAILABLE + +/* KPLL_CON1 */ +#define KPLL_CON1_VAL NOT_AVAILABLE + +/* CLK_SRC_ISP */ +#define CLK_SRC_ISP_VAL NOT_AVAILABLE +#define CLK_DIV_ISP0_VAL 0x31 +#define CLK_DIV_ISP1_VAL 0x0 + +/* CLK_FSYS */ +#define CLK_SRC_FSYS0_VAL 0x66666 +#define CLK_DIV_FSYS0_VAL 0x0BB00000 +#define CLK_DIV_FSYS1_VAL NOT_AVAILABLE +#define CLK_DIV_FSYS2_VAL NOT_AVAILABLE + +/* 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)) + /* CLK_SRC_CDREX */ #define CLK_SRC_CDREX_VAL 0x1 /* CLK_DIV_CDREX */ +#define CLK_DIV_CDREX0_VAL NOT_AVAILABLE +#define CLK_DIV_CDREX1_VAL NOT_AVAILABLE + +/* CLK_DIV_CPU0_VAL */ +#define CLK_DIV_CPU0_VAL NOT_AVAILABLE + #define MCLK_CDREX2_RATIO 0x0 #define ACLK_EFCON_RATIO 0x1 #define MCLK_DPHY_RATIO 0x1 @@ -247,6 +585,11 @@ | (MUX_ACLK_300_DISP1_SUB_SEL << 6) \ | (MUX_ACLK_200_DISP1_SUB_SEL << 4)) +#define CLK_SRC_TOP4_VAL NOT_AVAILABLE +#define CLK_SRC_TOP5_VAL NOT_AVAILABLE +#define CLK_SRC_TOP6_VAL NOT_AVAILABLE +#define CLK_SRC_TOP7_VAL NOT_AVAILABLE + /* CLK_DIV_TOP0 */ #define ACLK_300_DISP1_RATIO 0x2 #define ACLK_400_G3D_RATIO 0x0 @@ -279,40 +622,11 @@ | (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 CLK_DIV_TOP2_VAL NOT_AVAILABLE -#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 +/* PLL Lock Value Factor */ +#define PLL_LOCK_FACTOR 250 +#define PLL_X_LOCK_FACTOR 3000 /* CLK_SRC_PERIC0 */ #define PWM_SEL 6 @@ -336,18 +650,6 @@ | (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 @@ -380,105 +682,200 @@ #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 +/* CLK_DIV_PERIC4 */ +#define CLK_DIV_PERIC4_VAL NOT_AVAILABLE -#define MMC3_RATIO_MASK 0xf -#define MMC3_RATIO_VAL 0x1 -#define MMC3_RATIO_OFFSET 16 +/* CLK_SRC_DISP1_0 */ +#define CLK_SRC_DISP1_0_VAL 0x6 +#define CLK_DIV_DISP1_0_VAL NOT_AVAILABLE -#define MMC3_PRE_RATIO_MASK 0xff -#define MMC3_PRE_RATIO_VAL 0x0 -#define MMC3_PRE_RATIO_OFFSET 24 +#define APLL_FOUT (1 << 0) +#define KPLL_FOUT NOT_AVAILABLE -/* CLK_SRC_LEX */ -#define CLK_SRC_LEX_VAL 0x0 +#define CLK_DIV_CPERI1_VAL NOT_AVAILABLE -/* CLK_DIV_LEX */ -#define CLK_DIV_LEX_VAL 0x10 +#else -/* CLK_DIV_R0X */ -#define CLK_DIV_R0X_VAL 0x10 +/* APLL_CON1 */ +#define APLL_CON1_VAL (0x0020F300) -/* CLK_DIV_L0X */ -#define CLK_DIV_R1X_VAL 0x10 +/* MPLL_CON1 */ +#define MPLL_CON1_VAL (0x0020F300) -/* CLK_DIV_ISP0 */ -#define CLK_DIV_ISP0_VAL 0x31 -/* CLK_DIV_ISP1 */ -#define CLK_DIV_ISP1_VAL 0x0 +/* CPLL_CON1 */ +#define CPLL_CON1_VAL 0x0020f300 -/* CLK_DIV_ISP2 */ -#define CLK_DIV_ISP2_VAL 0x1 +/* DPLL_CON1 */ +#define DPLL_CON1_VAL (0x0020F300) -/* CLK_SRC_DISP1_0 */ -#define CLK_SRC_DISP1_0_VAL 0x6 +/* GPLL_CON1 */ +#define GPLL_CON1_VAL (NOT_AVAILABLE) -/* - * 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) +/* EPLL_CON1, CON2 */ +#define EPLL_CON1_VAL 0x00000000 +#define EPLL_CON2_VAL 0x00000080 -#define DDR3PHY_CTRL_PHY_RESET (1 << 0) -#define DDR3PHY_CTRL_PHY_RESET_OFF (0 << 0) +/* VPLL_CON1, CON2 */ +#define VPLL_CON1_VAL 0x0020f300 +#define VPLL_CON2_VAL NOT_AVAILABLE -#define PHY_CON0_RESET_VAL 0x17020a40 -#define P0_CMD_EN (1 << 14) -#define BYTE_RDLVL_EN (1 << 13) -#define CTRL_SHGATE (1 << 8) +/* RPLL_CON1, CON2 */ +#define RPLL_CON1_VAL 0x00000000 +#define RPLL_CON2_VAL 0x00000080 -#define PHY_CON1_RESET_VAL 0x09210100 -#define CTRL_GATEDURADJ_MASK (0xf << 20) +/* BPLL_CON1 */ +#define BPLL_CON1_VAL 0x0020f300 -#define PHY_CON2_RESET_VAL 0x00010004 -#define INIT_DESKEW_EN (1 << 6) -#define RDLVL_GATE_EN (1 << 24) +/* SPLL_CON1 */ +#define SPLL_CON1_VAL 0x0020f300 -/*ZQ Configurations */ -#define PHY_CON16_RESET_VAL 0x08000304 +/* IPLL_CON1 */ +#define IPLL_CON1_VAL 0x00000080 -#define ZQ_CLK_DIV_EN (1 << 18) -#define ZQ_MANUAL_STR (1 << 1) -#define ZQ_DONE (1 << 0) +/* KPLL_CON1 */ +#define KPLL_CON1_VAL 0x200000 -#define CTRL_RDLVL_GATE_ENABLE 1 -#define CTRL_RDLVL_GATE_DISABLE 1 +/* CLK_SRC_ISP */ +#define CLK_SRC_ISP_VAL 0x33366000 +#define CLK_DIV_ISP0_VAL 0x13131300 +#define CLK_DIV_ISP1_VAL 0xbb110202 -/* 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 */ +/* CLK_FSYS */ +#define CLK_SRC_FSYS0_VAL 0x33033300 +#define CLK_DIV_FSYS0_VAL 0x0 +#define CLK_DIV_FSYS1_VAL 0x04f13c4f +#define CLK_DIV_FSYS2_VAL 0x041d0000 + +/* CLK_SRC_CPU */ +/* 0 = MOUTAPLL, 1 = SCLKMPLL */ +#define MUX_HPM_SEL 1 +#define MUX_CPU_SEL 0 +#define MUX_APLL_SEL 1 -/* 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 CLK_SRC_CPU_VAL ((MUX_HPM_SEL << 20) \ + | (MUX_CPU_SEL << 16) \ + | (MUX_APLL_SEL)) -#define PHY_CON42_CTRL_BSTLEN_SHIFT 8 -#define PHY_CON42_CTRL_RDLAT_SHIFT 0 +/* CLK_SRC_CDREX */ +#define CLK_SRC_CDREX_VAL 0x00000011 + +/* CLK_DIV_CDREX */ +#define CLK_DIV_CDREX0_VAL 0x30010100 +#define CLK_DIV_CDREX1_VAL 0x300 + +#define CLK_DIV_CDREX_VAL 0x17010100 + +/* CLK_DIV_CPU0_VAL */ +#define CLK_DIV_CPU0_VAL 0x01440020 + +/* CLK_SRC_TOP */ +#define CLK_SRC_TOP0_VAL 0x12221222 +#define CLK_SRC_TOP1_VAL 0x00100200 +#define CLK_SRC_TOP2_VAL 0x11101000 +#define CLK_SRC_TOP3_VAL 0x11111111 +#define CLK_SRC_TOP4_VAL 0x11110111 +#define CLK_SRC_TOP5_VAL 0x11111100 +#define CLK_SRC_TOP6_VAL 0x11110111 +#define CLK_SRC_TOP7_VAL 0x00022200 + +/* CLK_DIV_TOP */ +#define CLK_DIV_TOP0_VAL 0x23712311 +#define CLK_DIV_TOP1_VAL 0x13100B00 +#define CLK_DIV_TOP2_VAL 0x11101100 + +/* PLL Lock Value Factor */ +#define PLL_LOCK_FACTOR 200 +#define PLL_X_LOCK_FACTOR 3000 + +/* CLK_SRC_PERIC0 */ +#define SPDIF_SEL 1 +#define PWM_SEL 3 +#define UART4_SEL 3 +#define UART3_SEL 3 +#define UART2_SEL 3 +#define UART1_SEL 3 +#define UART0_SEL 3 +/* SRC_CLOCK = SCLK_RPLL */ +#define CLK_SRC_PERIC0_VAL ((SPDIF_SEL << 28) \ + | (PWM_SEL << 24) \ + | (UART4_SEL << 20) \ + | (UART3_SEL << 16) \ + | (UART2_SEL << 12) \ + | (UART1_SEL << 8) \ + | (UART0_SEL << 4)) + +/* CLK_SRC_PERIC1 */ +/* SRC_CLOCK = SCLK_EPLL */ +#define SPI0_SEL 6 +#define SPI1_SEL 6 +#define SPI2_SEL 6 +#define AUDIO0_SEL 6 +#define AUDIO1_SEL 6 +#define AUDIO2_SEL 6 +#define CLK_SRC_PERIC1_VAL ((SPI2_SEL << 28) \ + | (SPI1_SEL << 24) \ + | (SPI0_SEL << 20) \ + | (AUDIO2_SEL << 16) \ + | (AUDIO2_SEL << 12) \ + | (AUDIO2_SEL << 8)) + +/* CLK_DIV_PERIC0 */ +#define PWM_RATIO 8 +#define UART4_RATIO 9 +#define UART3_RATIO 9 +#define UART2_RATIO 9 +#define UART1_RATIO 9 +#define UART0_RATIO 9 + +#define CLK_DIV_PERIC0_VAL ((PWM_RATIO << 28) \ + | (UART4_RATIO << 24) \ + | (UART3_RATIO << 20) \ + | (UART2_RATIO << 16) \ + | (UART1_RATIO << 12) \ + | (UART0_RATIO << 8)) +/* CLK_DIV_PERIC1 */ +#define SPI2_RATIO 0x1 +#define SPI1_RATIO 0x1 +#define SPI0_RATIO 0x1 +#define CLK_DIV_PERIC1_VAL ((SPI2_RATIO << 28) \ + | (SPI1_RATIO << 24) \ + | (SPI0_RATIO << 20)) + +/* CLK_DIV_PERIC2 */ +#define PCM2_RATIO 0x3 +#define PCM1_RATIO 0x3 +#define CLK_DIV_PERIC2_VAL ((PCM2_RATIO << 24) \ + | (PCM1_RATIO << 16)) + +/* CLK_DIV_PERIC3 */ +#define AUDIO2_RATIO 0x5 +#define AUDIO1_RATIO 0x5 +#define AUDIO0_RATIO 0x5 +#define CLK_DIV_PERIC3_VAL ((AUDIO2_RATIO << 28) \ + | (AUDIO1_RATIO << 24) \ + | (AUDIO0_RATIO << 20)) + +/* CLK_DIV_PERIC4 */ +#define SPI2_PRE_RATIO 0x2 +#define SPI1_PRE_RATIO 0x2 +#define SPI0_PRE_RATIO 0x2 +#define CLK_DIV_PERIC4_VAL ((SPI2_PRE_RATIO << 24) \ + | (SPI1_PRE_RATIO << 16) \ + | (SPI0_PRE_RATIO << 8)) + +/* CLK_SRC_DISP1_0 */ +#define CLK_SRC_DISP1_0_VAL 0x10666600 +#define CLK_DIV_DISP1_0_VAL 0x01050211 + +#define APLL_FOUT (1 << 0) +#define KPLL_FOUT (1 << 0) + +#define CLK_DIV_CPERI1_VAL 0x3f3f0000 +#endif struct mem_timings; @@ -490,7 +887,7 @@ enum { }; /* - * Memory variant specific initialization code + * Memory variant specific initialization code for DDR3 * * @param mem Memory timings for this memory type. * @param mem_iv_size Memory interleaving size is a configurable parameter @@ -503,6 +900,9 @@ enum { int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, int reset); +/* Memory variant specific initialization code for LPDDR3 */ +void lpddr3_mem_ctrl_init(void); + /* * Configure ZQ I/O interface * @@ -531,14 +931,6 @@ void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc); */ 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 -- cgit v1.2.1 From f3d7c2fe9da9b03230cecd634ddbbb2654f3d13d Mon Sep 17 00:00:00 2001 From: Rajeshwari Birje Date: Thu, 26 Dec 2013 09:44:22 +0530 Subject: Exynos5420: Add DDR3 initialization for 5420 This patch intends to add DDR3 initialization code for Exynos5420. Signed-off-by: Akshay Saraswat Signed-off-by: Rajeshwari S Shinde Acked-by: Simon Glass Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/dmc_common.c | 60 ++-- arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 439 +++++++++++++++++++++++++++++- arch/arm/cpu/armv7/exynos/exynos5_setup.h | 26 +- 3 files changed, 469 insertions(+), 56 deletions(-) (limited to 'arch/arm/cpu/armv7') diff --git a/arch/arm/cpu/armv7/exynos/dmc_common.c b/arch/arm/cpu/armv7/exynos/dmc_common.c index 53cfe6edb1..cca925e42c 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_common.c +++ b/arch/arm/cpu/armv7/exynos/dmc_common.c @@ -1,5 +1,5 @@ /* - * Mem setup common file for different types of DDR present on SMDK5250 boards. + * Mem setup common file for different types of DDR present on Exynos boards. * * Copyright (C) 2012 Samsung Electronics * @@ -15,9 +15,9 @@ #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) +int dmc_config_zq(struct mem_timings *mem, uint32_t *phy0_con16, + uint32_t *phy1_con16, uint32_t *phy0_con17, + uint32_t *phy1_con17) { unsigned long val = 0; int i; @@ -31,19 +31,19 @@ int dmc_config_zq(struct mem_timings *mem, 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); + writel(val, phy0_con16); + writel(val, phy1_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); + writel(val, phy0_con16); + writel(val, phy1_con16); /* ZQ_MANUAL_START: Enable */ val |= ZQ_MANUAL_STR; - writel(val, &phy0_ctrl->phy_con16); - writel(val, &phy1_ctrl->phy_con16); + writel(val, phy0_con16); + writel(val, phy1_con16); /* ZQ_MANUAL_START: Disable */ val &= ~ZQ_MANUAL_STR; @@ -53,47 +53,47 @@ int dmc_config_zq(struct mem_timings *mem, * 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) { + while ((readl(phy0_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { sdelay(100); i--; } if (!i) return -1; - writel(val, &phy0_ctrl->phy_con16); + writel(val, phy0_con16); i = ZQ_INIT_TIMEOUT; - while ((readl(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { + while ((readl(phy1_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { sdelay(100); i--; } if (!i) return -1; - writel(val, &phy1_ctrl->phy_con16); + writel(val, phy1_con16); return 0; } -void update_reset_dll(struct exynos5_dmc *dmc, enum ddr_mode mode) +void update_reset_dll(uint32_t *phycontrol0, 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); + writel(val, phycontrol0); } /* Update DLL Information: Force DLL Resyncronization */ - val = readl(&dmc->phycontrol0); + val = readl(phycontrol0); val |= FP_RSYNC; - writel(val, &dmc->phycontrol0); + writel(val, phycontrol0); /* Reset Force DLL Resyncronization */ - val = readl(&dmc->phycontrol0); + val = readl(phycontrol0); val &= ~FP_RSYNC; - writel(val, &dmc->phycontrol0); + writel(val, phycontrol0); } -void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) +void dmc_config_mrs(struct mem_timings *mem, uint32_t *directcmd) { int channel, chip; @@ -107,7 +107,7 @@ void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) mask |= chip << DIRECT_CMD_CHIP_SHIFT; /* Sending NOP command */ - writel(DIRECT_CMD_NOP | mask, &dmc->directcmd); + writel(DIRECT_CMD_NOP | mask, directcmd); /* * TODO(alim.akhtar@samsung.com): Do we need these @@ -119,14 +119,14 @@ void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) /* Sending EMRS/MRS commands */ for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) { writel(mem->direct_cmd_msr[i] | mask, - &dmc->directcmd); + directcmd); sdelay(0x10000); } if (mem->send_zq_init) { /* Sending ZQINIT command */ writel(DIRECT_CMD_ZQINIT | mask, - &dmc->directcmd); + directcmd); sdelay(10000); } @@ -134,7 +134,7 @@ void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) } } -void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc) +void dmc_config_prech(struct mem_timings *mem, uint32_t *directcmd) { int channel, chip; @@ -146,20 +146,12 @@ void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc) mask |= chip << DIRECT_CMD_CHIP_SHIFT; /* PALL (all banks precharge) CMD */ - writel(DIRECT_CMD_PALL | mask, &dmc->directcmd); + writel(DIRECT_CMD_PALL | mask, directcmd); sdelay(0x10000); } } } -void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc) -{ - writel(mem->memconfig, &dmc->memconfig0); - writel(mem->memconfig, &dmc->memconfig1); - writel(DMC_MEMBASECONFIG0_VAL, &dmc->membaseconfig0); - writel(DMC_MEMBASECONFIG1_VAL, &dmc->membaseconfig1); -} - void mem_ctrl_init(int reset) { struct spl_machine_param *param = spl_get_machine_params(); diff --git a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c index 5f5914ede8..487e6f423f 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c @@ -1,5 +1,5 @@ /* - * DDR3 mem setup file for SMDK5250 board based on EXYNOS5 + * DDR3 mem setup file for board based on EXYNOS5 * * Copyright (C) 2012 Samsung Electronics * @@ -11,12 +11,14 @@ #include #include #include +#include #include "common_setup.h" #include "exynos5_setup.h" #include "clock_init.h" -#define RDLVL_COMPLETE_TIMEOUT 10000 +#define TIMEOUT 10000 +#ifdef CONFIG_EXYNOS5250 static void reset_phy_ctrl(void) { struct exynos5_clock *clk = @@ -57,7 +59,8 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, writel(val, &phy1_ctrl->phy_con42); /* ZQ Calibration */ - if (dmc_config_zq(mem, phy0_ctrl, phy1_ctrl)) + if (dmc_config_zq(mem, &phy0_ctrl->phy_con16, &phy1_ctrl->phy_con16, + &phy0_ctrl->phy_con17, &phy1_ctrl->phy_con17)) return SETUP_ERR_ZQ_CALIBRATION_FAILURE; /* DQ Signal */ @@ -68,7 +71,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, | (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT), &dmc->concontrol); - update_reset_dll(dmc, DDR_MODE_DDR3); + update_reset_dll(&dmc->phycontrol0, DDR_MODE_DDR3); /* DQS Signal */ writel(mem->phy0_dqs, &phy0_ctrl->phy_con4); @@ -93,7 +96,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT), &phy1_ctrl->phy_con12); - update_reset_dll(dmc, DDR_MODE_DDR3); + update_reset_dll(&dmc->phycontrol0, DDR_MODE_DDR3); writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), &dmc->concontrol); @@ -124,10 +127,10 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, writel(mem->timing_power, &dmc->timingpower); /* Send PALL command */ - dmc_config_prech(mem, dmc); + dmc_config_prech(mem, &dmc->directcmd); /* Send NOP, MRS and ZQINIT commands */ - dmc_config_mrs(mem, dmc); + dmc_config_mrs(mem, &dmc->directcmd); if (mem->gate_leveling_enable) { val = PHY_CON0_RESET_VAL; @@ -174,7 +177,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, writel(val, &phy1_ctrl->phy_con1); writel(CTRL_RDLVL_GATE_ENABLE, &dmc->rdlvl_config); - i = RDLVL_COMPLETE_TIMEOUT; + i = TIMEOUT; while ((readl(&dmc->phystatus) & (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1)) != (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1) && i > 0) { @@ -202,11 +205,11 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, writel(val, &phy0_ctrl->phy_con12); writel(val, &phy1_ctrl->phy_con12); - update_reset_dll(dmc, DDR_MODE_DDR3); + update_reset_dll(&dmc->phycontrol0, DDR_MODE_DDR3); } /* Send PALL command */ - dmc_config_prech(mem, dmc); + dmc_config_prech(mem, &dmc->directcmd); writel(mem->memcontrol, &dmc->memcontrol); @@ -215,3 +218,419 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT), &dmc->concontrol); return 0; } +#endif + +#ifdef CONFIG_EXYNOS5420 +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, + int reset) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + struct exynos5420_power *power = + (struct exynos5420_power *)samsung_get_base_power(); + struct exynos5420_phy_control *phy0_ctrl, *phy1_ctrl; + struct exynos5420_dmc *drex0, *drex1; + struct exynos5420_tzasc *tzasc0, *tzasc1; + uint32_t val, n_lock_r, n_lock_w_phy0, n_lock_w_phy1; + int chip; + int i; + + phy0_ctrl = (struct exynos5420_phy_control *)samsung_get_base_dmc_phy(); + phy1_ctrl = (struct exynos5420_phy_control *)(samsung_get_base_dmc_phy() + + DMC_OFFSET); + drex0 = (struct exynos5420_dmc *)samsung_get_base_dmc_ctrl(); + drex1 = (struct exynos5420_dmc *)(samsung_get_base_dmc_ctrl() + + DMC_OFFSET); + tzasc0 = (struct exynos5420_tzasc *)samsung_get_base_dmc_tzasc(); + tzasc1 = (struct exynos5420_tzasc *)(samsung_get_base_dmc_tzasc() + + DMC_OFFSET); + + /* Enable PAUSE for DREX */ + setbits_le32(&clk->pause, ENABLE_BIT); + + /* Enable BYPASS mode */ + setbits_le32(&clk->bpll_con1, BYPASS_EN); + + writel(MUX_BPLL_SEL_FOUTBPLL, &clk->src_cdrex); + do { + val = readl(&clk->mux_stat_cdrex); + val &= BPLL_SEL_MASK; + } while (val != FOUTBPLL); + + clrbits_le32(&clk->bpll_con1, BYPASS_EN); + + /* Specify the DDR memory type as DDR3 */ + val = readl(&phy0_ctrl->phy_con0); + val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK << PHY_CON0_CTRL_DDR_MODE_SHIFT); + val |= (DDR_MODE_DDR3 << PHY_CON0_CTRL_DDR_MODE_SHIFT); + writel(val, &phy0_ctrl->phy_con0); + + val = readl(&phy1_ctrl->phy_con0); + val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK << PHY_CON0_CTRL_DDR_MODE_SHIFT); + val |= (DDR_MODE_DDR3 << PHY_CON0_CTRL_DDR_MODE_SHIFT); + writel(val, &phy1_ctrl->phy_con0); + + /* 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); + + val = readl(&phy0_ctrl->phy_con26); + val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET); + val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET); + writel(val, &phy0_ctrl->phy_con26); + + val = readl(&phy1_ctrl->phy_con26); + val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET); + val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET); + writel(val, &phy1_ctrl->phy_con26); + + /* + * Set Driver strength for CK, CKE, CS & CA to 0x7 + * Set Driver strength for Data Slice 0~3 to 0x7 + */ + val = (0x7 << CA_CK_DRVR_DS_OFFSET) | (0x7 << CA_CKE_DRVR_DS_OFFSET) | + (0x7 << CA_CS_DRVR_DS_OFFSET) | (0x7 << CA_ADR_DRVR_DS_OFFSET); + val |= (0x7 << DA_3_DS_OFFSET) | (0x7 << DA_2_DS_OFFSET) | + (0x7 << DA_1_DS_OFFSET) | (0x7 << DA_0_DS_OFFSET); + writel(val, &phy0_ctrl->phy_con39); + writel(val, &phy1_ctrl->phy_con39); + + /* ZQ Calibration */ + if (dmc_config_zq(mem, &phy0_ctrl->phy_con16, &phy1_ctrl->phy_con16, + &phy0_ctrl->phy_con17, &phy1_ctrl->phy_con17)) + return SETUP_ERR_ZQ_CALIBRATION_FAILURE; + + clrbits_le32(&phy0_ctrl->phy_con16, ZQ_CLK_DIV_EN); + clrbits_le32(&phy1_ctrl->phy_con16, ZQ_CLK_DIV_EN); + + /* DQ Signal */ + val = readl(&phy0_ctrl->phy_con14); + val |= mem->phy0_pulld_dqs; + writel(val, &phy0_ctrl->phy_con14); + val = readl(&phy1_ctrl->phy_con14); + val |= mem->phy1_pulld_dqs; + writel(val, &phy1_ctrl->phy_con14); + + val = MEM_TERM_EN | PHY_TERM_EN; + writel(val, &drex0->phycontrol0); + writel(val, &drex1->phycontrol0); + + writel(mem->concontrol | + (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), + &drex0->concontrol); + writel(mem->concontrol | + (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), + &drex1->concontrol); + + do { + val = readl(&drex0->phystatus); + } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE); + do { + val = readl(&drex1->phystatus); + } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE); + + clrbits_le32(&drex0->concontrol, DFI_INIT_START); + clrbits_le32(&drex1->concontrol, DFI_INIT_START); + + update_reset_dll(&drex0->phycontrol0, DDR_MODE_DDR3); + update_reset_dll(&drex1->phycontrol0, DDR_MODE_DDR3); + + /* + * Set Base Address: + * 0x2000_0000 ~ 0x5FFF_FFFF + * 0x6000_0000 ~ 0x9FFF_FFFF + */ + /* MEMBASECONFIG0 */ + val = DMC_MEMBASECONFIGX_CHIP_BASE(DMC_CHIP_BASE_0) | + DMC_MEMBASECONFIGX_CHIP_MASK(DMC_CHIP_MASK); + writel(val, &tzasc0->membaseconfig0); + writel(val, &tzasc1->membaseconfig0); + + /* MEMBASECONFIG1 */ + val = DMC_MEMBASECONFIGX_CHIP_BASE(DMC_CHIP_BASE_1) | + DMC_MEMBASECONFIGX_CHIP_MASK(DMC_CHIP_MASK); + writel(val, &tzasc0->membaseconfig1); + writel(val, &tzasc1->membaseconfig1); + + /* + * Memory Channel Inteleaving Size + * Ares Channel interleaving = 128 bytes + */ + /* MEMCONFIG0/1 */ + writel(mem->memconfig, &tzasc0->memconfig0); + writel(mem->memconfig, &tzasc1->memconfig0); + writel(mem->memconfig, &tzasc0->memconfig1); + writel(mem->memconfig, &tzasc1->memconfig1); + + /* Precharge Configuration */ + writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, + &drex0->prechconfig0); + writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, + &drex1->prechconfig0); + + /* + * TimingRow, TimingData, TimingPower and Timingaref + * values as per Memory AC parameters + */ + writel(mem->timing_ref, &drex0->timingref); + writel(mem->timing_ref, &drex1->timingref); + writel(mem->timing_row, &drex0->timingrow0); + writel(mem->timing_row, &drex1->timingrow0); + writel(mem->timing_data, &drex0->timingdata0); + writel(mem->timing_data, &drex1->timingdata0); + writel(mem->timing_power, &drex0->timingpower0); + writel(mem->timing_power, &drex1->timingpower0); + + if (reset) { + /* + * Send NOP, MRS and ZQINIT commands + * Sending MRS command will reset the DRAM. We should not be + * reseting the DRAM after resume, this will lead to memory + * corruption as DRAM content is lost after DRAM reset + */ + dmc_config_mrs(mem, &drex0->directcmd); + dmc_config_mrs(mem, &drex1->directcmd); + } else { + /* + * During Suspend-Resume & S/W-Reset, as soon as PMU releases + * pad retention, CKE goes high. This causes memory contents + * not to be retained during DRAM initialization. Therfore, + * there is a new control register(0x100431e8[28]) which lets us + * release pad retention and retain the memory content until the + * initialization is complete. + */ + writel(PAD_RETENTION_DRAM_COREBLK_VAL, + &power->pad_retention_dram_coreblk_option); + do { + val = readl(&power->pad_retention_dram_status); + } while (val != 0x1); + + /* + * CKE PAD retention disables DRAM self-refresh mode. + * Send auto refresh command for DRAM refresh. + */ + for (i = 0; i < 128; i++) { + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(DIRECT_CMD_REFA | + (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(DIRECT_CMD_REFA | + (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + } + } + + if (mem->gate_leveling_enable) { + writel(PHY_CON0_RESET_VAL, &phy0_ctrl->phy_con0); + writel(PHY_CON0_RESET_VAL, &phy1_ctrl->phy_con0); + + setbits_le32(&phy0_ctrl->phy_con0, P0_CMD_EN); + setbits_le32(&phy1_ctrl->phy_con0, P0_CMD_EN); + + val = PHY_CON2_RESET_VAL; + val |= INIT_DESKEW_EN; + writel(val, &phy0_ctrl->phy_con2); + writel(val, &phy1_ctrl->phy_con2); + + val = readl(&phy0_ctrl->phy_con1); + val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET); + writel(val, &phy0_ctrl->phy_con1); + + val = readl(&phy1_ctrl->phy_con1); + val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET); + writel(val, &phy1_ctrl->phy_con1); + + n_lock_r = readl(&phy0_ctrl->phy_con13); + n_lock_w_phy0 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2; + n_lock_r = readl(&phy0_ctrl->phy_con12); + n_lock_r &= ~CTRL_DLL_ON; + n_lock_r |= n_lock_w_phy0; + writel(n_lock_r, &phy0_ctrl->phy_con12); + + n_lock_r = readl(&phy1_ctrl->phy_con13); + n_lock_w_phy1 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2; + n_lock_r = readl(&phy1_ctrl->phy_con12); + n_lock_r &= ~CTRL_DLL_ON; + n_lock_r |= n_lock_w_phy1; + writel(n_lock_r, &phy1_ctrl->phy_con12); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT) | 0x4; + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + setbits_le32(&phy0_ctrl->phy_con2, RDLVL_GATE_EN); + setbits_le32(&phy1_ctrl->phy_con2, RDLVL_GATE_EN); + + setbits_le32(&phy0_ctrl->phy_con0, CTRL_SHGATE); + setbits_le32(&phy1_ctrl->phy_con0, CTRL_SHGATE); + + val = readl(&phy0_ctrl->phy_con1); + val &= ~(CTRL_GATEDURADJ_MASK); + writel(val, &phy0_ctrl->phy_con1); + + val = readl(&phy1_ctrl->phy_con1); + val &= ~(CTRL_GATEDURADJ_MASK); + writel(val, &phy1_ctrl->phy_con1); + + writel(CTRL_RDLVL_GATE_ENABLE, &drex0->rdlvl_config); + i = TIMEOUT; + while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) != + RDLVL_COMPLETE_CHO) && (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, &drex0->rdlvl_config); + + writel(CTRL_RDLVL_GATE_ENABLE, &drex1->rdlvl_config); + i = TIMEOUT; + while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) != + RDLVL_COMPLETE_CHO) && (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, &drex1->rdlvl_config); + + writel(0, &phy0_ctrl->phy_con14); + writel(0, &phy1_ctrl->phy_con14); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT); + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + if (mem->read_leveling_enable) { + /* Set Read DQ Calibration */ + val = (0x3 << DIRECT_CMD_BANK_SHIFT) | 0x4; + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + val = readl(&phy0_ctrl->phy_con1); + val |= READ_LEVELLING_DDR3; + writel(val, &phy0_ctrl->phy_con1); + val = readl(&phy1_ctrl->phy_con1); + val |= READ_LEVELLING_DDR3; + writel(val, &phy1_ctrl->phy_con1); + + val = readl(&phy0_ctrl->phy_con2); + val |= (RDLVL_EN | RDLVL_INCR_ADJ); + writel(val, &phy0_ctrl->phy_con2); + val = readl(&phy1_ctrl->phy_con2); + val |= (RDLVL_EN | RDLVL_INCR_ADJ); + writel(val, &phy1_ctrl->phy_con2); + + setbits_le32(&drex0->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + i = TIMEOUT; + while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) + != RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take + * to timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + + clrbits_le32(&drex0->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + setbits_le32(&drex1->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + i = TIMEOUT; + while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) + != RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take + * to timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + + clrbits_le32(&drex1->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT); + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + update_reset_dll(&drex0->phycontrol0, DDR_MODE_DDR3); + update_reset_dll(&drex1->phycontrol0, DDR_MODE_DDR3); + } + + /* Common Settings for Leveling */ + val = PHY_CON12_RESET_VAL; + writel((val + n_lock_w_phy0), &phy0_ctrl->phy_con12); + writel((val + n_lock_w_phy1), &phy1_ctrl->phy_con12); + + setbits_le32(&phy0_ctrl->phy_con2, DLL_DESKEW_EN); + setbits_le32(&phy1_ctrl->phy_con2, DLL_DESKEW_EN); + } + + /* Send PALL command */ + dmc_config_prech(mem, &drex0->directcmd); + dmc_config_prech(mem, &drex1->directcmd); + + writel(mem->memcontrol, &drex0->memcontrol); + writel(mem->memcontrol, &drex1->memcontrol); + + /* + * Set DMC Concontrol: Enable auto-refresh counter, provide + * read data fetch cycles and enable DREX auto set powerdown + * for input buffer of I/O in none read memory state. + */ + writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)| + DMC_CONCONTROL_IO_PD_CON(0x2), + &drex0->concontrol); + writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)| + DMC_CONCONTROL_IO_PD_CON(0x2), + &drex1->concontrol); + + /* + * Enable Clock Gating Control for DMC + * this saves around 25 mw dmc power as compared to the power + * consumption without these bits enabled + */ + setbits_le32(&drex0->cgcontrol, DMC_INTERNAL_CG); + setbits_le32(&drex1->cgcontrol, DMC_INTERNAL_CG); + + return 0; +} +#endif diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index c8d6515044..53b0ace6e3 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -696,6 +696,7 @@ #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE #else +#define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000 /* APLL_CON1 */ #define APLL_CON1_VAL (0x0020F300) @@ -907,37 +908,38 @@ void lpddr3_mem_ctrl_init(void); * 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 + * @param phy0_con16 Register address for dmc_phy0->phy_con16 + * @param phy1_con16 Register address for dmc_phy1->phy_con16 + * @param phy0_con17 Register address for dmc_phy0->phy_con17 + * @param phy1_con17 Register address for dmc_phy1->phy_con17 * @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); - +int dmc_config_zq(struct mem_timings *mem, uint32_t *phy0_con16, + uint32_t *phy1_con16, uint32_t *phy0_con17, + uint32_t *phy1_con17); /* * Send NOP and MRS/EMRS Direct commands * * @param mem Memory timings for this memory type. - * @param dmc Pointer to struct of DMC registers + * @param directcmd Register address for dmc_phy->directcmd */ -void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc); +void dmc_config_mrs(struct mem_timings *mem, uint32_t *directcmd); /* * Send PALL Direct commands * * @param mem Memory timings for this memory type. - * @param dmc Pointer to struct of DMC registers + * @param directcmd Register address for dmc_phy->directcmd */ -void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc); +void dmc_config_prech(struct mem_timings *mem, uint32_t *directcmd); /* * 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 phycontrol0 Register address for dmc_phy->phycontrol0 * @param ddr_mode Type of DDR memory */ -void update_reset_dll(struct exynos5_dmc *, enum ddr_mode); +void update_reset_dll(uint32_t *phycontrol0, enum ddr_mode); #endif -- cgit v1.2.1 From 5af4a4f74ac0607c71f5fca3fd0c6679b662b207 Mon Sep 17 00:00:00 2001 From: Rajeshwari Birje Date: Thu, 26 Dec 2013 09:44:23 +0530 Subject: Exynos5420: Add support for 5420 in pinmux and gpio Adds code in pinmux and gpio framework to support Exynos5420. Signed-off-by: Naveen Krishna Chatradhi Signed-off-by: Akshay Saraswat Signed-off-by: Rajeshwari S Shinde Acked-by: Simon Glass Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/pinmux.c | 260 ++++++++++++++++++++++++++++++++++++- 1 file changed, 258 insertions(+), 2 deletions(-) (limited to 'arch/arm/cpu/armv7') diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index 74cc7009ff..904177a149 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -46,6 +46,42 @@ static void exynos5_uart_config(int peripheral) } } +static void exynos5420_uart_config(int peripheral) +{ + struct exynos5420_gpio_part1 *gpio1 = + (struct exynos5420_gpio_part1 *)samsung_get_base_gpio_part1(); + struct s5p_gpio_bank *bank; + int i, start, count; + + switch (peripheral) { + case PERIPH_ID_UART0: + bank = &gpio1->a0; + start = 0; + count = 4; + break; + case PERIPH_ID_UART1: + bank = &gpio1->a0; + start = 4; + count = 4; + break; + case PERIPH_ID_UART2: + bank = &gpio1->a1; + start = 0; + count = 4; + break; + case PERIPH_ID_UART3: + bank = &gpio1->a1; + start = 4; + count = 2; + break; + } + + for (i = start; i < start + count; i++) { + s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + } +} + static int exynos5_mmc_config(int peripheral, int flags) { struct exynos5_gpio_part1 *gpio1 = @@ -101,6 +137,75 @@ static int exynos5_mmc_config(int peripheral, int flags) return 0; } +static int exynos5420_mmc_config(int peripheral, int flags) +{ + struct exynos5420_gpio_part3 *gpio3 = + (struct exynos5420_gpio_part3 *)samsung_get_base_gpio_part3(); + struct s5p_gpio_bank *bank = NULL, *bank_ext = NULL; + int i, start; + + switch (peripheral) { + case PERIPH_ID_SDMMC0: + bank = &gpio3->c0; + bank_ext = &gpio3->c3; + start = 0; + break; + case PERIPH_ID_SDMMC1: + bank = &gpio3->c1; + bank_ext = &gpio3->d1; + start = 4; + break; + case PERIPH_ID_SDMMC2: + bank = &gpio3->c2; + bank_ext = NULL; + start = 0; + break; + default: + start = 0; + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + + if ((flags & PINMUX_FLAG_8BIT_MODE) && !bank_ext) { + debug("SDMMC device %d does not support 8bit mode", + peripheral); + return -1; + } + + if (flags & PINMUX_FLAG_8BIT_MODE) { + for (i = start; i <= (start + 3); i++) { + s5p_gpio_cfg_pin(bank_ext, i, GPIO_FUNC(0x2)); + s5p_gpio_set_pull(bank_ext, i, GPIO_PULL_UP); + s5p_gpio_set_drv(bank_ext, i, GPIO_DRV_4X); + } + } + + for (i = 0; i < 3; i++) { + /* + * MMC0 is intended to be used for eMMC. The + * card detect pin is used as a VDDEN signal to + * power on the eMMC. The 5420 iROM makes + * this same assumption. + */ + if ((peripheral == PERIPH_ID_SDMMC0) && (i == 2)) { + s5p_gpio_set_value(bank, i, 1); + s5p_gpio_cfg_pin(bank, i, GPIO_OUTPUT); + } else { + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + } + s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); + s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); + } + + for (i = 3; i <= 6; i++) { + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + s5p_gpio_set_pull(bank, i, GPIO_PULL_UP); + s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); + } + + return 0; +} + static void exynos5_sromc_config(int flags) { struct exynos5_gpio_part1 *gpio1 = @@ -216,6 +321,59 @@ static void exynos5_i2c_config(int peripheral, int flags) } } +static void exynos5420_i2c_config(int peripheral) +{ + struct exynos5420_gpio_part1 *gpio1 = + (struct exynos5420_gpio_part1 *)samsung_get_base_gpio_part1(); + + switch (peripheral) { + case PERIPH_ID_I2C0: + s5p_gpio_cfg_pin(&gpio1->b3, 0, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b3, 1, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C1: + s5p_gpio_cfg_pin(&gpio1->b3, 2, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b3, 3, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C2: + s5p_gpio_cfg_pin(&gpio1->a0, 6, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a0, 7, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C3: + s5p_gpio_cfg_pin(&gpio1->a1, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a1, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C4: + s5p_gpio_cfg_pin(&gpio1->a2, 0, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a2, 1, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C5: + s5p_gpio_cfg_pin(&gpio1->a2, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a2, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C6: + s5p_gpio_cfg_pin(&gpio1->b1, 3, GPIO_FUNC(0x4)); + s5p_gpio_cfg_pin(&gpio1->b1, 4, GPIO_FUNC(0x4)); + break; + case PERIPH_ID_I2C7: + s5p_gpio_cfg_pin(&gpio1->b2, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->b2, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C8: + s5p_gpio_cfg_pin(&gpio1->b3, 4, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b3, 5, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C9: + s5p_gpio_cfg_pin(&gpio1->b3, 6, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b3, 7, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C10: + s5p_gpio_cfg_pin(&gpio1->b4, 0, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->b4, 1, GPIO_FUNC(0x2)); + break; + } +} + static void exynos5_i2s_config(int peripheral) { int i; @@ -279,6 +437,58 @@ void exynos5_spi_config(int peripheral) } } +void exynos5420_spi_config(int peripheral) +{ + int cfg, pin, i; + struct s5p_gpio_bank *bank = NULL; + struct exynos5420_gpio_part1 *gpio1 = + (struct exynos5420_gpio_part1 *)samsung_get_base_gpio_part1(); + struct exynos5420_gpio_part4 *gpio4 = + (struct exynos5420_gpio_part4 *)samsung_get_base_gpio_part4(); + + switch (peripheral) { + case PERIPH_ID_SPI0: + bank = &gpio1->a2; + cfg = GPIO_FUNC(0x2); + pin = 0; + break; + case PERIPH_ID_SPI1: + bank = &gpio1->a2; + cfg = GPIO_FUNC(0x2); + pin = 4; + break; + case PERIPH_ID_SPI2: + bank = &gpio1->b1; + cfg = GPIO_FUNC(0x5); + pin = 1; + break; + case PERIPH_ID_SPI3: + bank = &gpio4->f1; + cfg = GPIO_FUNC(0x2); + pin = 0; + break; + case PERIPH_ID_SPI4: + cfg = 0; + pin = 0; + break; + default: + cfg = 0; + pin = 0; + debug("%s: invalid peripheral %d", __func__, peripheral); + return; + } + + if (peripheral != PERIPH_ID_SPI4) { + for (i = pin; i < pin + 4; i++) + s5p_gpio_cfg_pin(bank, i, cfg); + } else { + for (i = 0; i < 2; i++) { + s5p_gpio_cfg_pin(&gpio4->f0, i + 2, GPIO_FUNC(0x4)); + s5p_gpio_cfg_pin(&gpio4->e0, i + 4, GPIO_FUNC(0x4)); + } + } +} + static int exynos5_pinmux_config(int peripheral, int flags) { switch (peripheral) { @@ -325,6 +535,48 @@ static int exynos5_pinmux_config(int peripheral, int flags) return 0; } +static int exynos5420_pinmux_config(int peripheral, int flags) +{ + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case PERIPH_ID_UART3: + exynos5420_uart_config(peripheral); + break; + case PERIPH_ID_SDMMC0: + case PERIPH_ID_SDMMC1: + case PERIPH_ID_SDMMC2: + case PERIPH_ID_SDMMC3: + return exynos5420_mmc_config(peripheral, flags); + case PERIPH_ID_SPI0: + case PERIPH_ID_SPI1: + case PERIPH_ID_SPI2: + case PERIPH_ID_SPI3: + case PERIPH_ID_SPI4: + exynos5420_spi_config(peripheral); + break; + case PERIPH_ID_I2C0: + case PERIPH_ID_I2C1: + case PERIPH_ID_I2C2: + case PERIPH_ID_I2C3: + case PERIPH_ID_I2C4: + case PERIPH_ID_I2C5: + case PERIPH_ID_I2C6: + case PERIPH_ID_I2C7: + case PERIPH_ID_I2C8: + case PERIPH_ID_I2C9: + case PERIPH_ID_I2C10: + exynos5420_i2c_config(peripheral); + break; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + + return 0; +} + static void exynos4_i2c_config(int peripheral, int flags) { struct exynos4_gpio_part1 *gpio1 = @@ -475,13 +727,17 @@ static int exynos4_pinmux_config(int peripheral, int flags) int exynos_pinmux_config(int peripheral, int flags) { if (cpu_is_exynos5()) { - return exynos5_pinmux_config(peripheral, flags); + if (proid_is_exynos5420()) + return exynos5420_pinmux_config(peripheral, flags); + else if (proid_is_exynos5250()) + return exynos5_pinmux_config(peripheral, flags); } else if (cpu_is_exynos4()) { return exynos4_pinmux_config(peripheral, flags); } else { debug("pinmux functionality not supported\n"); - return -1; } + + return -1; } #ifdef CONFIG_OF_CONTROL -- cgit v1.2.1