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