]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/bf537-stamp/post-memory.c
[Blackfin][PATCH] Add BF537 stamp board support
[karo-tx-uboot.git] / board / bf537-stamp / post-memory.c
1 #include <common.h>
2 #include <asm/io.h>
3
4 #ifdef CONFIG_POST
5
6 #include <post.h>
7 #include <watchdog.h>
8
9 #if CONFIG_POST & CFG_POST_MEMORY
10 #define CLKIN 25000000
11 #define PATTERN1 0x5A5A5A5A
12 #define PATTERN2 0xAAAAAAAA
13
14 #define CCLK_NUM        4
15 #define SCLK_NUM        3
16
17 void post_out_buff(char *buff);
18 int post_key_pressed(void);
19 void post_init_pll(int mult, int div);
20 int post_init_sdram(int sclk);
21 void post_init_uart(int sclk);
22
23 const int pll[CCLK_NUM][SCLK_NUM][2] = {
24         {{20, 4}, {20, 5}, {20, 10}},   /* CCLK = 500M */
25         {{16, 4}, {16, 5}, {16, 8}},    /* CCLK = 400M */
26         {{8, 2}, {8, 4}, {8, 5}},       /* CCLK = 200M */
27         {{4, 1}, {4, 2}, {4, 4}}        /* CCLK = 100M */
28 };
29 const char *const log[CCLK_NUM][SCLK_NUM] = {
30         {"CCLK-500Mhz SCLK-125Mhz:    Writing...\0",
31          "CCLK-500Mhz SCLK-100Mhz:    Writing...\0",
32          "CCLK-500Mhz SCLK- 50Mhz:    Writing...\0",},
33         {"CCLK-400Mhz SCLK-100Mhz:    Writing...\0",
34          "CCLK-400Mhz SCLK- 80Mhz:    Writing...\0",
35          "CCLK-400Mhz SCLK- 50Mhz:    Writing...\0",},
36         {"CCLK-200Mhz SCLK-100Mhz:    Writing...\0",
37          "CCLK-200Mhz SCLK- 50Mhz:    Writing...\0",
38          "CCLK-200Mhz SCLK- 40Mhz:    Writing...\0",},
39         {"CCLK-100Mhz SCLK-100Mhz:    Writing...\0",
40          "CCLK-100Mhz SCLK- 50Mhz:    Writing...\0",
41          "CCLK-100Mhz SCLK- 25Mhz:    Writing...\0",},
42 };
43
44 int memory_post_test(int flags)
45 {
46         int addr;
47         int m, n;
48         int sclk, sclk_temp;
49         int ret = 1;
50
51         sclk_temp = CLKIN / 1000000;
52         sclk_temp = sclk_temp * CONFIG_VCO_MULT;
53         for (sclk = 0; sclk_temp > 0; sclk++)
54                 sclk_temp -= CONFIG_SCLK_DIV;
55         sclk = sclk * 1000000;
56         post_init_uart(sclk);
57         if (post_key_pressed() == 0)
58                 return 0;
59
60         for (m = 0; m < CCLK_NUM; m++) {
61                 for (n = 0; n < SCLK_NUM; n++) {
62                         /* Calculate the sclk */
63                         sclk_temp = CLKIN / 1000000;
64                         sclk_temp = sclk_temp * pll[m][n][0];
65                         for (sclk = 0; sclk_temp > 0; sclk++)
66                                 sclk_temp -= pll[m][n][1];
67                         sclk = sclk * 1000000;
68
69                         post_init_pll(pll[m][n][0], pll[m][n][1]);
70                         post_init_sdram(sclk);
71                         post_init_uart(sclk);
72                         post_out_buff("\n\r\0");
73                         post_out_buff(log[m][n]);
74                         for (addr = 0x0; addr < CFG_MAX_RAM_SIZE; addr += 4)
75                                 *(unsigned long *)addr = PATTERN1;
76                         post_out_buff("Reading...\0");
77                         for (addr = 0x0; addr < CFG_MAX_RAM_SIZE; addr += 4) {
78                                 if ((*(unsigned long *)addr) != PATTERN1) {
79                                         post_out_buff("Error\n\r\0");
80                                         ret = 0;
81                                 }
82                         }
83                         post_out_buff("OK\n\r\0");
84                 }
85         }
86         if (ret)
87                 post_out_buff("memory POST passed\n\r\0");
88         else
89                 post_out_buff("memory POST failed\n\r\0");
90
91         post_out_buff("\n\r\n\r\0");
92         return 1;
93 }
94
95 void post_init_uart(int sclk)
96 {
97         int divisor;
98
99         for (divisor = 0; sclk > 0; divisor++)
100                 sclk -= 57600 * 16;
101
102         *pPORTF_FER = 0x000F;
103         *pPORTH_FER = 0xFFFF;
104
105         *pUART_GCTL = 0x00;
106         *pUART_LCR = 0x83;
107         sync();
108         *pUART_DLL = (divisor & 0xFF);
109         sync();
110         *pUART_DLH = ((divisor >> 8) & 0xFF);
111         sync();
112         *pUART_LCR = 0x03;
113         sync();
114         *pUART_GCTL = 0x01;
115         sync();
116 }
117
118 void post_out_buff(char *buff)
119 {
120
121         int i = 0;
122         for (i = 0; i < 0x80000; i++) ;
123         i = 0;
124         while ((buff[i] != '\0') && (i != 100)) {
125                 while (!(*pUART_LSR & 0x20)) ;
126                 *pUART_THR = buff[i];
127                 sync();
128                 i++;
129         }
130         for (i = 0; i < 0x80000; i++) ;
131 }
132
133 /* Using sw10-PF5 as the hotkey */
134 #define KEY_LOOP 0x80000
135 #define KEY_DELAY 0x80
136 int post_key_pressed(void)
137 {
138         int i, n;
139         unsigned short value;
140
141         *pPORTF_FER &= ~PF5;
142         *pPORTFIO_DIR &= ~PF5;
143         *pPORTFIO_INEN |= PF5;
144         sync();
145
146         post_out_buff("########Press SW10 to enter Memory POST########: 3\0");
147         for (i = 0; i < KEY_LOOP; i++) {
148                 value = *pPORTFIO & PF5;
149                 if (*pUART0_RBR == 0x0D) {
150                         value = 0;
151                         goto key_pressed;
152                 }
153                 if (value != 0) {
154                         goto key_pressed;
155                 }
156                 for (n = 0; n < KEY_DELAY; n++)
157                         asm("nop");
158         }
159         post_out_buff("\b2\0");
160
161         for (i = 0; i < KEY_LOOP; i++) {
162                 value = *pPORTFIO & PF5;
163                 if (*pUART0_RBR == 0x0D) {
164                         value = 0;
165                         goto key_pressed;
166                 }
167                 if (value != 0) {
168                         goto key_pressed;
169                 }
170                 for (n = 0; n < KEY_DELAY; n++)
171                         asm("nop");
172         }
173         post_out_buff("\b1\0");
174
175         for (i = 0; i < KEY_LOOP; i++) {
176                 value = *pPORTFIO & PF5;
177                 if (*pUART0_RBR == 0x0D) {
178                         value = 0;
179                         goto key_pressed;
180                 }
181                 if (value != 0) {
182                         goto key_pressed;
183                 }
184                 for (n = 0; n < KEY_DELAY; n++)
185                         asm("nop");
186         }
187       key_pressed:
188         post_out_buff("\b0");
189         post_out_buff("\n\r\0");
190         if (value == 0)
191                 return 0;
192         post_out_buff("Hotkey has been pressed, Enter POST . . . . . .\n\r\0");
193         return 1;
194 }
195
196 void post_init_pll(int mult, int div)
197 {
198
199         *pSIC_IWR = 0x01;
200         *pPLL_CTL = (mult << 9);
201         *pPLL_DIV = div;
202         asm("CLI R2;");
203         asm("IDLE;");
204         asm("STI R2;");
205         while (!(*pPLL_STAT & 0x20)) ;
206 }
207
208 int post_init_sdram(int sclk)
209 {
210         int SDRAM_tRP, SDRAM_tRP_num, SDRAM_tRAS, SDRAM_tRAS_num, SDRAM_tRCD,
211             SDRAM_tWR;
212         int SDRAM_Tref, SDRAM_NRA, SDRAM_CL, SDRAM_SIZE, SDRAM_WIDTH,
213             mem_SDGCTL, mem_SDBCTL, mem_SDRRC;
214
215         if ((sclk > 119402985)) {
216                 SDRAM_tRP = TRP_2;
217                 SDRAM_tRP_num = 2;
218                 SDRAM_tRAS = TRAS_7;
219                 SDRAM_tRAS_num = 7;
220                 SDRAM_tRCD = TRCD_2;
221                 SDRAM_tWR = TWR_2;
222         } else if ((sclk > 104477612) && (sclk <= 119402985)) {
223                 SDRAM_tRP = TRP_2;
224                 SDRAM_tRP_num = 2;
225                 SDRAM_tRAS = TRAS_6;
226                 SDRAM_tRAS_num = 6;
227                 SDRAM_tRCD = TRCD_2;
228                 SDRAM_tWR = TWR_2;
229         } else if ((sclk > 89552239) && (sclk <= 104477612)) {
230                 SDRAM_tRP = TRP_2;
231                 SDRAM_tRP_num = 2;
232                 SDRAM_tRAS = TRAS_5;
233                 SDRAM_tRAS_num = 5;
234                 SDRAM_tRCD = TRCD_2;
235                 SDRAM_tWR = TWR_2;
236         } else if ((sclk > 74626866) && (sclk <= 89552239)) {
237                 SDRAM_tRP = TRP_2;
238                 SDRAM_tRP_num = 2;
239                 SDRAM_tRAS = TRAS_4;
240                 SDRAM_tRAS_num = 4;
241                 SDRAM_tRCD = TRCD_2;
242                 SDRAM_tWR = TWR_2;
243         } else if ((sclk > 66666667) && (sclk <= 74626866)) {
244                 SDRAM_tRP = TRP_2;
245                 SDRAM_tRP_num = 2;
246                 SDRAM_tRAS = TRAS_3;
247                 SDRAM_tRAS_num = 3;
248                 SDRAM_tRCD = TRCD_2;
249                 SDRAM_tWR = TWR_2;
250         } else if ((sclk > 59701493) && (sclk <= 66666667)) {
251                 SDRAM_tRP = TRP_1;
252                 SDRAM_tRP_num = 1;
253                 SDRAM_tRAS = TRAS_4;
254                 SDRAM_tRAS_num = 4;
255                 SDRAM_tRCD = TRCD_1;
256                 SDRAM_tWR = TWR_2;
257         } else if ((sclk > 44776119) && (sclk <= 59701493)) {
258                 SDRAM_tRP = TRP_1;
259                 SDRAM_tRP_num = 1;
260                 SDRAM_tRAS = TRAS_3;
261                 SDRAM_tRAS_num = 3;
262                 SDRAM_tRCD = TRCD_1;
263                 SDRAM_tWR = TWR_2;
264         } else if ((sclk > 29850746) && (sclk <= 44776119)) {
265                 SDRAM_tRP = TRP_1;
266                 SDRAM_tRP_num = 1;
267                 SDRAM_tRAS = TRAS_2;
268                 SDRAM_tRAS_num = 2;
269                 SDRAM_tRCD = TRCD_1;
270                 SDRAM_tWR = TWR_2;
271         } else if (sclk <= 29850746) {
272                 SDRAM_tRP = TRP_1;
273                 SDRAM_tRP_num = 1;
274                 SDRAM_tRAS = TRAS_1;
275                 SDRAM_tRAS_num = 1;
276                 SDRAM_tRCD = TRCD_1;
277                 SDRAM_tWR = TWR_2;
278         } else {
279                 SDRAM_tRP = TRP_1;
280                 SDRAM_tRP_num = 1;
281                 SDRAM_tRAS = TRAS_1;
282                 SDRAM_tRAS_num = 1;
283                 SDRAM_tRCD = TRCD_1;
284                 SDRAM_tWR = TWR_2;
285         }
286         /*SDRAM INFORMATION: */
287         SDRAM_Tref = 64;        /* Refresh period in milliseconds */
288         SDRAM_NRA = 4096;       /* Number of row addresses in SDRAM */
289         SDRAM_CL = CL_3;        /* 2 */
290
291         SDRAM_SIZE = EBSZ_64;
292         SDRAM_WIDTH = EBCAW_10;
293
294         mem_SDBCTL = SDRAM_WIDTH | SDRAM_SIZE | EBE;
295
296         /* Equation from section 17 (p17-46) of BF533 HRM */
297         mem_SDRRC =
298             (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) -
299             (SDRAM_tRAS_num + SDRAM_tRP_num);
300
301         /* Enable SCLK Out */
302         mem_SDGCTL =
303             (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR
304              | PSS);
305
306         sync();
307
308         *pEBIU_SDGCTL |= 0x1000000;
309         /* Set the SDRAM Refresh Rate control register based on SSCLK value */
310         *pEBIU_SDRRC = mem_SDRRC;
311
312         /* SDRAM Memory Bank Control Register */
313         *pEBIU_SDBCTL = mem_SDBCTL;
314
315         /* SDRAM Memory Global Control Register */
316         *pEBIU_SDGCTL = mem_SDGCTL;
317         sync();
318         return mem_SDRRC;
319 }
320
321 #endif                          /* CONFIG_POST & CFG_POST_MEMORY */
322 #endif                          /* CONFIG_POST */