1 // SPDX-License-Identifier: GPL-2.0+
3 * Mem setup common file for different types of DDR present on Exynos boards.
5 * Copyright (C) 2012 Samsung Electronics
9 #include <asm/arch/spl.h>
11 #include "clock_init.h"
12 #include "common_setup.h"
13 #include "exynos5_setup.h"
15 #define ZQ_INIT_TIMEOUT 10000
17 int dmc_config_zq(struct mem_timings *mem, uint32_t *phy0_con16,
18 uint32_t *phy1_con16, uint32_t *phy0_con17,
21 unsigned long val = 0;
26 * Select Driver Strength,
27 * long calibration for manual calibration
29 val = PHY_CON16_RESET_VAL;
30 val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT;
31 val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT;
33 writel(val, phy0_con16);
34 writel(val, phy1_con16);
36 /* Disable termination */
37 if (mem->zq_mode_noterm)
38 val |= PHY_CON16_ZQ_MODE_NOTERM_MASK;
39 writel(val, phy0_con16);
40 writel(val, phy1_con16);
42 /* ZQ_MANUAL_START: Enable */
44 writel(val, phy0_con16);
45 writel(val, phy1_con16);
47 /* ZQ_MANUAL_START: Disable */
48 val &= ~ZQ_MANUAL_STR;
51 * Since we are manaully calibrating the ZQ values,
52 * we are looping for the ZQ_init to complete.
55 while ((readl(phy0_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
61 writel(val, phy0_con16);
64 while ((readl(phy1_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
70 writel(val, phy1_con16);
75 void update_reset_dll(uint32_t *phycontrol0, enum ddr_mode mode)
79 if (mode == DDR_MODE_DDR3) {
80 val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE;
81 writel(val, phycontrol0);
84 /* Update DLL Information: Force DLL Resyncronization */
85 val = readl(phycontrol0);
87 writel(val, phycontrol0);
89 /* Reset Force DLL Resyncronization */
90 val = readl(phycontrol0);
92 writel(val, phycontrol0);
95 void dmc_config_mrs(struct mem_timings *mem, uint32_t *directcmd)
99 for (channel = 0; channel < mem->dmc_channels; channel++) {
102 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
103 for (chip = 0; chip < mem->chips_to_configure; chip++) {
106 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
108 /* Sending NOP command */
109 writel(DIRECT_CMD_NOP | mask, directcmd);
112 * TODO(alim.akhtar@samsung.com): Do we need these
113 * delays? This one and the next were not there for
118 /* Sending EMRS/MRS commands */
119 for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) {
120 writel(mem->direct_cmd_msr[i] | mask,
125 if (mem->send_zq_init) {
126 /* Sending ZQINIT command */
127 writel(DIRECT_CMD_ZQINIT | mask,
136 void dmc_config_prech(struct mem_timings *mem, uint32_t *directcmd)
140 for (channel = 0; channel < mem->dmc_channels; channel++) {
143 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
144 for (chip = 0; chip < mem->chips_per_channel; chip++) {
145 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
147 /* PALL (all banks precharge) CMD */
148 writel(DIRECT_CMD_PALL | mask, directcmd);
154 void mem_ctrl_init(int reset)
156 struct spl_machine_param *param = spl_get_machine_params();
157 struct mem_timings *mem;
160 mem = clock_get_mem_timings();
162 /* If there are any other memory variant, add their init call below */
163 if (param->mem_type == DDR_MODE_DDR3) {
164 ret = ddr3_mem_ctrl_init(mem, reset);
166 /* will hang if failed to init memory control */
171 /* will hang if unknow memory type */