]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/a4m072/a4m072.c
driver/serial: delete at91rm9200_usart
[karo-tx-uboot.git] / board / a4m072 / a4m072.c
1 /*
2  * (C) Copyright 2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * (C) Copyright 2004
6  * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
7  *
8  * (C) Copyright 2010
9  * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
10  *
11  * See file CREDITS for list of people who contributed to this
12  * project.
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License as
16  * published by the Free Software Foundation; either version 2 of
17  * the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27  * MA 02111-1307 USA
28  */
29
30 #include <common.h>
31 #include <mpc5xxx.h>
32 #include <pci.h>
33 #include <asm/processor.h>
34 #include <asm/io.h>
35 #include <libfdt.h>
36 #include <netdev.h>
37 #include <led-display.h>
38 #include <linux/err.h>
39
40 #include "mt46v32m16.h"
41
42 #ifndef CONFIG_SYS_RAMBOOT
43 static void sdram_start (int hi_addr)
44 {
45         long hi_addr_bit = hi_addr ? 0x01000000 : 0;
46         long control = SDRAM_CONTROL | hi_addr_bit;
47
48         /* unlock mode register */
49         out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000000);
50         __asm__ volatile ("sync");
51
52         /* precharge all banks */
53         out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000002);
54         __asm__ volatile ("sync");
55
56 #if SDRAM_DDR
57         /* set mode register: extended mode */
58         out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_EMODE);
59         __asm__ volatile ("sync");
60
61         /* set mode register: reset DLL */
62         out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_MODE | 0x04000000);
63         __asm__ volatile ("sync");
64 #endif
65
66         /* precharge all banks */
67         out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000002);
68         __asm__ volatile ("sync");
69
70         /* auto refresh */
71         out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000004);
72         __asm__ volatile ("sync");
73
74         /* set mode register */
75         out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_MODE);
76         __asm__ volatile ("sync");
77
78         /* normal operation */
79         out_be32((void *)MPC5XXX_SDRAM_CTRL, control);
80         __asm__ volatile ("sync");
81 }
82 #endif
83
84 /*
85  * ATTENTION: Although partially referenced initdram does NOT make real use
86  *            use of CONFIG_SYS_SDRAM_BASE. The code does not work if CONFIG_SYS_SDRAM_BASE
87  *            is something else than 0x00000000.
88  */
89
90 phys_size_t initdram (int board_type)
91 {
92         ulong dramsize = 0;
93         uint svr, pvr;
94
95 #ifndef CONFIG_SYS_RAMBOOT
96         ulong test1, test2;
97
98         /* setup SDRAM chip selects */
99         out_be32((void *)MPC5XXX_SDRAM_CS0CFG, 0x0000001e); /* 2GB at 0x0 */
100         out_be32((void *)MPC5XXX_SDRAM_CS1CFG, 0x80000000); /* disabled */
101         __asm__ volatile ("sync");
102
103         /* setup config registers */
104         out_be32((void *)MPC5XXX_SDRAM_CONFIG1, SDRAM_CONFIG1);
105         out_be32((void *)MPC5XXX_SDRAM_CONFIG2, SDRAM_CONFIG2);
106         __asm__ volatile ("sync");
107
108 #if SDRAM_DDR
109         /* set tap delay */
110         out_be32((void *)MPC5XXX_CDM_PORCFG, SDRAM_TAPDELAY);
111         __asm__ volatile ("sync");
112 #endif
113
114         /* find RAM size using SDRAM CS0 only */
115         sdram_start(0);
116         test1 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
117         sdram_start(1);
118         test2 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
119         if (test1 > test2) {
120                 sdram_start(0);
121                 dramsize = test1;
122         } else {
123                 dramsize = test2;
124         }
125
126         /* memory smaller than 1MB is impossible */
127         if (dramsize < (1 << 20)) {
128                 dramsize = 0;
129         }
130
131         /* set SDRAM CS0 size according to the amount of RAM found */
132         if (dramsize > 0) {
133                 out_be32((void *)MPC5XXX_SDRAM_CS0CFG,
134                                  0x13 + __builtin_ffs(dramsize >> 20) - 1);
135         } else {
136                 out_be32((void *)MPC5XXX_SDRAM_CS0CFG, 0); /* disabled */
137         }
138
139 #else /* CONFIG_SYS_RAMBOOT */
140
141         /* retrieve size of memory connected to SDRAM CS0 */
142         dramsize = in_be32((void *)MPC5XXX_SDRAM_CS0CFG) & 0xFF;
143         if (dramsize >= 0x13) {
144                 dramsize = (1 << (dramsize - 0x13)) << 20;
145         } else {
146                 dramsize = 0;
147         }
148
149 #endif /* CONFIG_SYS_RAMBOOT */
150
151         /*
152          * On MPC5200B we need to set the special configuration delay in the
153          * DDR controller. Please refer to Freescale's AN3221 "MPC5200B SDRAM
154          * Initialization and Configuration", 3.3.1 SDelay--MBAR + 0x0190:
155          *
156          * "The SDelay should be written to a value of 0x00000004. It is
157          * required to account for changes caused by normal wafer processing
158          * parameters."
159          */
160         svr = get_svr();
161         pvr = get_pvr();
162         if ((SVR_MJREV(svr) >= 2) &&
163             (PVR_MAJ(pvr) == 1) && (PVR_MIN(pvr) == 4)) {
164
165                 out_be32((void *)MPC5XXX_SDRAM_SDELAY, 0x04);
166                 __asm__ volatile ("sync");
167         }
168
169         return dramsize;
170 }
171
172 int checkboard (void)
173 {
174         puts ("Board: A4M072\n");
175         return 0;
176 }
177
178 #ifdef  CONFIG_PCI
179 static struct pci_controller hose;
180
181 extern void pci_mpc5xxx_init(struct pci_controller *);
182
183 void pci_init_board(void)
184 {
185         pci_mpc5xxx_init(&hose);
186 }
187 #endif
188
189 #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
190 void
191 ft_board_setup(void *blob, bd_t *bd)
192 {
193         ft_cpu_setup(blob, bd);
194 }
195 #endif
196
197 int board_eth_init(bd_t *bis)
198 {
199         int rv, num_if = 0;
200
201         /* Initialize TSECs first */
202         if ((rv = cpu_eth_init(bis)) >= 0)
203                 num_if += rv;
204         else
205                 printf("ERROR: failed to initialize FEC.\n");
206
207         if ((rv = pci_eth_init(bis)) >= 0)
208                 num_if += rv;
209         else
210                 printf("ERROR: failed to initialize PCI Ethernet.\n");
211
212         return num_if;
213 }
214 /*
215  * Miscellaneous late-boot configurations
216  *
217  * Initialize EEPROM write-protect GPIO pin.
218  */
219 int misc_init_r(void)
220 {
221 #if defined(CONFIG_SYS_EEPROM_WREN)
222         /* Enable GPIO pin */
223         setbits_be32((void *)MPC5XXX_WU_GPIO_ENABLE, CONFIG_SYS_EEPROM_WP);
224         /* Set direction, output */
225         setbits_be32((void *)MPC5XXX_WU_GPIO_DIR, CONFIG_SYS_EEPROM_WP);
226         /* De-assert write enable */
227         setbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O, CONFIG_SYS_EEPROM_WP);
228 #endif
229         return 0;
230 }
231 #if defined(CONFIG_SYS_EEPROM_WREN)
232 /* Input: <dev_addr>  I2C address of EEPROM device to enable.
233  *         <state>     -1: deliver current state
234  *                     0: disable write
235  *                     1: enable write
236  *  Returns:           -1: wrong device address
237  *                      0: dis-/en- able done
238  *                   0/1: current state if <state> was -1.
239  */
240 int eeprom_write_enable (unsigned dev_addr, int state)
241 {
242         if (CONFIG_SYS_I2C_EEPROM_ADDR != dev_addr) {
243                 return -1;
244         } else {
245                 switch (state) {
246                 case 1:
247                         /* Enable write access */
248                         clrbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O, CONFIG_SYS_EEPROM_WP);
249                         state = 0;
250                         break;
251                 case 0:
252                         /* Disable write access */
253                         setbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O, CONFIG_SYS_EEPROM_WP);
254                         state = 0;
255                         break;
256                 default:
257                         /* Read current status back. */
258                         state = (0 == (in_be32((void *)MPC5XXX_WU_GPIO_DATA_O) &
259                                                    CONFIG_SYS_EEPROM_WP));
260                         break;
261                 }
262         }
263         return state;
264 }
265 #endif
266
267 #ifdef CONFIG_CMD_DISPLAY
268 #define DISPLAY_BUF_SIZE        2
269 static u8 display_buf[DISPLAY_BUF_SIZE];
270 static u8 display_putc_pos;
271 static u8 display_out_pos;
272
273 void display_set(int cmd) {
274
275         if (cmd & DISPLAY_CLEAR) {
276                 display_buf[0] = display_buf[1] = 0;
277         }
278
279         if (cmd & DISPLAY_HOME) {
280                 display_putc_pos = 0;
281         }
282 }
283
284 #define SEG_A    (1<<0)
285 #define SEG_B    (1<<1)
286 #define SEG_C    (1<<2)
287 #define SEG_D    (1<<3)
288 #define SEG_E    (1<<4)
289 #define SEG_F    (1<<5)
290 #define SEG_G    (1<<6)
291 #define SEG_P    (1<<7)
292 #define SEG__    0
293
294 /*
295  * +- A -+
296  * |     |
297  * F     B
298  * |     |
299  * +- G -+
300  * |     |
301  * E     C
302  * |     |
303  * +- D -+  P
304  *
305  * 0..9         index 0..9
306  * A..Z         index 10..35
307  * -            index 36
308  * _            index 37
309  * .            index 38
310  */
311
312 #define SYMBOL_DASH             (36)
313 #define SYMBOL_UNDERLINE        (37)
314 #define SYMBOL_DOT              (38)
315
316 static u8 display_char2seg7_tbl[]=
317 {
318         SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,          /* 0 */
319         SEG_B | SEG_C,                                          /* 1 */
320         SEG_A | SEG_B | SEG_D | SEG_E | SEG_G,                  /* 2 */
321         SEG_A | SEG_B | SEG_C | SEG_D | SEG_G,                  /* 3 */
322         SEG_B | SEG_C | SEG_F | SEG_G,                          /* 4 */
323         SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,                  /* 5 */
324         SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,          /* 6 */
325         SEG_A | SEG_B | SEG_C,                                  /* 7 */
326         SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,  /* 8 */
327         SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,          /* 9 */
328         SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,          /* A */
329         SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,                  /* b */
330         SEG_A | SEG_D | SEG_E | SEG_F,                          /* C */
331         SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,                  /* d */
332         SEG_A | SEG_D | SEG_E | SEG_F | SEG_G,                  /* E */
333         SEG_A | SEG_E | SEG_F | SEG_G,                          /* F */
334         0,                                      /* g - not displayed */
335         SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,                  /* H */
336         SEG_B | SEG_C,                                          /* I */
337         0,                                      /* J - not displayed */
338         0,                                      /* K - not displayed */
339         SEG_D | SEG_E | SEG_F,                                  /* L */
340         0,                                      /* m - not displayed */
341         0,                                      /* n - not displayed */
342         SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,          /* O */
343         SEG_A | SEG_B | SEG_E | SEG_F | SEG_G,                  /* P */
344         0,                                      /* q - not displayed */
345         0,                                      /* r - not displayed */
346         SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,                  /* S */
347         SEG_D | SEG_E | SEG_F | SEG_G,                          /* t */
348         SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,                  /* U */
349         0,                                      /* V - not displayed */
350         0,                                      /* w - not displayed */
351         0,                                      /* X - not displayed */
352         SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,                  /* Y */
353         0,                                      /* Z - not displayed */
354         SEG_G,                                                  /* - */
355         SEG_D,                                                  /* _ */
356         SEG_P                                                   /* . */
357 };
358
359 /* Convert char to the LED segments representation */
360 static u8 display_char2seg7(char c)
361 {
362         u8 val = 0;
363
364         if (c >= '0' && c <= '9')
365                 c -= '0';
366         else if (c >= 'a' && c <= 'z')
367                 c -= 'a' - 10;
368         else if (c >= 'A' && c <= 'Z')
369                 c -= 'A' - 10;
370         else if (c == '-')
371                 c = SYMBOL_DASH;
372         else if (c == '_')
373                 c = SYMBOL_UNDERLINE;
374         else if (c == '.')
375                 c = SYMBOL_DOT;
376         else
377                 c = ' ';        /* display unsupported symbols as space */
378
379         if (c != ' ')
380                 val = display_char2seg7_tbl[(int)c];
381
382         return val;
383 }
384
385 int display_putc(char c)
386 {
387         if (display_putc_pos >= DISPLAY_BUF_SIZE)
388                 return -1;
389
390         display_buf[display_putc_pos++] = display_char2seg7(c);
391         /* one-symbol message should be steady */
392         if (display_putc_pos == 1)
393                 display_buf[display_putc_pos] = display_char2seg7(c);
394
395         return c;
396 }
397
398 /*
399  * Flush current symbol to the LED display hardware
400  */
401 static inline void display_flush(void)
402 {
403         u32 val = display_buf[display_out_pos];
404
405         val |= (val << 8) | (val << 16) | (val << 24);
406         out_be32((void *)CONFIG_SYS_DISP_CHR_RAM, val);
407 }
408
409 /*
410  * Output contents of the software display buffer to the LED display every 0.5s
411  */
412 void board_show_activity(ulong timestamp)
413 {
414         static ulong last;
415         static u8 once;
416
417         if (!once || (timestamp - last >= (CONFIG_SYS_HZ / 2))) {
418                 display_flush();
419                 display_out_pos ^= 1;
420                 last = timestamp;
421                 once = 1;
422         }
423 }
424
425 /*
426  * Empty fake function
427  */
428 void show_activity(int arg)
429 {
430 }
431 #endif
432 #if defined (CONFIG_SHOW_BOOT_PROGRESS)
433 static int a4m072_status2code(int status, char *buf)
434 {
435         char c = 0;
436
437         if (((status > 0) && (status <= 8)) ||
438                                 ((status >= 100) && (status <= 108)) ||
439                                 ((status < 0) && (status >= -9)) ||
440                                 (status == -100) || (status == -101) ||
441                                 ((status <= -103) && (status >= -113))) {
442                 c = '5';
443         } else if (((status >= 9) && (status <= 14)) ||
444                         ((status >= 120) && (status <= 123)) ||
445                         ((status >= 125) && (status <= 129)) ||
446                         ((status >= -13) && (status <= -10)) ||
447                         (status == -120) || (status == -122) ||
448                         ((status <= -124) && (status >= -127)) ||
449                         (status == -129)) {
450                 c = '8';
451         } else if (status == 15) {
452                 c = '9';
453         } else if ((status <= -30) && (status >= -32)) {
454                 c = 'A';
455         } else if (((status <= -35) && (status >= -40)) ||
456                         ((status <= -42) && (status >= -51)) ||
457                         ((status <= -53) && (status >= -58)) ||
458                         (status == -64) ||
459                         ((status <= -80) && (status >= -83)) ||
460                         (status == -130) || (status == -140) ||
461                         (status == -150)) {
462                 c = 'B';
463         }
464
465         if (c == 0)
466                 return -EINVAL;
467
468         buf[0] = (status < 0) ? '-' : c;
469         buf[1] = c;
470
471         return 0;
472 }
473
474 void show_boot_progress(int status)
475 {
476         char buf[2];
477
478         if (a4m072_status2code(status, buf) < 0)
479                 return;
480
481         display_putc(buf[0]);
482         display_putc(buf[1]);
483         display_set(DISPLAY_HOME);
484         display_out_pos = 0;    /* reset output position */
485
486         /* we want to flush status 15 now */
487         if (status == 15)
488                 display_flush();
489 }
490 #endif