2 * Mem setup common file for different types of DDR present on SMDK5250 boards.
4 * Copyright (C) 2012 Samsung Electronics
6 * SPDX-License-Identifier: GPL-2.0+
10 #include <asm/arch/spl.h>
12 #include "clock_init.h"
13 #include "common_setup.h"
14 #include "exynos5_setup.h"
16 #define ZQ_INIT_TIMEOUT 10000
18 int dmc_config_zq(struct mem_timings *mem,
19 struct exynos5_phy_control *phy0_ctrl,
20 struct exynos5_phy_control *phy1_ctrl)
22 unsigned long val = 0;
27 * Select Driver Strength,
28 * long calibration for manual calibration
30 val = PHY_CON16_RESET_VAL;
31 val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT;
32 val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT;
34 writel(val, &phy0_ctrl->phy_con16);
35 writel(val, &phy1_ctrl->phy_con16);
37 /* Disable termination */
38 if (mem->zq_mode_noterm)
39 val |= PHY_CON16_ZQ_MODE_NOTERM_MASK;
40 writel(val, &phy0_ctrl->phy_con16);
41 writel(val, &phy1_ctrl->phy_con16);
43 /* ZQ_MANUAL_START: Enable */
45 writel(val, &phy0_ctrl->phy_con16);
46 writel(val, &phy1_ctrl->phy_con16);
48 /* ZQ_MANUAL_START: Disable */
49 val &= ~ZQ_MANUAL_STR;
52 * Since we are manaully calibrating the ZQ values,
53 * we are looping for the ZQ_init to complete.
56 while ((readl(&phy0_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
62 writel(val, &phy0_ctrl->phy_con16);
65 while ((readl(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
71 writel(val, &phy1_ctrl->phy_con16);
76 void update_reset_dll(struct exynos5_dmc *dmc, enum ddr_mode mode)
80 if (mode == DDR_MODE_DDR3) {
81 val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE;
82 writel(val, &dmc->phycontrol0);
85 /* Update DLL Information: Force DLL Resyncronization */
86 val = readl(&dmc->phycontrol0);
88 writel(val, &dmc->phycontrol0);
90 /* Reset Force DLL Resyncronization */
91 val = readl(&dmc->phycontrol0);
93 writel(val, &dmc->phycontrol0);
96 void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc)
100 for (channel = 0; channel < mem->dmc_channels; channel++) {
103 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
104 for (chip = 0; chip < mem->chips_to_configure; chip++) {
107 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
109 /* Sending NOP command */
110 writel(DIRECT_CMD_NOP | mask, &dmc->directcmd);
113 * TODO(alim.akhtar@samsung.com): Do we need these
114 * delays? This one and the next were not there for
119 /* Sending EMRS/MRS commands */
120 for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) {
121 writel(mem->direct_cmd_msr[i] | mask,
126 if (mem->send_zq_init) {
127 /* Sending ZQINIT command */
128 writel(DIRECT_CMD_ZQINIT | mask,
137 void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc)
141 for (channel = 0; channel < mem->dmc_channels; channel++) {
144 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
145 for (chip = 0; chip < mem->chips_per_channel; chip++) {
146 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
148 /* PALL (all banks precharge) CMD */
149 writel(DIRECT_CMD_PALL | mask, &dmc->directcmd);
155 void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc)
157 writel(mem->memconfig, &dmc->memconfig0);
158 writel(mem->memconfig, &dmc->memconfig1);
159 writel(DMC_MEMBASECONFIG0_VAL, &dmc->membaseconfig0);
160 writel(DMC_MEMBASECONFIG1_VAL, &dmc->membaseconfig1);
163 void mem_ctrl_init(int reset)
165 struct spl_machine_param *param = spl_get_machine_params();
166 struct mem_timings *mem;
169 mem = clock_get_mem_timings();
171 /* If there are any other memory variant, add their init call below */
172 if (param->mem_type == DDR_MODE_DDR3) {
173 ret = ddr3_mem_ctrl_init(mem, param->mem_iv_size, reset);
175 /* will hang if failed to init memory control */
180 /* will hang if unknow memory type */