2 * DDR3 mem setup file for SMDK5250 board based on EXYNOS5
4 * Copyright (C) 2012 Samsung Electronics
6 * SPDX-License-Identifier: GPL-2.0+
11 #include <asm/arch/clock.h>
12 #include <asm/arch/cpu.h>
13 #include <asm/arch/dmc.h>
14 #include "common_setup.h"
15 #include "exynos5_setup.h"
16 #include "clock_init.h"
18 #define RDLVL_COMPLETE_TIMEOUT 10000
20 static void reset_phy_ctrl(void)
22 struct exynos5_clock
*clk
=
23 (struct exynos5_clock
*)samsung_get_base_clock();
25 writel(DDR3PHY_CTRL_PHY_RESET_OFF
, &clk
->lpddr3phy_ctrl
);
26 writel(DDR3PHY_CTRL_PHY_RESET
, &clk
->lpddr3phy_ctrl
);
29 int ddr3_mem_ctrl_init(struct mem_timings
*mem
, unsigned long mem_iv_size
,
33 struct exynos5_phy_control
*phy0_ctrl
, *phy1_ctrl
;
34 struct exynos5_dmc
*dmc
;
37 phy0_ctrl
= (struct exynos5_phy_control
*)samsung_get_base_dmc_phy();
38 phy1_ctrl
= (struct exynos5_phy_control
*)(samsung_get_base_dmc_phy()
40 dmc
= (struct exynos5_dmc
*)samsung_get_base_dmc_ctrl();
45 /* Set Impedance Output Driver */
46 val
= (mem
->impedance
<< CA_CK_DRVR_DS_OFFSET
) |
47 (mem
->impedance
<< CA_CKE_DRVR_DS_OFFSET
) |
48 (mem
->impedance
<< CA_CS_DRVR_DS_OFFSET
) |
49 (mem
->impedance
<< CA_ADR_DRVR_DS_OFFSET
);
50 writel(val
, &phy0_ctrl
->phy_con39
);
51 writel(val
, &phy1_ctrl
->phy_con39
);
53 /* Set Read Latency and Burst Length for PHY0 and PHY1 */
54 val
= (mem
->ctrl_bstlen
<< PHY_CON42_CTRL_BSTLEN_SHIFT
) |
55 (mem
->ctrl_rdlat
<< PHY_CON42_CTRL_RDLAT_SHIFT
);
56 writel(val
, &phy0_ctrl
->phy_con42
);
57 writel(val
, &phy1_ctrl
->phy_con42
);
60 if (dmc_config_zq(mem
, phy0_ctrl
, phy1_ctrl
))
61 return SETUP_ERR_ZQ_CALIBRATION_FAILURE
;
64 writel(mem
->phy0_pulld_dqs
, &phy0_ctrl
->phy_con14
);
65 writel(mem
->phy1_pulld_dqs
, &phy1_ctrl
->phy_con14
);
67 writel(mem
->concontrol
| (mem
->rd_fetch
<< CONCONTROL_RD_FETCH_SHIFT
)
68 | (mem
->dfi_init_start
<< CONCONTROL_DFI_INIT_START_SHIFT
),
71 update_reset_dll(dmc
, DDR_MODE_DDR3
);
74 writel(mem
->phy0_dqs
, &phy0_ctrl
->phy_con4
);
75 writel(mem
->phy1_dqs
, &phy1_ctrl
->phy_con4
);
77 writel(mem
->phy0_dq
, &phy0_ctrl
->phy_con6
);
78 writel(mem
->phy1_dq
, &phy1_ctrl
->phy_con6
);
80 writel(mem
->phy0_tFS
, &phy0_ctrl
->phy_con10
);
81 writel(mem
->phy1_tFS
, &phy1_ctrl
->phy_con10
);
83 val
= (mem
->ctrl_start_point
<< PHY_CON12_CTRL_START_POINT_SHIFT
) |
84 (mem
->ctrl_inc
<< PHY_CON12_CTRL_INC_SHIFT
) |
85 (mem
->ctrl_dll_on
<< PHY_CON12_CTRL_DLL_ON_SHIFT
) |
86 (mem
->ctrl_ref
<< PHY_CON12_CTRL_REF_SHIFT
);
87 writel(val
, &phy0_ctrl
->phy_con12
);
88 writel(val
, &phy1_ctrl
->phy_con12
);
90 /* Start DLL locking */
91 writel(val
| (mem
->ctrl_start
<< PHY_CON12_CTRL_START_SHIFT
),
92 &phy0_ctrl
->phy_con12
);
93 writel(val
| (mem
->ctrl_start
<< PHY_CON12_CTRL_START_SHIFT
),
94 &phy1_ctrl
->phy_con12
);
96 update_reset_dll(dmc
, DDR_MODE_DDR3
);
98 writel(mem
->concontrol
| (mem
->rd_fetch
<< CONCONTROL_RD_FETCH_SHIFT
),
101 /* Memory Channel Inteleaving Size */
102 writel(mem
->iv_size
, &dmc
->ivcontrol
);
104 writel(mem
->memconfig
, &dmc
->memconfig0
);
105 writel(mem
->memconfig
, &dmc
->memconfig1
);
106 writel(mem
->membaseconfig0
, &dmc
->membaseconfig0
);
107 writel(mem
->membaseconfig1
, &dmc
->membaseconfig1
);
109 /* Precharge Configuration */
110 writel(mem
->prechconfig_tp_cnt
<< PRECHCONFIG_TP_CNT_SHIFT
,
113 /* Power Down mode Configuration */
114 writel(mem
->dpwrdn_cyc
<< PWRDNCONFIG_DPWRDN_CYC_SHIFT
|
115 mem
->dsref_cyc
<< PWRDNCONFIG_DSREF_CYC_SHIFT
,
118 /* TimingRow, TimingData, TimingPower and Timingaref
119 * values as per Memory AC parameters
121 writel(mem
->timing_ref
, &dmc
->timingref
);
122 writel(mem
->timing_row
, &dmc
->timingrow
);
123 writel(mem
->timing_data
, &dmc
->timingdata
);
124 writel(mem
->timing_power
, &dmc
->timingpower
);
126 /* Send PALL command */
127 dmc_config_prech(mem
, dmc
);
129 /* Send NOP, MRS and ZQINIT commands */
130 dmc_config_mrs(mem
, dmc
);
132 if (mem
->gate_leveling_enable
) {
133 val
= PHY_CON0_RESET_VAL
;
135 writel(val
, &phy0_ctrl
->phy_con0
);
136 writel(val
, &phy1_ctrl
->phy_con0
);
138 val
= PHY_CON2_RESET_VAL
;
139 val
|= INIT_DESKEW_EN
;
140 writel(val
, &phy0_ctrl
->phy_con2
);
141 writel(val
, &phy1_ctrl
->phy_con2
);
143 val
= PHY_CON0_RESET_VAL
;
145 val
|= BYTE_RDLVL_EN
;
146 writel(val
, &phy0_ctrl
->phy_con0
);
147 writel(val
, &phy1_ctrl
->phy_con0
);
149 val
= (mem
->ctrl_start_point
<<
150 PHY_CON12_CTRL_START_POINT_SHIFT
) |
151 (mem
->ctrl_inc
<< PHY_CON12_CTRL_INC_SHIFT
) |
152 (mem
->ctrl_force
<< PHY_CON12_CTRL_FORCE_SHIFT
) |
153 (mem
->ctrl_start
<< PHY_CON12_CTRL_START_SHIFT
) |
154 (mem
->ctrl_ref
<< PHY_CON12_CTRL_REF_SHIFT
);
155 writel(val
, &phy0_ctrl
->phy_con12
);
156 writel(val
, &phy1_ctrl
->phy_con12
);
158 val
= PHY_CON2_RESET_VAL
;
159 val
|= INIT_DESKEW_EN
;
160 val
|= RDLVL_GATE_EN
;
161 writel(val
, &phy0_ctrl
->phy_con2
);
162 writel(val
, &phy1_ctrl
->phy_con2
);
164 val
= PHY_CON0_RESET_VAL
;
166 val
|= BYTE_RDLVL_EN
;
168 writel(val
, &phy0_ctrl
->phy_con0
);
169 writel(val
, &phy1_ctrl
->phy_con0
);
171 val
= PHY_CON1_RESET_VAL
;
172 val
&= ~(CTRL_GATEDURADJ_MASK
);
173 writel(val
, &phy0_ctrl
->phy_con1
);
174 writel(val
, &phy1_ctrl
->phy_con1
);
176 writel(CTRL_RDLVL_GATE_ENABLE
, &dmc
->rdlvl_config
);
177 i
= RDLVL_COMPLETE_TIMEOUT
;
178 while ((readl(&dmc
->phystatus
) &
179 (RDLVL_COMPLETE_CHO
| RDLVL_COMPLETE_CH1
)) !=
180 (RDLVL_COMPLETE_CHO
| RDLVL_COMPLETE_CH1
) && i
> 0) {
182 * TODO(waihong): Comment on how long this take to
189 return SETUP_ERR_RDLV_COMPLETE_TIMEOUT
;
190 writel(CTRL_RDLVL_GATE_DISABLE
, &dmc
->rdlvl_config
);
192 writel(0, &phy0_ctrl
->phy_con14
);
193 writel(0, &phy1_ctrl
->phy_con14
);
195 val
= (mem
->ctrl_start_point
<<
196 PHY_CON12_CTRL_START_POINT_SHIFT
) |
197 (mem
->ctrl_inc
<< PHY_CON12_CTRL_INC_SHIFT
) |
198 (mem
->ctrl_force
<< PHY_CON12_CTRL_FORCE_SHIFT
) |
199 (mem
->ctrl_start
<< PHY_CON12_CTRL_START_SHIFT
) |
200 (mem
->ctrl_dll_on
<< PHY_CON12_CTRL_DLL_ON_SHIFT
) |
201 (mem
->ctrl_ref
<< PHY_CON12_CTRL_REF_SHIFT
);
202 writel(val
, &phy0_ctrl
->phy_con12
);
203 writel(val
, &phy1_ctrl
->phy_con12
);
205 update_reset_dll(dmc
, DDR_MODE_DDR3
);
208 /* Send PALL command */
209 dmc_config_prech(mem
, dmc
);
211 writel(mem
->memcontrol
, &dmc
->memcontrol
);
213 /* Set DMC Concontrol and enable auto-refresh counter */
214 writel(mem
->concontrol
| (mem
->rd_fetch
<< CONCONTROL_RD_FETCH_SHIFT
)
215 | (mem
->aref_en
<< CONCONTROL_AREF_EN_SHIFT
), &dmc
->concontrol
);