}
}
-static void show_hw_revision(void)
+void show_hw_revision(void)
{
int board;
printf("i2c_write error: %x\n", addr);
return;
}
+ i2c_read(addr, 0x06, 1, val, 2);
if (i2c_read(addr, 0x04, 1, val, 1)) {
printf("i2c_read error: %x\n", addr);
*/
val[0] = 0x35;
i2c_write((0x72 >> 1), 0x08, 1, val, 1);
+ i2c_read((0x72 >> 1), 0x08, 1, val, 1);
/*
* MHL TX Control #1
*/
val[0] = 0xd0;
i2c_write((0x72 >> 1), 0xa0, 1, val, 1);
+ i2c_read((0x72 >> 1), 0xa0, 1, val, 1);
}
static void check_micro_usb(void)
val[0] &= ~(0x7 << 0);
val[0] |= 5; /* 600mA */
i2c_write(addr, 0x0C, 1, val, 1);
+ i2c_read(addr, 0x0C, 1, val, 1);
}
/* If Factory Mode is Boot ON-USB, go to download mode */
val[0] &= ~(MAX8998_LDO10 | MAX8998_LDO11 |
MAX8998_LDO12 | MAX8998_LDO13);
i2c_write(addr, MAX8998_REG_ONOFF2, 1, val, 1);
+ i2c_read(addr, MAX8998_REG_ONOFF2, 1, val, 1);
/* ONOFF3 */
i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
/*
val[0] &= ~(MAX8998_LDO14 | MAX8998_LDO15 |
MAX8998_LDO16 | MAX8998_LDO17);
i2c_write(addr, MAX8998_REG_ONOFF3, 1, val, 1);
+ i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
}
#define PDN_MASK(x) (0x3 << ((x) << 1))
PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
PULL_DIS(4),
}, { /* S5PC110_GPIO_C1_OFFSET */
- OUTPUT0(0) | OUTPUT0(1) | OUTPUT0(2) | OUTPUT0(3) |
+ /* OUTPUT0(0) | OUTPUT0(1) | OUTPUT0(2) | OUTPUT0(3) |
+ OUTPUT0(4), */
+ OUTPUT0(0) | OUTPUT0(1) | OUTPUT0(2) | INPUT(3) |
OUTPUT0(4),
PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
PULL_DIS(4),
PULL_DIS(4) | PULL_DIS(5) | PULL_DIS(6) | PULL_DIS(7),
}, { /* S5PC110_GPIO_J2_OFFSET */
OUTPUT0(0) | OUTPUT0(1) | OUTPUT0(2) | OUTPUT0(3) |
- INPUT(4) | OUTPUT1(5) | OUTPUT0(6) | INPUT(7),
+ INPUT(4) | OUTPUT0(5) | OUTPUT0(6) | INPUT(7),
PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
PULL_DIS(4) | PULL_DIS(5) | PULL_DIS(6) | PULL_DOWN(7),
}, { /* S5PC110_GPIO_J3_OFFSET */
CON_OUTPUT(4) | CON_OUTPUT(5) | CON_INPUT(6) | CON_INPUT(7),
DAT_SET(0) | DAT_CLEAR(2) | DAT_CLEAR(3) |
DAT_CLEAR(4) | DAT_CLEAR(5),
+ PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
+ PULL_DIS(4) | PULL_DIS(5),
}, { /* S5PC110_GPIO_H1_OFFSET */
- CON_INPUT(0) | CON_INPUT(1) | CON_OUTPUT(2) | CON_IRQ(3) |
+ /* CON_INPUT(0) | CON_INPUT(1) | CON_OUTPUT(2) | CON_IRQ(3) |
CON_IRQ(4) | CON_INPUT(5) | CON_INPUT(6) | CON_INPUT(7),
DAT_CLEAR(2),
PULL_DOWN(0) | PULL_DOWN(1) |
- PULL_DOWN(6),
+ PULL_DOWN(6), */
+ CON_INPUT(0) | CON_INPUT(1) | CON_OUTPUT(2) | CON_IRQ(3) |
+ CON_INPUT(4) | CON_INPUT(5) | CON_OUTPUT(6) | CON_INPUT(7),
+ DAT_SET(0),
+ PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
+ PULL_DOWN(4),
}, { /* S5PC110_GPIO_H2_OFFSET */
CON_OUTPUT(0) | CON_OUTPUT(1) | CON_OUTPUT(2) | CON_OUTPUT(3) |
CON_IRQ(4) | CON_IRQ(5) | CON_IRQ(6) | CON_IRQ(7),
writel(0x0000, &bank->pdn_con);
writel(0x0000, &bank->pdn_pull);
+ /* M299 */
+ writel(0xff0022b0, (unsigned int*) 0xF0000000);
+ writel(0xff0022b0, (unsigned int*) 0xF1400000);
+
+
bank = &gpio->gpio_h0;
ge = external_powerdown_modes;
else
setenv("lcd", "lcd=tl2796-dual");
#endif
+
show_hw_revision();
/* Set proper PMIC pins */
}
/* Used for sleep test */
+static unsigned char saved_val[3][2];
void board_sleep_init(void)
{
unsigned int value;
unsigned char addr;
unsigned char val[2];
+ unsigned char dummy = 0;
/* Set wakeup mask register */
value = 0xFFFF;
/* Set ONOFF1 */
i2c_read(addr, 0x11, 1, val, 1);
+ saved_val[0][0] = val[0];
+ saved_val[0][1] = val[1];
val[0] &= ~((1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) |
(1 << 1) | (1 << 0));
i2c_write(addr, 0x11, 1, val, 1);
i2c_read(addr, 0x11, 1, val, 1);
- printf("ONOFF1 0x%02x\n", val[0]);
/* Set ONOFF2 */
i2c_read(addr, 0x12, 1, val, 1);
+ saved_val[1][0] = val[0];
+ saved_val[1][1] = val[1];
val[0] &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 3) |
(1 << 2) | (1 << 1) | (1 << 0));
i2c_write(addr, 0x12, 1, val, 1);
i2c_read(addr, 0x12, 1, val, 1);
- printf("ONOFF2 0x%02x\n", val[0]);
/* Set ONOFF3 */
i2c_read(addr, 0x13, 1, val, 1);
+ saved_val[2][0] = val[0];
+ saved_val[2][1] = val[1];
val[0] &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4));
val[0] = 0x0;
i2c_write(addr, 0x13, 1, val, 1);
i2c_read(addr, 0x13, 1, val, 1);
- printf("ONOFF3 0x%02x\n", val[0]);
+ printf("Preparing to sleep.\n");
+ /* Strangely, unless printf is used,
+ * it does not work. (i2c_read seems to be ignored)
+ * Probably, the compiler's optimization mechanism is
+ * doing this. */
+}
+void board_sleep_resume(void)
+{
+ unsigned char addr;
+ unsigned char val[2];
+
+ i2c_gpio_set_bus(I2C_PMIC);
+ addr = 0xCC >> 1;
+ if (i2c_probe(addr)) {
+ printf("Can't found max8998\n");
+ return;
+ }
+
+ /* Set ONOFF1 */
+ i2c_write(addr, 0x11, 1, saved_val[0], 1);
+ i2c_read(addr, 0x11, 1, val, 1);
+ /* Set ONOFF2 */
+ i2c_write(addr, 0x12, 1, saved_val[1], 1);
+ i2c_read(addr, 0x12, 1, val, 1);
+ /* Set ONOFF3 */
+ i2c_write(addr, 0x13, 1, saved_val[2], 1);
+ i2c_read(addr, 0x13, 1, val, 1);
+ printf("Waked up.\n");
}
#ifdef CONFIG_CMD_USBDOWN
printf("i2c_write error\n");
return 1;
}
+ i2c_read(0x66, 0, 1, val, 2);
#endif
return 0;
}
#include <asm/arch/cpu.h>
#include <asm/arch/power.h>
+#define CONFIG_CPU_S5PC110_EVT0_ERRATA
+
+#include <common.h>
+#include "sleep.h"
+
+extern int s5pc110_cpu_save(unsigned long *saveblk);
+extern void s5pc110_cpu_resume(void);
+extern unsigned int s5pc110_sleep_return_addr;
+extern unsigned int s5pc110_sleep_save_phys;
+
+struct stack {
+ u32 irq[3];
+ u32 abt[3];
+ u32 und[3];
+} ____cacheline_aligned;
+
+static struct stack stacks[1];
+
enum {
SLEEP_WFI,
SLEEP_REGISTER,
void board_sleep_init(void)
__attribute__((weak, alias("__board_sleep_init")));
+struct regs_to_save {
+ unsigned int start_address;
+ unsigned int size;
+};
+static struct regs_to_save core_save[] = {
+ { .start_address=0xE0100200, .size=7},
+ { .start_address=0xE0100280, .size=2},
+ { .start_address=0xE0100300, .size=7},
+ { .start_address=0xE0100460, .size=5},
+ { .start_address=0xE0100480, .size=3},
+ { .start_address=0xE0100500, .size=1},
+ { .start_address=0xE0107008, .size=1},
+};
+static unsigned int buf_core_save[7+2+7+5+3+1+1];
+static struct regs_to_save gpio_save[] = {
+ { .start_address=0xE0200000, .size=6},
+ { .start_address=0xE0200020, .size=6},
+ { .start_address=0xE0200040, .size=6},
+ { .start_address=0xE0200060, .size=6},
+ { .start_address=0xE0200080, .size=6},
+ { .start_address=0xE02000A0, .size=6},
+ { .start_address=0xE02000C0, .size=6},
+ { .start_address=0xE02000E0, .size=6},
+ { .start_address=0xE0200100, .size=6},
+ { .start_address=0xE0200120, .size=6},
+ { .start_address=0xE0200140, .size=6},
+ { .start_address=0xE0200160, .size=6},
+ { .start_address=0xE0200180, .size=6},
+ { .start_address=0xE02001A0, .size=6},
+ { .start_address=0xE02001C0, .size=6},
+ { .start_address=0xE02001E0, .size=6},
+ { .start_address=0xE0200200, .size=6},
+ { .start_address=0xE0200220, .size=6},
+ { .start_address=0xE0200240, .size=6},
+ { .start_address=0xE0200260, .size=6},
+ { .start_address=0xE0200280, .size=6},
+ { .start_address=0xE02002A0, .size=6},
+ { .start_address=0xE02002C0, .size=6},
+ { .start_address=0xE02002E0, .size=6},
+ { .start_address=0xE0200300, .size=6},
+ { .start_address=0xE0200320, .size=6},
+ { .start_address=0xE0200340, .size=6},
+ { .start_address=0xE0200360, .size=6},
+ { .start_address=0xE0200380, .size=6},
+ { .start_address=0xE02003A0, .size=6},
+ { .start_address=0xE02003C0, .size=6},
+ { .start_address=0xE02003E0, .size=6},
+ { .start_address=0xE0200400, .size=6},
+ { .start_address=0xE0200420, .size=6},
+ { .start_address=0xE0200440, .size=6},
+ { .start_address=0xE0200460, .size=6},
+ { .start_address=0xE0200480, .size=6},
+ { .start_address=0xE02004A0, .size=6},
+ { .start_address=0xE02004C0, .size=6},
+ { .start_address=0xE02004E0, .size=6},
+ { .start_address=0xE0200500, .size=6},
+ { .start_address=0xE0200520, .size=6},
+ { .start_address=0xE0200540, .size=6},
+ { .start_address=0xE0200560, .size=6},
+ { .start_address=0xE0200580, .size=6},
+ { .start_address=0xE02005A0, .size=6},
+ { .start_address=0xE02005C0, .size=6},
+ { .start_address=0xE02005E0, .size=6},
+ { .start_address=0xE0200700, .size=22},
+ { .start_address=0xE0200900, .size=22},
+ { .start_address=0xE0200A00, .size=22},
+};
+static unsigned int buf_gpio_save[ 6*8*6 + 22*3 ];
+static struct regs_to_save irq_save[] = {
+ { .start_address=0xF200000C, .size=2},
+ { .start_address=0xF2000018, .size=1},
+ { .start_address=0xF210000C, .size=2},
+ { .start_address=0xF2100018, .size=1},
+ { .start_address=0xF220000C, .size=2},
+ { .start_address=0xF2200018, .size=1},
+ { .start_address=0xF230000C, .size=2},
+ { .start_address=0xF2300018, .size=1},
+};
+static unsigned int buf_irq_save[ (2+1)*4 ];
+static struct regs_to_save sromc_save[] = {
+ { .start_address=0xE8000000, .size=7},
+};
+static unsigned int buf_sromc_save[7];
+static struct regs_to_save uart_save[] = {
+ { .start_address=0xE2900000, .size=4},
+ { .start_address=0xE2900028, .size=2},
+ { .start_address=0xE2900038, .size=1},
+ { .start_address=0xE2900400, .size=4},
+ { .start_address=0xE2900428, .size=2},
+ { .start_address=0xE2900438, .size=1},
+ { .start_address=0xE2900800, .size=4},
+ { .start_address=0xE2900828, .size=2},
+ { .start_address=0xE2900838, .size=1},
+ { .start_address=0xE2900C00, .size=4},
+ { .start_address=0xE2900C28, .size=2},
+ { .start_address=0xE2900C38, .size=1},
+};
+static unsigned int buf_uart_save[(4+2+1)*4];
+
+static unsigned int reg_others;
+
+void s5pc110_save_reg(struct regs_to_save * list, unsigned int * buf, int length)
+{
+ int i;
+ int counter = 0;
+ for (i=0; i<length; i++) {
+ int j;
+ for (j=0; j<list[i].size; j++) {
+ (*buf) = readl((unsigned int *)(list[i].start_address+j*4));
+ buf++;
+ counter++;
+ }
+ }
+}
+void s5pc110_save_regs(void)
+{
+ reg_others = readl(S5PC110_OTHERS);
+ s5pc110_save_reg(gpio_save, buf_gpio_save, ARRAY_SIZE(gpio_save));
+ s5pc110_save_reg(irq_save, buf_irq_save, ARRAY_SIZE(irq_save));
+ s5pc110_save_reg(core_save, buf_core_save, ARRAY_SIZE(core_save));
+ s5pc110_save_reg(sromc_save, buf_sromc_save, ARRAY_SIZE(sromc_save));
+ s5pc110_save_reg(uart_save, buf_uart_save, ARRAY_SIZE(uart_save));
+}
+void s5pc110_restore_reg(struct regs_to_save * list, unsigned int * buf, int length)
+{
+ int i;
+ for (i=0; i<length; i++) {
+ int j;
+ for (j=0; j<list[i].size; j++) {
+ writel(*buf, (unsigned int *)(list[i].start_address+j*4));
+#ifdef CONFIG_CPU_S5PC110_EVT0_ERRATA
+ readl((unsigned int *)(list[i].start_address+j*4));
+#endif
+ buf++;
+ }
+ }
+
+}
+void s5pc110_restore_regs(void)
+{
+ s5pc110_restore_reg(uart_save, buf_uart_save, ARRAY_SIZE(uart_save));
+ s5pc110_restore_reg(sromc_save, buf_sromc_save, ARRAY_SIZE(sromc_save));
+ s5pc110_restore_reg(core_save, buf_core_save, ARRAY_SIZE(core_save));
+ s5pc110_restore_reg(irq_save, buf_irq_save, ARRAY_SIZE(irq_save));
+ s5pc110_restore_reg(gpio_save, buf_gpio_save, ARRAY_SIZE(gpio_save));
+}
+
+void s5pc110_wakeup(void)
+{
+ struct stack *stk = &stacks[0];
+ __asm__ (
+ "msr cpsr_c, %1\n\t"
+ "add sp, %0, %2\n\t"
+ "msr cpsr_c, %3\n\t"
+ "add sp, %0, %4\n\t"
+ "msr cpsr_c, %5\n\t"
+ "add sp, %0, %6\n\t"
+ "msr cpsr_c, %7"
+ :
+ : "r" (stk),
+ "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
+ "I" (offsetof(struct stack, irq[0])),
+ "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
+ "I" (offsetof(struct stack, abt[0])),
+ "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
+ "I" (offsetof(struct stack, und[0])),
+ "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
+ : "r14");
+
+
+ s5pc110_restore_regs();
+
+ reg_others |= 1<<28;
+ writel(reg_others, S5PC110_OTHERS);
+
+ printf("%s: Waking up...\n", __func__);
+
+ start_armboot_resume();
+
+ return;
+}
+
static int s5pc110_sleep(int mode)
{
+ unsigned long regs_save[16];
unsigned int value;
+ int i;
+
+ printf("Entering s5pc110_sleep();\n");
board_sleep_init();
- writel(0x0badcafe, S5PC110_INFORM0);
+ value = readl(S5PC110_WAKEUP_MASK);
+ value |= (1 << 15);
+ value |= (1 << 14);
+ value |= (1 << 13);
+ value |= (1 << 12);
+ value |= (1 << 11);
+ value |= (1 << 10);
+ value |= (1 << 9);
+ value |= (1 << 5);
+ value |= (1 << 4);
+ value |= (1 << 3);
+ value |= (1 << 2);
+ value |= (1 << 1);
+ writel(value, S5PC110_WAKEUP_MASK);
+
+ value = __raw_readl(S5PC110_EINT_WAKEUP_MASK);
+ value = 0xFFFFFFFF;
+ value &= ~(1 << 7); /* AP_PMIC_IRQ */
+ value &= ~(1 << 22); /* nPOWER */
+ writel(value, S5PC110_EINT_WAKEUP_MASK);
+#ifdef CONFIG_CPU_S5PC110_EVT0_ERRATA
+ readl(S5PC110_EINT_WAKEUP_MASK);
+ for (i = 0; i < 4; i++)
+ readl(0xE0200F40+i*4);
+#endif
+
+ s5pc110_save_regs();
+ writel((unsigned long) s5pc110_cpu_resume, S5PC110_INFORM0);
+
+#ifdef CONFIG_CPU_S5PC110_EVT0_ERRATA
+ value = readl(S5PC110_SLEEP_CFG);
+ value &= ~(1 << 0); /* OSC_EN off */
+ value &= ~(1 << 1); /* USBOSC_EN off */
+ writel(value, S5PC110_SLEEP_CFG);
+#endif
value = readl(S5PC110_PWR_CFG);
value &= ~S5PC110_CFG_STANDBYWFI_MASK;
if (mode == SLEEP_WFI)
+#ifdef CONFIG_CPU_S5PC110_EVT0_ERRATA
+ {
+ printf("ERRATA MODE\n");
+ value |= S5PC110_CFG_STANDBYWFI_IGNORE;
+ }
+#else
value |= S5PC110_CFG_STANDBYWFI_SLEEP;
+#endif
else
value |= S5PC110_CFG_STANDBYWFI_IGNORE;
writel(value, S5PC110_PWR_CFG);
+ /* F2000000: VICIRQSTATUS-irq0 */
+ writel(0xffffffff, 0xF2000000 + 0x14); /* VIC_INT_ENABLE_CLEAR */
+ writel(0xffffffff, 0xF2100000 + 0x14);
+ writel(0xffffffff, 0xF2200000 + 0x14);
+ writel(0xffffffff, 0xF2300000 + 0x14);
+ writel(0xffffffff, 0xF2000000 + 0x1c); /* VIC_INT_SOFT_CLEAR */
+ writel(0xffffffff, 0xF2100000 + 0x1c);
+ writel(0xffffffff, 0xF2200000 + 0x1c);
+ writel(0xffffffff, 0xF2300000 + 0x1c);
+
+ /* Clear all EINT PENDING bit */
+ writel(0xff, 0xE0200000 + 0xF40);
+ value = readl(0xE0200000 + 0xF40);
+ writel(0xff, 0xE0200000 + 0xF44);
+ value = readl(0xE0200000 + 0xF44);
+ writel(0xff, 0xE0200000 + 0xF48);
+ value = readl(0xE0200000 + 0xF48);
+ writel(0xff, 0xE0200000 + 0xF4C);
+ value = readl(0xE0200000 + 0xF4C);
+ writel(0xFFFF , S5PC110_WAKEUP_STAT);
+
+
value = readl(S5PC110_OTHERS);
value |= S5PC110_OTHERS_SYSCON_INT_DISABLE;
writel(value, S5PC110_OTHERS);
- printf("%s[%d] sleep enter mode %d\n\n", __func__, __LINE__, mode);
-
if (mode == SLEEP_WFI) {
value = 0;
+ s5pc110_sleep_save_phys = (unsigned int) regs_save;
+
+ value = readl(S5PC110_OTHERS);
+ value |= 1;
+ writel(value, S5PC110_OTHERS);
+
+#ifdef CONFIG_CPU_S5PC110_EVT0_ERRATA
+ if (s5pc110_cpu_save(regs_save) == 0) {
+ /* cache flush */
+ asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0));
+ l2_cache_disable();
+ invalidate_dcache(get_device_type());
+
+ value = (1 << 2);
+ writel(value, S5PC110_PWR_MODE);
+ while(1);
+ }
+
+ s5pc110_wakeup();
+
+ writel(0, S5PC110_EINT_WAKEUP_MASK);
+#ifdef CONFIG_CPU_S5PC110_EVT0_ERRATA
+ readl(S5PC110_EINT_WAKEUP_MASK);
+ for (i = 0; i < 4; i++)
+ readl(0xE0200F40+i*4);
+#endif
+ value = readl(S5PC110_WAKEUP_STAT);
+ writel(0xFFFF & value, S5PC110_WAKEUP_STAT);
+
+ printf("Wakeup Source: 0x%08x\n", value);
+ value = readl(S5PC110_WAKEUP_STAT);
+
+#else
asm("b 1f\n\t"
".align 5\n\t"
"1:\n\t"
"mcr p15, 0, %0, c7, c10, 5\n\t"
"mcr p15, 0, %0, c7, c10, 4\n\t"
".word 0xe320f003" :: "r" (value));
+#endif
} else {
value = S5PC110_PWR_MODE_SLEEP;
writel(value, S5PC110_PWR_MODE);
}
- printf("%s[%d] sleep success\n", __func__, __LINE__);
+ show_hw_revision();
+
+ board_sleep_resume();
return 0;
}
NULL,
};
+void start_armboot_resume(void)
+{
+ init_fnc_t **init_fnc_ptr;
+ char *s;
+#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
+ unsigned long addr;
+#endif
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
+ /* compiler optimization barrier needed for GCC >= 3.4 */
+ __asm__ __volatile__("": : :"memory");
+
+ memset ((void*)gd, 0, sizeof (gd_t));
+ gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
+ memset (gd->bd, 0, sizeof (bd_t));
+
+ gd->flags |= GD_FLG_RELOC;
+
+ monitor_flash_len = _bss_start - _armboot_start;
+
+ for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+ if ((*init_fnc_ptr)() != 0) {
+ hang ();
+ }
+ }
+
+#ifdef CONFIG_VFD
+# ifndef PAGE_SIZE
+# define PAGE_SIZE 4096
+# endif
+ /*
+ * reserve memory for VFD display (always full pages)
+ */
+ /* bss_end is defined in the board-specific linker script */
+ addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+ vfd_setmem (addr);
+ gd->fb_base = addr;
+#endif /* CONFIG_VFD */
+
+#ifdef CONFIG_LCD
+ /* board init may have inited fb_base */
+ if (!gd->fb_base) {
+# ifndef PAGE_SIZE
+# define PAGE_SIZE 4096
+# endif
+ /*
+ * reserve memory for LCD display (always full pages)
+ */
+ /* bss_end is defined in the board-specific linker script */
+ addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+ lcd_setmem (addr);
+ gd->fb_base = addr;
+ }
+#endif /* CONFIG_LCD */
+
+#if defined(CONFIG_CMD_NAND)
+ puts ("NAND: ");
+ nand_init(); /* go init the NAND */
+#endif
+
+#if defined(CONFIG_CMD_ONENAND)
+ onenand_init();
+#endif
+
+#ifdef CONFIG_HAS_DATAFLASH
+ AT91F_DataflashInit();
+ dataflash_print_info();
+#endif
+
+ /* initialize environment */
+ env_relocate ();
+
+#ifdef CONFIG_VFD
+ /* must do this after the framebuffer is allocated */
+ drv_vfd_init();
+#endif /* CONFIG_VFD */
+
+#ifdef CONFIG_SERIAL_MULTI
+ serial_initialize();
+#endif
+
+ stdio_init_resume (); /* get the devices list going. */
+
+#if defined(CONFIG_ARCH_MISC_INIT)
+ /* miscellaneous arch dependent initialisations */
+ arch_misc_init ();
+#endif
+
+#if defined(CONFIG_MISC_INIT_R)
+ /* miscellaneous platform dependent initialisations */
+ misc_init_r ();
+#endif
+
+ /* enable exceptions */
+ enable_interrupts ();
+
+ /* Perform network card initialisation if necessary */
+#ifdef CONFIG_DRIVER_TI_EMAC
+ /* XXX: this needs to be moved to board init */
+extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
+ if (getenv ("ethaddr")) {
+ uchar enetaddr[6];
+ eth_getenv_enetaddr("ethaddr", enetaddr);
+ davinci_eth_set_mac_addr(enetaddr);
+ }
+#endif
+
+#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
+ /* XXX: this needs to be moved to board init */
+ if (getenv ("ethaddr")) {
+ uchar enetaddr[6];
+ eth_getenv_enetaddr("ethaddr", enetaddr);
+ smc_set_mac_addr(enetaddr);
+ }
+#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
+
+ /* Initialize from environment */
+ if ((s = getenv ("loadaddr")) != NULL) {
+ load_addr = simple_strtoul (s, NULL, 16);
+ }
+
+#ifdef BOARD_LATE_INIT
+ board_late_init ();
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+ puts ("MMC: ");
+ mmc_initialize (gd->bd);
+#endif
+
+#ifdef CONFIG_BITBANGMII
+ bb_miiphy_init();
+#endif
+#if defined(CONFIG_CMD_NET)
+#if defined(CONFIG_NET_MULTI)
+ puts ("Net: ");
+#endif
+ eth_initialize(gd->bd);
+#endif
+
+}
+
void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;