]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Drivers/PL34xDmc/PL341Dmc.c
Remove tabs from all text files in the package.
[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
58b5d037 67#define DMC_DIRECT_CMD_CHIP_ADDR(n)\s\s\s\s((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
58b5d037 166\s\s// CLCD AXIID = 000\r
167\s\sDmcWriteReg(DMC_ID_0_CFG_REG, DMC_ID_CFG_QOS_ENABLE | DMC_ID_CFG_QOS_MIN);\r
168\r
169\s\s// Default disable QoS\r
170\s\sDmcWriteReg(DMC_ID_1_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
171\s\sDmcWriteReg(DMC_ID_2_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
172\s\sDmcWriteReg(DMC_ID_3_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
173\s\sDmcWriteReg(DMC_ID_4_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
174\s\sDmcWriteReg(DMC_ID_5_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
175\s\sDmcWriteReg(DMC_ID_6_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
176\s\sDmcWriteReg(DMC_ID_7_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
177\s\sDmcWriteReg(DMC_ID_8_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
178\s\sDmcWriteReg(DMC_ID_9_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
179\s\sDmcWriteReg(DMC_ID_10_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
180\s\sDmcWriteReg(DMC_ID_11_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
181\s\sDmcWriteReg(DMC_ID_12_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
182\s\sDmcWriteReg(DMC_ID_13_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
183\s\sDmcWriteReg(DMC_ID_14_CFG_REG, DMC_ID_CFG_QOS_DISABLE);\r
184\s\sDmcWriteReg(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
58b5d037 234\s\s// |========================================================\r
235\s\s// |Set Test Chip PHY Registers via PL341 User Config Reg\r
236\s\s// |Note that user_cfgX registers are Write Only\r
237\s\s// |\r
238\s\s// |DLL Freq set = 250MHz - 266MHz\r
239\s\s// |======================================================== \r
240\s\sDmcWriteReg(DMC_USER_0_CFG_REG, 0x7C924924);\r
1bfda055 241 \r
58b5d037 242\s\s// user_config2\r
243\s\s// ------------\r
244\s\s// Set defaults before calibrating the DDR2 buffer impendence\r
245\s\s// -Disable ODT\r
246\s\s// -Default drive strengths\r
247\s\sDmcWriteReg(DMC_USER_2_CFG_REG, 0x40000198);\r
1bfda055 248 \r
58b5d037 249\s\s// |=======================================================\r
250\s\s// |Auto calibrate the DDR2 buffers impendence \r
251\s\s// |=======================================================\r
252\s\sval32 = DmcReadReg(DMC_USER_STATUS_REG);\r
253\s\swhile (!(val32 & 0x100)) {\r
254\s\s val32 = DmcReadReg(DMC_USER_STATUS_REG);\r
255\s\s}\r
256\r
257\s\s// Set the output driven strength\r
258\s\sDmcWriteReg(DMC_USER_2_CFG_REG, 0x40800000 | \r
259\s\s\s\s (TC_UIOLHXC_VALUE << TC_UIOLHNC_SHIFT) | \r
260\s\s\s\s (TC_UIOLHXC_VALUE << TC_UIOLHPC_SHIFT) |\r
261\s\s\s\s (0x1 << TC_UIOHOCT_SHIFT) | \r
262\s\s\s\s (0x1 << TC_UIOHSTOP_SHIFT));\r
263\r
264\s\s// |======================================\r
265\s\s// | Set PL341 Feature Control Register \r
266\s\s// |======================================\r
267\s\s// | Disable early BRESP - use to optimise CLCD performance\r
268\s\sDmcWriteReg(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
58b5d037 275\s\s// send nop\r
276\s\sDmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_NOP);\r
277\s\s// pre-charge all\r
278\s\sDmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL);\r
279\r
280\s\s// delay\r
281\s\sfor (i = 0; i < 10; i++) {\r
282\s\s val32 = DmcReadReg(DMC_STATUS_REG);\r
283\s\s}\r
284\r
285\s\s// set (EMR2) extended mode register 2\r
286\s\sDmcWriteReg(DMC_DIRECT_CMD_REG, \r
287\s\s\s\s DMC_DIRECT_CMD_CHIP_ADDR(chip) | \r
288\s\s\s\s DMC_DIRECT_CMD_BANKADDR(2) | \r
289\s\s\s\s DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);\r
290\s\s// set (EMR3) extended mode register 3\r
291\s\sDmcWriteReg(DMC_DIRECT_CMD_REG, \r
292\s\s\s\s DMC_DIRECT_CMD_CHIP_ADDR(chip) | \r
293\s\s\s\s DMC_DIRECT_CMD_BANKADDR(3) | \r
294\s\s\s\s DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);\r
295\r
296\s\s// =================================\r
297\s\s// set (EMR) Extended Mode Register\r
298\s\s// ==================================\r
299\s\s// Put into OCD default state\r
300\s\sDmcWriteReg(DMC_DIRECT_CMD_REG, \r
301\s\s\s\s DMC_DIRECT_CMD_CHIP_ADDR(chip) | \r
302\s\s\s\s DMC_DIRECT_CMD_BANKADDR(1) | \r
303\s\s\s\s DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);\r
304\r
305\s\s// =========================================================== \r
306\s\s// set (MR) mode register - With DLL reset\r
307\s\s// ===========================================================\r
308\s\s// Burst Length = 4 (010)\r
309\s\s// Burst Type = Seq (0)\r
310\s\s// Latency = 4 (100)\r
311\s\s// Test mode = Off (0)\r
312\s\s// DLL reset = Yes (1)\r
313\s\s// Wr Recovery = 4 (011) \r
314\s\s// PD = Normal (0)\r
1bfda055 315 DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00080742);\r
316 \r
58b5d037 317\s\s// pre-charge all \r
318\s\sDmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL);\r
319\s\s// auto-refresh \r
320\s\sDmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH);\r
321\s\s// auto-refresh \r
322\s\sDmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH);\r
323\r
324\s\s// delay\r
325\s\sfor (i = 0; i < 10; i++) {\r
326\s\s val32 = DmcReadReg(DMC_STATUS_REG);\r
327\s\s}\r
328\r
329\s\s// =========================================================== \r
330\s\s// set (MR) mode register - Without DLL reset\r
331\s\s// ===========================================================\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
58b5d037 341\s\s// ====================================================== \r
342\s\s// set (EMR) extended mode register - Enable OCD defaults\r
343\s\s// ====================================================== \r
344\s\sval32 = 0; //NOP\r
345\s\sDmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00090000 |\r
346\s\s\s\s (DDR_EMR_OCD_DEFAULT << DDR_EMR_OCD_SHIFT) | \r
347\s\s\s\s DDR_EMR_RTT_75R | \r
348\s\s\s\s (DDR_EMR_ODS_VAL << DDR_EMR_ODS_MASK));\r
349\r
350\s\s// delay\r
351\s\sfor (i = 0; i < 10; i++) {\r
352\s\s val32 = DmcReadReg(DMC_STATUS_REG);\r
353\s\s}\r
354\r
355\s\s// Set (EMR) extended mode register - OCD Exit\r
356\s\sval32 = 0; //NOP\r
357\s\sDmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00090000 | \r
358\s\s\s\s (DDR_EMR_OCD_NS << DDR_EMR_OCD_SHIFT) | \r
359\s\s\s\s DDR_EMR_RTT_75R |\r
360\s\s\s\s (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