563221a117c3880eec0cb2529890272bf32111d5
[litex.git] / software / bios / ddrinit.c
1 /*
2 * Milkymist SoC (Software)
3 * Copyright (C) 2012 Sebastien Bourdeauducq
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20
21 #include <hw/dfii.h>
22
23 #include "ddrinit.h"
24
25 static void cdelay(int i)
26 {
27 while(i > 0) {
28 __asm__ volatile("nop");
29 i--;
30 }
31 }
32
33 static void setaddr(int a)
34 {
35 CSR_DFII_AH_P0 = (a & 0x1fe0) >> 5;
36 CSR_DFII_AL_P0 = a & 0x001f;
37 CSR_DFII_AH_P1 = (a & 0x1fe0) >> 5;
38 CSR_DFII_AL_P1 = a & 0x001f;
39 }
40
41 static void init_sequence(void)
42 {
43 int i;
44
45 printf("Sending initialization sequence...\n");
46
47 /* Bring CKE high */
48 setaddr(0x0000);
49 CSR_DFII_BA_P0 = 0;
50 CSR_DFII_CONTROL = DFII_CONTROL_CKE;
51
52 /* Precharge All */
53 setaddr(0x0400);
54 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
55
56 /* Load Extended Mode Register */
57 CSR_DFII_BA_P0 = 1;
58 setaddr(0x0000);
59 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
60 CSR_DFII_BA_P0 = 0;
61
62 /* Load Mode Register */
63 setaddr(0x0132); /* Reset DLL, CL=3, BL=4 */
64 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
65 cdelay(200);
66
67 /* Precharge All */
68 setaddr(0x0400);
69 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
70
71 /* 2x Auto Refresh */
72 for(i=0;i<2;i++) {
73 setaddr(0);
74 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS;
75 cdelay(4);
76 }
77
78 /* Load Mode Register */
79 setaddr(0x0032); /* CL=3, BL=4 */
80 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
81 cdelay(200);
82 }
83
84 void ddrrd(char *startaddr)
85 {
86 char *c;
87 unsigned int addr;
88 int i;
89
90 if(*startaddr == 0) {
91 printf("ddrrd <address>\n");
92 return;
93 }
94 addr = strtoul(startaddr, &c, 0);
95 if(*c != 0) {
96 printf("incorrect address\n");
97 return;
98 }
99
100 setaddr(addr);
101 CSR_DFII_BA_P0 = 0;
102 CSR_DFII_COMMAND_P0 = DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA;
103 cdelay(15);
104
105 for(i=0;i<8;i++)
106 printf("%02x", MMPTR(0xe0000834+4*i));
107 for(i=0;i<8;i++)
108 printf("%02x", MMPTR(0xe0000884+4*i));
109 printf("\n");
110 }
111
112 void ddrwr(char *startaddr)
113 {
114 char *c;
115 unsigned int addr;
116 int i;
117
118 if(*startaddr == 0) {
119 printf("ddrrd <address>\n");
120 return;
121 }
122 addr = strtoul(startaddr, &c, 0);
123 if(*c != 0) {
124 printf("incorrect address\n");
125 return;
126 }
127
128 for(i=0;i<8;i++) {
129 MMPTR(0xe0000814+4*i) = i;
130 MMPTR(0xe0000864+4*i) = 0xf0 + i;
131 }
132
133 setaddr(addr);
134 CSR_DFII_BA_P1 = 0;
135 CSR_DFII_COMMAND_P1 = DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA;
136 }
137
138 int ddrinit(void)
139 {
140 printf("Initializing DDR SDRAM...\n");
141
142 init_sequence();
143
144 setaddr(0x0000);
145 CSR_DFII_BA_P0 = 0;
146 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CS;
147 cdelay(15);
148
149 return 1;
150 }