3 * Copyright (c) 2011, ARM Limited. All rights reserved.
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include <Library/IoLib.h>
16 #include <Library/DebugLib.h>
17 #include <Drivers/PL341Dmc.h>
20 // DMC Configuration Register Map
22 #define DMC_STATUS_REG 0x00
23 #define DMC_COMMAND_REG 0x04
24 #define DMC_DIRECT_CMD_REG 0x08
25 #define DMC_MEMORY_CONFIG_REG 0x0C
26 #define DMC_REFRESH_PRD_REG 0x10
27 #define DMC_CAS_LATENCY_REG 0x14
28 #define DMC_WRITE_LATENCY_REG 0x18
29 #define DMC_T_MRD_REG 0x1C
30 #define DMC_T_RAS_REG 0x20
31 #define DMC_T_RC_REG 0x24
32 #define DMC_T_RCD_REG 0x28
33 #define DMC_T_RFC_REG 0x2C
34 #define DMC_T_RP_REG 0x30
35 #define DMC_T_RRD_REG 0x34
36 #define DMC_T_WR_REG 0x38
37 #define DMC_T_WTR_REG 0x3C
38 #define DMC_T_XP_REG 0x40
39 #define DMC_T_XSR_REG 0x44
40 #define DMC_T_ESR_REG 0x48
41 #define DMC_MEMORY_CFG2_REG 0x4C
42 #define DMC_MEMORY_CFG3_REG 0x50
43 #define DMC_T_FAW_REG 0x54
45 // Returns the state of the memory controller:
46 #define DMC_STATUS_CONFIG 0x0
47 #define DMC_STATUS_READY 0x1
48 #define DMC_STATUS_PAUSED 0x2
49 #define DMC_STATUS_LOWPOWER 0x3
51 // Changes the state of the memory controller:
52 #define DMC_COMMAND_GO 0x0
53 #define DMC_COMMAND_SLEEP 0x1
54 #define DMC_COMMAND_WAKEUP 0x2
55 #define DMC_COMMAND_PAUSE 0x3
56 #define DMC_COMMAND_CONFIGURE 0x4
57 #define DMC_COMMAND_ACTIVEPAUSE 0x7
59 // Determines the command required
60 #define DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL 0x0
61 #define DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH (0x1 << 18)
62 #define DMC_DIRECT_CMD_MEMCMD_MODEREG (0x2 << 18)
63 #define DMC_DIRECT_CMD_MEMCMD_EXTMODEREG (0x2 << 18)
64 #define DMC_DIRECT_CMD_MEMCMD_NOP (0x3 << 18)
65 #define DMC_DIRECT_CMD_MEMCMD_DPD (0x1 << 22)
66 #define DMC_DIRECT_CMD_BANKADDR(n) ((n & 0x3) << 16)
67 #define DMC_DIRECT_CMD_CHIP_ADDR(n) ((n & 0x3) << 20)
71 // AXI ID configuration register map
73 #define DMC_ID_0_CFG_REG 0x100
74 #define DMC_ID_1_CFG_REG 0x104
75 #define DMC_ID_2_CFG_REG 0x108
76 #define DMC_ID_3_CFG_REG 0x10C
77 #define DMC_ID_4_CFG_REG 0x110
78 #define DMC_ID_5_CFG_REG 0x114
79 #define DMC_ID_6_CFG_REG 0x118
80 #define DMC_ID_7_CFG_REG 0x11C
81 #define DMC_ID_8_CFG_REG 0x120
82 #define DMC_ID_9_CFG_REG 0x124
83 #define DMC_ID_10_CFG_REG 0x128
84 #define DMC_ID_11_CFG_REG 0x12C
85 #define DMC_ID_12_CFG_REG 0x130
86 #define DMC_ID_13_CFG_REG 0x134
87 #define DMC_ID_14_CFG_REG 0x138
88 #define DMC_ID_15_CFG_REG 0x13C
91 #define DMC_ID_CFG_QOS_DISABLE 0
92 #define DMC_ID_CFG_QOS_ENABLE 1
93 #define DMC_ID_CFG_QOS_MIN 2
97 // Chip configuration register map
99 #define DMC_CHIP_0_CFG_REG 0x200
100 #define DMC_CHIP_1_CFG_REG 0x204
101 #define DMC_CHIP_2_CFG_REG 0x208
102 #define DMC_CHIP_3_CFG_REG 0x20C
107 #define DMC_USER_STATUS_REG 0x300
108 #define DMC_USER_0_CFG_REG 0x304
109 #define DMC_USER_1_CFG_REG 0x308
110 #define DMC_FEATURE_CRTL_REG 0x30C
111 #define DMC_USER_2_CFG_REG 0x310
115 // PHY Register Settings
117 #define TC_UIOLHNC_MASK 0x000003C0
118 #define TC_UIOLHNC_SHIFT 0x6
119 #define TC_UIOLHPC_MASK 0x0000003F
120 #define TC_UIOLHPC_SHIFT 0x2
121 #define TC_UIOHOCT_MASK 0x2
122 #define TC_UIOHOCT_SHIFT 0x1
123 #define TC_UIOHSTOP_SHIFT 0x0
124 #define TC_UIOLHXC_VALUE 0x4
127 // Extended Mode Register settings
129 #define DDR_EMR_OCD_MASK 0x0000380
130 #define DDR_EMR_OCD_SHIFT 0x7
131 #define DDR_EMR_RTT_MASK 0x00000044 // DDR2 Device RTT (ODT) settings
132 #define DDR_EMR_RTT_SHIFT 0x2
133 #define DDR_EMR_ODS_MASK 0x00000002 // DDR2 Output Drive Strength
134 #define DDR_EMR_ODS_SHIFT 0x0001
135 // Termination Values:
136 #define DDR_EMR_RTT_50 0x00000044 // DDR2 50 Ohm termination
137 #define DDR_EMR_RTT_75R 0x00000004 // DDR2 75 Ohm termination
138 #define DDR_EMR_RTT_150 0x00000040 // DDR2 150 Ohm termination
139 // Output Drive Strength Values:
140 #define DDR_EMR_ODS_FULL 0x0 // DDR2 Full Drive Strength
141 #define DDR_EMR_ODS_HALF 0x1 // DDR2 Half Drive Strength
143 #define DDR_EMR_OCD_DEFAULT 0x7
144 #define DDR_EMR_OCD_NS 0x0
146 #define DDR_EMR_ODS_VAL DDR_EMR_ODS_FULL
150 #define DmcWriteReg(reg,val) MmioWrite32(DmcBase + reg, val)
151 #define DmcReadReg(reg) MmioRead32(DmcBase + reg)
153 // Initialize PL341 Dynamic Memory Controller
154 VOID
PL341DmcInit(struct pl341_dmc_config
*config
) {
155 UINTN DmcBase
= config
->base
;
156 UINT32 i
, chip
, val32
;
159 DmcWriteReg(DMC_COMMAND_REG
, DMC_COMMAND_CONFIGURE
);
162 // Setup the QoS AXI ID bits
165 if (config
->has_qos
) {
167 DmcWriteReg(DMC_ID_0_CFG_REG
, DMC_ID_CFG_QOS_ENABLE
| DMC_ID_CFG_QOS_MIN
);
169 // Default disable QoS
170 DmcWriteReg(DMC_ID_1_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
171 DmcWriteReg(DMC_ID_2_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
172 DmcWriteReg(DMC_ID_3_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
173 DmcWriteReg(DMC_ID_4_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
174 DmcWriteReg(DMC_ID_5_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
175 DmcWriteReg(DMC_ID_6_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
176 DmcWriteReg(DMC_ID_7_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
177 DmcWriteReg(DMC_ID_8_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
178 DmcWriteReg(DMC_ID_9_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
179 DmcWriteReg(DMC_ID_10_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
180 DmcWriteReg(DMC_ID_11_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
181 DmcWriteReg(DMC_ID_12_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
182 DmcWriteReg(DMC_ID_13_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
183 DmcWriteReg(DMC_ID_14_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
184 DmcWriteReg(DMC_ID_15_CFG_REG
, DMC_ID_CFG_QOS_DISABLE
);
188 // Initialise memory controlller
190 DmcWriteReg(DMC_REFRESH_PRD_REG
, config
->refresh_prd
);
191 DmcWriteReg(DMC_CAS_LATENCY_REG
, config
->cas_latency
);
192 DmcWriteReg(DMC_WRITE_LATENCY_REG
, config
->write_latency
);
193 DmcWriteReg(DMC_T_MRD_REG
, config
->t_mrd
);
194 DmcWriteReg(DMC_T_RAS_REG
, config
->t_ras
);
195 DmcWriteReg(DMC_T_RC_REG
, config
->t_rc
);
196 DmcWriteReg(DMC_T_RCD_REG
, config
->t_rcd
);
197 DmcWriteReg(DMC_T_RFC_REG
, config
->t_rfc
);
198 DmcWriteReg(DMC_T_RP_REG
, config
->t_rp
);
199 DmcWriteReg(DMC_T_RRD_REG
, config
->t_rrd
);
200 DmcWriteReg(DMC_T_WR_REG
, config
->t_wr
);
201 DmcWriteReg(DMC_T_WTR_REG
, config
->t_wtr
);
202 DmcWriteReg(DMC_T_XP_REG
, config
->t_xp
);
203 DmcWriteReg(DMC_T_XSR_REG
, config
->t_xsr
);
204 DmcWriteReg(DMC_T_ESR_REG
, config
->t_esr
);
205 DmcWriteReg(DMC_T_FAW_REG
, config
->t_faw
);
207 // =======================================================================
208 // Initialise PL341 Mem Config Registers
209 // =======================================================================
211 // |======================================
212 // | Set PL341 Memory Config
213 // |======================================
214 DmcWriteReg(DMC_MEMORY_CONFIG_REG
, config
->memory_cfg
);
216 // |======================================
217 // | Set PL341 Memory Config 2
218 // |======================================
219 DmcWriteReg(DMC_MEMORY_CFG2_REG
, config
->memory_cfg2
);
221 // |======================================
222 // | Set PL341 Chip Select <n>
223 // |======================================
224 DmcWriteReg(DMC_CHIP_0_CFG_REG
, config
->chip_cfg0
);
225 DmcWriteReg(DMC_CHIP_1_CFG_REG
, config
->chip_cfg1
);
226 DmcWriteReg(DMC_CHIP_2_CFG_REG
, config
->chip_cfg2
);
227 DmcWriteReg(DMC_CHIP_3_CFG_REG
, config
->chip_cfg3
);
229 // |======================================
230 // | Set PL341 Memory Config 3
231 // |======================================
232 DmcWriteReg(DMC_MEMORY_CFG3_REG
, config
->memory_cfg3
);
234 // |========================================================
235 // |Set Test Chip PHY Registers via PL341 User Config Reg
236 // |Note that user_cfgX registers are Write Only
238 // |DLL Freq set = 250MHz - 266MHz
239 // |========================================================
240 DmcWriteReg(DMC_USER_0_CFG_REG
, 0x7C924924);
244 // Set defaults before calibrating the DDR2 buffer impendence
246 // -Default drive strengths
247 DmcWriteReg(DMC_USER_2_CFG_REG
, 0x40000198);
249 // |=======================================================
250 // |Auto calibrate the DDR2 buffers impendence
251 // |=======================================================
252 val32
= DmcReadReg(DMC_USER_STATUS_REG
);
253 while (!(val32
& 0x100)) {
254 val32
= DmcReadReg(DMC_USER_STATUS_REG
);
257 // Set the output driven strength
258 DmcWriteReg(DMC_USER_2_CFG_REG
, 0x40800000 |
259 (TC_UIOLHXC_VALUE
<< TC_UIOLHNC_SHIFT
) |
260 (TC_UIOLHXC_VALUE
<< TC_UIOLHPC_SHIFT
) |
261 (0x1 << TC_UIOHOCT_SHIFT
) |
262 (0x1 << TC_UIOHSTOP_SHIFT
));
264 // |======================================
265 // | Set PL341 Feature Control Register
266 // |======================================
267 // | Disable early BRESP - use to optimise CLCD performance
268 DmcWriteReg(DMC_FEATURE_CRTL_REG
, 0x00000001);
274 for (chip
= 0; chip
<= config
-> max_chip
; chip
++) {
276 DmcWriteReg(DMC_DIRECT_CMD_REG
, DMC_DIRECT_CMD_CHIP_ADDR(chip
) | DMC_DIRECT_CMD_MEMCMD_NOP
);
278 DmcWriteReg(DMC_DIRECT_CMD_REG
, DMC_DIRECT_CMD_CHIP_ADDR(chip
) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL
);
281 for (i
= 0; i
< 10; i
++) {
282 val32
= DmcReadReg(DMC_STATUS_REG
);
285 // set (EMR2) extended mode register 2
286 DmcWriteReg(DMC_DIRECT_CMD_REG
,
287 DMC_DIRECT_CMD_CHIP_ADDR(chip
) |
288 DMC_DIRECT_CMD_BANKADDR(2) |
289 DMC_DIRECT_CMD_MEMCMD_EXTMODEREG
);
290 // set (EMR3) extended mode register 3
291 DmcWriteReg(DMC_DIRECT_CMD_REG
,
292 DMC_DIRECT_CMD_CHIP_ADDR(chip
) |
293 DMC_DIRECT_CMD_BANKADDR(3) |
294 DMC_DIRECT_CMD_MEMCMD_EXTMODEREG
);
296 // =================================
297 // set (EMR) Extended Mode Register
298 // ==================================
299 // Put into OCD default state
300 DmcWriteReg(DMC_DIRECT_CMD_REG
,
301 DMC_DIRECT_CMD_CHIP_ADDR(chip
) |
302 DMC_DIRECT_CMD_BANKADDR(1) |
303 DMC_DIRECT_CMD_MEMCMD_EXTMODEREG
);
305 // ===========================================================
306 // set (MR) mode register - With DLL reset
307 // ===========================================================
308 // Burst Length = 4 (010)
309 // Burst Type = Seq (0)
311 // Test mode = Off (0)
312 // DLL reset = Yes (1)
313 // Wr Recovery = 4 (011)
315 DmcWriteReg(DMC_DIRECT_CMD_REG
, DMC_DIRECT_CMD_CHIP_ADDR(chip
) | 0x00080742);
318 DmcWriteReg(DMC_DIRECT_CMD_REG
, DMC_DIRECT_CMD_CHIP_ADDR(chip
) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL
);
320 DmcWriteReg(DMC_DIRECT_CMD_REG
, DMC_DIRECT_CMD_CHIP_ADDR(chip
) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH
);
322 DmcWriteReg(DMC_DIRECT_CMD_REG
, DMC_DIRECT_CMD_CHIP_ADDR(chip
) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH
);
325 for (i
= 0; i
< 10; i
++) {
326 val32
= DmcReadReg(DMC_STATUS_REG
);
329 // ===========================================================
330 // set (MR) mode register - Without DLL reset
331 // ===========================================================
333 DmcWriteReg(DMC_DIRECT_CMD_REG
, DMC_DIRECT_CMD_CHIP_ADDR(chip
) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH
);
334 DmcWriteReg(DMC_DIRECT_CMD_REG
, DMC_DIRECT_CMD_CHIP_ADDR(chip
) | 0x00080642);
337 for (i
= 0; i
< 10; i
++) {
338 val32
= DmcReadReg(DMC_STATUS_REG
);
341 // ======================================================
342 // set (EMR) extended mode register - Enable OCD defaults
343 // ======================================================
345 DmcWriteReg(DMC_DIRECT_CMD_REG
, DMC_DIRECT_CMD_CHIP_ADDR(chip
) | 0x00090000 |
346 (DDR_EMR_OCD_DEFAULT
<< DDR_EMR_OCD_SHIFT
) |
348 (DDR_EMR_ODS_VAL
<< DDR_EMR_ODS_MASK
));
351 for (i
= 0; i
< 10; i
++) {
352 val32
= DmcReadReg(DMC_STATUS_REG
);
355 // Set (EMR) extended mode register - OCD Exit
357 DmcWriteReg(DMC_DIRECT_CMD_REG
, DMC_DIRECT_CMD_CHIP_ADDR(chip
) | 0x00090000 |
358 (DDR_EMR_OCD_NS
<< DDR_EMR_OCD_SHIFT
) |
360 (DDR_EMR_ODS_VAL
<< DDR_EMR_ODS_MASK
));
364 //----------------------------------------
366 DmcWriteReg(DMC_COMMAND_REG
, DMC_COMMAND_GO
);
369 val32
= DmcReadReg(DMC_STATUS_REG
);
370 while (!(val32
& DMC_STATUS_READY
)) {
371 val32
= DmcReadReg(DMC_STATUS_REG
);