3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6 * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
9 * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
11 * SPDX-License-Identifier: GPL-2.0+
17 #include <asm/processor.h>
21 #include <led-display.h>
22 #include <linux/err.h>
24 #include "mt46v32m16.h"
26 #ifndef CONFIG_SYS_RAMBOOT
27 static void sdram_start (int hi_addr
)
29 long hi_addr_bit
= hi_addr
? 0x01000000 : 0;
30 long control
= SDRAM_CONTROL
| hi_addr_bit
;
32 /* unlock mode register */
33 out_be32((void *)MPC5XXX_SDRAM_CTRL
, control
| 0x80000000);
34 __asm__
volatile ("sync");
36 /* precharge all banks */
37 out_be32((void *)MPC5XXX_SDRAM_CTRL
, control
| 0x80000002);
38 __asm__
volatile ("sync");
41 /* set mode register: extended mode */
42 out_be32((void *)MPC5XXX_SDRAM_MODE
, SDRAM_EMODE
);
43 __asm__
volatile ("sync");
45 /* set mode register: reset DLL */
46 out_be32((void *)MPC5XXX_SDRAM_MODE
, SDRAM_MODE
| 0x04000000);
47 __asm__
volatile ("sync");
50 /* precharge all banks */
51 out_be32((void *)MPC5XXX_SDRAM_CTRL
, control
| 0x80000002);
52 __asm__
volatile ("sync");
55 out_be32((void *)MPC5XXX_SDRAM_CTRL
, control
| 0x80000004);
56 __asm__
volatile ("sync");
58 /* set mode register */
59 out_be32((void *)MPC5XXX_SDRAM_MODE
, SDRAM_MODE
);
60 __asm__
volatile ("sync");
62 /* normal operation */
63 out_be32((void *)MPC5XXX_SDRAM_CTRL
, control
);
64 __asm__
volatile ("sync");
69 * ATTENTION: Although partially referenced initdram does NOT make real use
70 * use of CONFIG_SYS_SDRAM_BASE. The code does not work if CONFIG_SYS_SDRAM_BASE
71 * is something else than 0x00000000.
74 phys_size_t
initdram (int board_type
)
79 #ifndef CONFIG_SYS_RAMBOOT
82 /* setup SDRAM chip selects */
83 out_be32((void *)MPC5XXX_SDRAM_CS0CFG
, 0x0000001e); /* 2GB at 0x0 */
84 out_be32((void *)MPC5XXX_SDRAM_CS1CFG
, 0x80000000); /* disabled */
85 __asm__
volatile ("sync");
87 /* setup config registers */
88 out_be32((void *)MPC5XXX_SDRAM_CONFIG1
, SDRAM_CONFIG1
);
89 out_be32((void *)MPC5XXX_SDRAM_CONFIG2
, SDRAM_CONFIG2
);
90 __asm__
volatile ("sync");
94 out_be32((void *)MPC5XXX_CDM_PORCFG
, SDRAM_TAPDELAY
);
95 __asm__
volatile ("sync");
98 /* find RAM size using SDRAM CS0 only */
100 test1
= get_ram_size((long *)CONFIG_SYS_SDRAM_BASE
, 0x80000000);
102 test2
= get_ram_size((long *)CONFIG_SYS_SDRAM_BASE
, 0x80000000);
110 /* memory smaller than 1MB is impossible */
111 if (dramsize
< (1 << 20)) {
115 /* set SDRAM CS0 size according to the amount of RAM found */
117 out_be32((void *)MPC5XXX_SDRAM_CS0CFG
,
118 0x13 + __builtin_ffs(dramsize
>> 20) - 1);
120 out_be32((void *)MPC5XXX_SDRAM_CS0CFG
, 0); /* disabled */
123 #else /* CONFIG_SYS_RAMBOOT */
125 /* retrieve size of memory connected to SDRAM CS0 */
126 dramsize
= in_be32((void *)MPC5XXX_SDRAM_CS0CFG
) & 0xFF;
127 if (dramsize
>= 0x13) {
128 dramsize
= (1 << (dramsize
- 0x13)) << 20;
133 #endif /* CONFIG_SYS_RAMBOOT */
136 * On MPC5200B we need to set the special configuration delay in the
137 * DDR controller. Please refer to Freescale's AN3221 "MPC5200B SDRAM
138 * Initialization and Configuration", 3.3.1 SDelay--MBAR + 0x0190:
140 * "The SDelay should be written to a value of 0x00000004. It is
141 * required to account for changes caused by normal wafer processing
146 if ((SVR_MJREV(svr
) >= 2) &&
147 (PVR_MAJ(pvr
) == 1) && (PVR_MIN(pvr
) == 4)) {
149 out_be32((void *)MPC5XXX_SDRAM_SDELAY
, 0x04);
150 __asm__
volatile ("sync");
156 int checkboard (void)
158 puts ("Board: A4M072\n");
163 static struct pci_controller hose
;
165 extern void pci_mpc5xxx_init(struct pci_controller
*);
167 void pci_init_board(void)
169 pci_mpc5xxx_init(&hose
);
173 #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
175 ft_board_setup(void *blob
, bd_t
*bd
)
177 ft_cpu_setup(blob
, bd
);
181 int board_eth_init(bd_t
*bis
)
185 /* Initialize TSECs first */
186 if ((rv
= cpu_eth_init(bis
)) >= 0)
189 printf("ERROR: failed to initialize FEC.\n");
191 if ((rv
= pci_eth_init(bis
)) >= 0)
194 printf("ERROR: failed to initialize PCI Ethernet.\n");
199 * Miscellaneous late-boot configurations
201 * Initialize EEPROM write-protect GPIO pin.
203 int misc_init_r(void)
205 #if defined(CONFIG_SYS_EEPROM_WREN)
206 /* Enable GPIO pin */
207 setbits_be32((void *)MPC5XXX_WU_GPIO_ENABLE
, CONFIG_SYS_EEPROM_WP
);
208 /* Set direction, output */
209 setbits_be32((void *)MPC5XXX_WU_GPIO_DIR
, CONFIG_SYS_EEPROM_WP
);
210 /* De-assert write enable */
211 setbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O
, CONFIG_SYS_EEPROM_WP
);
215 #if defined(CONFIG_SYS_EEPROM_WREN)
216 /* Input: <dev_addr> I2C address of EEPROM device to enable.
217 * <state> -1: deliver current state
220 * Returns: -1: wrong device address
221 * 0: dis-/en- able done
222 * 0/1: current state if <state> was -1.
224 int eeprom_write_enable (unsigned dev_addr
, int state
)
226 if (CONFIG_SYS_I2C_EEPROM_ADDR
!= dev_addr
) {
231 /* Enable write access */
232 clrbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O
, CONFIG_SYS_EEPROM_WP
);
236 /* Disable write access */
237 setbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O
, CONFIG_SYS_EEPROM_WP
);
241 /* Read current status back. */
242 state
= (0 == (in_be32((void *)MPC5XXX_WU_GPIO_DATA_O
) &
243 CONFIG_SYS_EEPROM_WP
));
251 #ifdef CONFIG_CMD_DISPLAY
252 #define DISPLAY_BUF_SIZE 2
253 static u8 display_buf
[DISPLAY_BUF_SIZE
];
254 static u8 display_putc_pos
;
255 static u8 display_out_pos
;
257 void display_set(int cmd
) {
259 if (cmd
& DISPLAY_CLEAR
) {
260 display_buf
[0] = display_buf
[1] = 0;
263 if (cmd
& DISPLAY_HOME
) {
264 display_putc_pos
= 0;
296 #define SYMBOL_DASH (36)
297 #define SYMBOL_UNDERLINE (37)
298 #define SYMBOL_DOT (38)
300 static u8 display_char2seg7_tbl
[]=
302 SEG_A
| SEG_B
| SEG_C
| SEG_D
| SEG_E
| SEG_F
, /* 0 */
303 SEG_B
| SEG_C
, /* 1 */
304 SEG_A
| SEG_B
| SEG_D
| SEG_E
| SEG_G
, /* 2 */
305 SEG_A
| SEG_B
| SEG_C
| SEG_D
| SEG_G
, /* 3 */
306 SEG_B
| SEG_C
| SEG_F
| SEG_G
, /* 4 */
307 SEG_A
| SEG_C
| SEG_D
| SEG_F
| SEG_G
, /* 5 */
308 SEG_A
| SEG_C
| SEG_D
| SEG_E
| SEG_F
| SEG_G
, /* 6 */
309 SEG_A
| SEG_B
| SEG_C
, /* 7 */
310 SEG_A
| SEG_B
| SEG_C
| SEG_D
| SEG_E
| SEG_F
| SEG_G
, /* 8 */
311 SEG_A
| SEG_B
| SEG_C
| SEG_D
| SEG_F
| SEG_G
, /* 9 */
312 SEG_A
| SEG_B
| SEG_C
| SEG_E
| SEG_F
| SEG_G
, /* A */
313 SEG_C
| SEG_D
| SEG_E
| SEG_F
| SEG_G
, /* b */
314 SEG_A
| SEG_D
| SEG_E
| SEG_F
, /* C */
315 SEG_B
| SEG_C
| SEG_D
| SEG_E
| SEG_G
, /* d */
316 SEG_A
| SEG_D
| SEG_E
| SEG_F
| SEG_G
, /* E */
317 SEG_A
| SEG_E
| SEG_F
| SEG_G
, /* F */
318 0, /* g - not displayed */
319 SEG_B
| SEG_C
| SEG_E
| SEG_F
| SEG_G
, /* H */
320 SEG_B
| SEG_C
, /* I */
321 0, /* J - not displayed */
322 0, /* K - not displayed */
323 SEG_D
| SEG_E
| SEG_F
, /* L */
324 0, /* m - not displayed */
325 0, /* n - not displayed */
326 SEG_A
| SEG_B
| SEG_C
| SEG_D
| SEG_E
| SEG_F
, /* O */
327 SEG_A
| SEG_B
| SEG_E
| SEG_F
| SEG_G
, /* P */
328 0, /* q - not displayed */
329 0, /* r - not displayed */
330 SEG_A
| SEG_C
| SEG_D
| SEG_F
| SEG_G
, /* S */
331 SEG_D
| SEG_E
| SEG_F
| SEG_G
, /* t */
332 SEG_B
| SEG_C
| SEG_D
| SEG_E
| SEG_F
, /* U */
333 0, /* V - not displayed */
334 0, /* w - not displayed */
335 0, /* X - not displayed */
336 SEG_B
| SEG_C
| SEG_D
| SEG_F
| SEG_G
, /* Y */
337 0, /* Z - not displayed */
343 /* Convert char to the LED segments representation */
344 static u8
display_char2seg7(char c
)
348 if (c
>= '0' && c
<= '9')
350 else if (c
>= 'a' && c
<= 'z')
352 else if (c
>= 'A' && c
<= 'Z')
357 c
= SYMBOL_UNDERLINE
;
361 c
= ' '; /* display unsupported symbols as space */
364 val
= display_char2seg7_tbl
[(int)c
];
369 int display_putc(char c
)
371 if (display_putc_pos
>= DISPLAY_BUF_SIZE
)
374 display_buf
[display_putc_pos
++] = display_char2seg7(c
);
375 /* one-symbol message should be steady */
376 if (display_putc_pos
== 1)
377 display_buf
[display_putc_pos
] = display_char2seg7(c
);
383 * Flush current symbol to the LED display hardware
385 static inline void display_flush(void)
387 u32 val
= display_buf
[display_out_pos
];
389 val
|= (val
<< 8) | (val
<< 16) | (val
<< 24);
390 out_be32((void *)CONFIG_SYS_DISP_CHR_RAM
, val
);
394 * Output contents of the software display buffer to the LED display every 0.5s
396 void board_show_activity(ulong timestamp
)
401 if (!once
|| (timestamp
- last
>= (CONFIG_SYS_HZ
/ 2))) {
403 display_out_pos
^= 1;
410 * Empty fake function
412 void show_activity(int arg
)
416 #if defined (CONFIG_SHOW_BOOT_PROGRESS)
417 static int a4m072_status2code(int status
, char *buf
)
421 if (((status
> 0) && (status
<= 8)) ||
422 ((status
>= 100) && (status
<= 108)) ||
423 ((status
< 0) && (status
>= -9)) ||
424 (status
== -100) || (status
== -101) ||
425 ((status
<= -103) && (status
>= -113))) {
427 } else if (((status
>= 9) && (status
<= 14)) ||
428 ((status
>= 120) && (status
<= 123)) ||
429 ((status
>= 125) && (status
<= 129)) ||
430 ((status
>= -13) && (status
<= -10)) ||
431 (status
== -120) || (status
== -122) ||
432 ((status
<= -124) && (status
>= -127)) ||
435 } else if (status
== 15) {
437 } else if ((status
<= -30) && (status
>= -32)) {
439 } else if (((status
<= -35) && (status
>= -40)) ||
440 ((status
<= -42) && (status
>= -51)) ||
441 ((status
<= -53) && (status
>= -58)) ||
443 ((status
<= -80) && (status
>= -83)) ||
444 (status
== -130) || (status
== -140) ||
452 buf
[0] = (status
< 0) ? '-' : c
;
458 void show_boot_progress(int status
)
462 if (a4m072_status2code(status
, buf
) < 0)
465 display_putc(buf
[0]);
466 display_putc(buf
[1]);
467 display_set(DISPLAY_HOME
);
468 display_out_pos
= 0; /* reset output position */
470 /* we want to flush status 15 now */
471 if (status
== BOOTSTAGE_ID_RUN_OS
)