uboot/arch/arm/lib/board.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002-2006
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * (C) Copyright 2002
   6 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   7 * Marius Groeger <mgroeger@sysgo.de>
   8 *
   9 * See file CREDITS for list of people who contributed to this
  10 * project.
  11 *
  12 * This program is free software; you can redistribute it and/or
  13 * modify it under the terms of the GNU General Public License as
  14 * published by the Free Software Foundation; either version 2 of
  15 * the License, or (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  25 * MA 02111-1307 USA
  26 */
  27
  28/*
  29 * To match the U-Boot user interface on ARM platforms to the U-Boot
  30 * standard (as on PPC platforms), some messages with debug character
  31 * are removed from the default U-Boot build.
  32 *
  33 * Define DEBUG here if you want additional info as shown below
  34 * printed upon startup:
  35 *
  36 * U-Boot code: 00F00000 -> 00F3C774  BSS: -> 00FC3274
  37 * IRQ Stack: 00ebff7c
  38 * FIQ Stack: 00ebef7c
  39 */
  40
  41#include <common.h>
  42#include <command.h>
  43#include <environment.h>
  44#include <malloc.h>
  45#include <stdio_dev.h>
  46#include <version.h>
  47#include <net.h>
  48#include <serial.h>
  49#include <nand.h>
  50#include <onenand_uboot.h>
  51#include <mmc.h>
  52#include <libfdt.h>
  53#include <fdtdec.h>
  54#include <post.h>
  55#include <logbuff.h>
  56#include <asm/sections.h>
  57
  58#ifdef CONFIG_BITBANGMII
  59#include <miiphy.h>
  60#endif
  61
  62DECLARE_GLOBAL_DATA_PTR;
  63
  64ulong monitor_flash_len;
  65
  66#ifdef CONFIG_HAS_DATAFLASH
  67extern int  AT91F_DataflashInit(void);
  68extern void dataflash_print_info(void);
  69#endif
  70
  71#if defined(CONFIG_HARD_I2C) || \
  72    defined(CONFIG_SOFT_I2C)
  73#include <i2c.h>
  74#endif
  75
  76/************************************************************************
  77 * Coloured LED functionality
  78 ************************************************************************
  79 * May be supplied by boards if desired
  80 */
  81inline void __coloured_LED_init(void) {}
  82void coloured_LED_init(void)
  83        __attribute__((weak, alias("__coloured_LED_init")));
  84inline void __red_led_on(void) {}
  85void red_led_on(void) __attribute__((weak, alias("__red_led_on")));
  86inline void __red_led_off(void) {}
  87void red_led_off(void) __attribute__((weak, alias("__red_led_off")));
  88inline void __green_led_on(void) {}
  89void green_led_on(void) __attribute__((weak, alias("__green_led_on")));
  90inline void __green_led_off(void) {}
  91void green_led_off(void) __attribute__((weak, alias("__green_led_off")));
  92inline void __yellow_led_on(void) {}
  93void yellow_led_on(void) __attribute__((weak, alias("__yellow_led_on")));
  94inline void __yellow_led_off(void) {}
  95void yellow_led_off(void) __attribute__((weak, alias("__yellow_led_off")));
  96inline void __blue_led_on(void) {}
  97void blue_led_on(void) __attribute__((weak, alias("__blue_led_on")));
  98inline void __blue_led_off(void) {}
  99void blue_led_off(void) __attribute__((weak, alias("__blue_led_off")));
 100
 101/*
 102 ************************************************************************
 103 * Init Utilities                                                       *
 104 ************************************************************************
 105 * Some of this code should be moved into the core functions,
 106 * or dropped completely,
 107 * but let's get it working (again) first...
 108 */
 109
 110#if defined(CONFIG_ARM_DCC) && !defined(CONFIG_BAUDRATE)
 111#define CONFIG_BAUDRATE 115200
 112#endif
 113
 114static int init_baudrate(void)
 115{
 116        gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
 117        return 0;
 118}
 119
 120static int display_banner(void)
 121{
 122        printf("\n\n%s\n\n", version_string);
 123        debug("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n",
 124               _TEXT_BASE,
 125               _bss_start_ofs + _TEXT_BASE, _bss_end_ofs + _TEXT_BASE);
 126#ifdef CONFIG_MODEM_SUPPORT
 127        debug("Modem Support enabled\n");
 128#endif
 129#ifdef CONFIG_USE_IRQ
 130        debug("IRQ Stack: %08lx\n", IRQ_STACK_START);
 131        debug("FIQ Stack: %08lx\n", FIQ_STACK_START);
 132#endif
 133
 134        return (0);
 135}
 136
 137/*
 138 * WARNING: this code looks "cleaner" than the PowerPC version, but
 139 * has the disadvantage that you either get nothing, or everything.
 140 * On PowerPC, you might see "DRAM: " before the system hangs - which
 141 * gives a simple yet clear indication which part of the
 142 * initialization if failing.
 143 */
 144static int display_dram_config(void)
 145{
 146        int i;
 147
 148#ifdef DEBUG
 149        puts("RAM Configuration:\n");
 150
 151        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
 152                printf("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
 153                print_size(gd->bd->bi_dram[i].size, "\n");
 154        }
 155#else
 156        ulong size = 0;
 157
 158        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
 159                size += gd->bd->bi_dram[i].size;
 160
 161        puts("DRAM:  ");
 162        print_size(size, "\n");
 163#endif
 164
 165        return (0);
 166}
 167
 168#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
 169static int init_func_i2c(void)
 170{
 171        puts("I2C:   ");
 172        i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 173        puts("ready\n");
 174        return (0);
 175}
 176#endif
 177
 178#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
 179#include <pci.h>
 180static int arm_pci_init(void)
 181{
 182        pci_init();
 183        return 0;
 184}
 185#endif /* CONFIG_CMD_PCI || CONFIG_PCI */
 186
 187/*
 188 * Breathe some life into the board...
 189 *
 190 * Initialize a serial port as console, and carry out some hardware
 191 * tests.
 192 *
 193 * The first part of initialization is running from Flash memory;
 194 * its main purpose is to initialize the RAM so that we
 195 * can relocate the monitor code to RAM.
 196 */
 197
 198/*
 199 * All attempts to come up with a "common" initialization sequence
 200 * that works for all boards and architectures failed: some of the
 201 * requirements are just _too_ different. To get rid of the resulting
 202 * mess of board dependent #ifdef'ed code we now make the whole
 203 * initialization sequence configurable to the user.
 204 *
 205 * The requirements for any new initalization function is simple: it
 206 * receives a pointer to the "global data" structure as it's only
 207 * argument, and returns an integer return code, where 0 means
 208 * "continue" and != 0 means "fatal error, hang the system".
 209 */
 210typedef int (init_fnc_t) (void);
 211
 212int print_cpuinfo(void);
 213
 214void __dram_init_banksize(void)
 215{
 216        gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
 217        gd->bd->bi_dram[0].size =  gd->ram_size;
 218}
 219void dram_init_banksize(void)
 220        __attribute__((weak, alias("__dram_init_banksize")));
 221
 222int __arch_cpu_init(void)
 223{
 224        return 0;
 225}
 226int arch_cpu_init(void)
 227        __attribute__((weak, alias("__arch_cpu_init")));
 228
 229int __power_init_board(void)
 230{
 231        return 0;
 232}
 233int power_init_board(void)
 234        __attribute__((weak, alias("__power_init_board")));
 235
 236        /* Record the board_init_f() bootstage (after arch_cpu_init()) */
 237static int mark_bootstage(void)
 238{
 239        bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");
 240
 241        return 0;
 242}
 243
 244init_fnc_t *init_sequence[] = {
 245        arch_cpu_init,          /* basic arch cpu dependent setup */
 246        mark_bootstage,
 247#ifdef CONFIG_OF_CONTROL
 248        fdtdec_check_fdt,
 249#endif
 250#if defined(CONFIG_BOARD_EARLY_INIT_F)
 251        board_early_init_f,
 252#endif
 253        timer_init,             /* initialize timer */
 254#ifdef CONFIG_BOARD_POSTCLK_INIT
 255        board_postclk_init,
 256#endif
 257#ifdef CONFIG_FSL_ESDHC
 258        get_clocks,
 259#endif
 260        env_init,               /* initialize environment */
 261        init_baudrate,          /* initialze baudrate settings */
 262        serial_init,            /* serial communications setup */
 263        console_init_f,         /* stage 1 init of console */
 264        display_banner,         /* say that we are here */
 265#if defined(CONFIG_DISPLAY_CPUINFO)
 266        print_cpuinfo,          /* display cpu info (and speed) */
 267#endif
 268#if defined(CONFIG_DISPLAY_BOARDINFO)
 269        checkboard,             /* display board info */
 270#endif
 271#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
 272        init_func_i2c,
 273#endif
 274        dram_init,              /* configure available RAM banks */
 275        NULL,
 276};
 277
 278void board_init_f(ulong bootflag)
 279{
 280        bd_t *bd;
 281        init_fnc_t **init_fnc_ptr;
 282        gd_t *id;
 283        ulong addr, addr_sp;
 284#ifdef CONFIG_PRAM
 285        ulong reg;
 286#endif
 287        void *new_fdt = NULL;
 288        size_t fdt_size = 0;
 289
 290        memset((void *)gd, 0, sizeof(gd_t));
 291
 292        gd->mon_len = _bss_end_ofs;
 293#ifdef CONFIG_OF_EMBED
 294        /* Get a pointer to the FDT */
 295        gd->fdt_blob = _binary_dt_dtb_start;
 296#elif defined CONFIG_OF_SEPARATE
 297        /* FDT is at end of image */
 298        gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
 299#endif
 300        /* Allow the early environment to override the fdt address */
 301        gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
 302                                                (uintptr_t)gd->fdt_blob);
 303
 304        for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 305                if ((*init_fnc_ptr)() != 0) {
 306                        hang ();
 307                }
 308        }
 309
 310#ifdef CONFIG_OF_CONTROL
 311        /* For now, put this check after the console is ready */
 312        if (fdtdec_prepare_fdt()) {
 313                panic("** CONFIG_OF_CONTROL defined but no FDT - please see "
 314                        "doc/README.fdt-control");
 315        }
 316#endif
 317
 318        debug("monitor len: %08lX\n", gd->mon_len);
 319        /*
 320         * Ram is setup, size stored in gd !!
 321         */
 322        debug("ramsize: %08lX\n", gd->ram_size);
 323#if defined(CONFIG_SYS_MEM_TOP_HIDE)
 324        /*
 325         * Subtract specified amount of memory to hide so that it won't
 326         * get "touched" at all by U-Boot. By fixing up gd->ram_size
 327         * the Linux kernel should now get passed the now "corrected"
 328         * memory size and won't touch it either. This should work
 329         * for arch/ppc and arch/powerpc. Only Linux board ports in
 330         * arch/powerpc with bootwrapper support, that recalculate the
 331         * memory size from the SDRAM controller setup will have to
 332         * get fixed.
 333         */
 334        gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
 335#endif
 336
 337        addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
 338
 339#ifdef CONFIG_LOGBUFFER
 340#ifndef CONFIG_ALT_LB_ADDR
 341        /* reserve kernel log buffer */
 342        addr -= (LOGBUFF_RESERVE);
 343        debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN,
 344                addr);
 345#endif
 346#endif
 347
 348#ifdef CONFIG_PRAM
 349        /*
 350         * reserve protected RAM
 351         */
 352        reg = getenv_ulong("pram", 10, CONFIG_PRAM);
 353        addr -= (reg << 10);            /* size is in kB */
 354        debug("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
 355#endif /* CONFIG_PRAM */
 356
 357#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
 358        /* reserve TLB table */
 359        gd->arch.tlb_size = 4096 * 4;
 360        addr -= gd->arch.tlb_size;
 361
 362        /* round down to next 64 kB limit */
 363        addr &= ~(0x10000 - 1);
 364
 365        gd->arch.tlb_addr = addr;
 366        debug("TLB table from %08lx to %08lx\n", addr, addr + gd->arch.tlb_size);
 367#endif
 368
 369        /* round down to next 4 kB limit */
 370        addr &= ~(4096 - 1);
 371        debug("Top of RAM usable for U-Boot at: %08lx\n", addr);
 372
 373#ifdef CONFIG_LCD
 374#ifdef CONFIG_FB_ADDR
 375        gd->fb_base = CONFIG_FB_ADDR;
 376#else
 377        /* reserve memory for LCD display (always full pages) */
 378        addr = lcd_setmem(addr);
 379        gd->fb_base = addr;
 380#endif /* CONFIG_FB_ADDR */
 381#endif /* CONFIG_LCD */
 382
 383        /*
 384         * reserve memory for U-Boot code, data & bss
 385         * round down to next 4 kB limit
 386         */
 387        addr -= gd->mon_len;
 388        addr &= ~(4096 - 1);
 389
 390        debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);
 391
 392#ifndef CONFIG_SPL_BUILD
 393        /*
 394         * reserve memory for malloc() arena
 395         */
 396        addr_sp = addr - TOTAL_MALLOC_LEN;
 397        debug("Reserving %dk for malloc() at: %08lx\n",
 398                        TOTAL_MALLOC_LEN >> 10, addr_sp);
 399        /*
 400         * (permanently) allocate a Board Info struct
 401         * and a permanent copy of the "global" data
 402         */
 403        addr_sp -= sizeof (bd_t);
 404        bd = (bd_t *) addr_sp;
 405        gd->bd = bd;
 406        debug("Reserving %zu Bytes for Board Info at: %08lx\n",
 407                        sizeof (bd_t), addr_sp);
 408
 409#ifdef CONFIG_MACH_TYPE
 410        gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
 411#endif
 412
 413        addr_sp -= sizeof (gd_t);
 414        id = (gd_t *) addr_sp;
 415        debug("Reserving %zu Bytes for Global Data at: %08lx\n",
 416                        sizeof (gd_t), addr_sp);
 417
 418#if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL)
 419        /*
 420         * If the device tree is sitting immediate above our image then we
 421         * must relocate it. If it is embedded in the data section, then it
 422         * will be relocated with other data.
 423         */
 424        if (gd->fdt_blob) {
 425                fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);
 426
 427                addr_sp -= fdt_size;
 428                new_fdt = (void *)addr_sp;
 429                debug("Reserving %zu Bytes for FDT at: %08lx\n",
 430                      fdt_size, addr_sp);
 431        }
 432#endif
 433
 434        /* setup stackpointer for exeptions */
 435        gd->irq_sp = addr_sp;
 436#ifdef CONFIG_USE_IRQ
 437        addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
 438        debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",
 439                CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);
 440#endif
 441        /* leave 3 words for abort-stack    */
 442        addr_sp -= 12;
 443
 444        /* 8-byte alignment for ABI compliance */
 445        addr_sp &= ~0x07;
 446#else
 447        addr_sp += 128; /* leave 32 words for abort-stack   */
 448        gd->irq_sp = addr_sp;
 449#endif
 450
 451        debug("New Stack Pointer is: %08lx\n", addr_sp);
 452
 453#ifdef CONFIG_POST
 454        post_bootmode_init();
 455        post_run(NULL, POST_ROM | post_bootmode_get(0));
 456#endif
 457
 458        gd->bd->bi_baudrate = gd->baudrate;
 459        /* Ram ist board specific, so move it to board code ... */
 460        dram_init_banksize();
 461        display_dram_config();  /* and display it */
 462
 463        gd->relocaddr = addr;
 464        gd->start_addr_sp = addr_sp;
 465        gd->reloc_off = addr - _TEXT_BASE;
 466        debug("relocation Offset is: %08lx\n", gd->reloc_off);
 467        if (new_fdt) {
 468                memcpy(new_fdt, gd->fdt_blob, fdt_size);
 469                gd->fdt_blob = new_fdt;
 470        }
 471        memcpy(id, (void *)gd, sizeof(gd_t));
 472}
 473
 474#if !defined(CONFIG_SYS_NO_FLASH)
 475static char *failed = "*** failed ***\n";
 476#endif
 477
 478/*
 479 * Tell if it's OK to load the environment early in boot.
 480 *
 481 * If CONFIG_OF_CONFIG is defined, we'll check with the FDT to see
 482 * if this is OK (defaulting to saying it's not OK).
 483 *
 484 * NOTE: Loading the environment early can be a bad idea if security is
 485 *       important, since no verification is done on the environment.
 486 *
 487 * @return 0 if environment should not be loaded, !=0 if it is ok to load
 488 */
 489static int should_load_env(void)
 490{
 491#ifdef CONFIG_OF_CONTROL
 492        return fdtdec_get_config_int(gd->fdt_blob, "load-environment", 1);
 493#elif defined CONFIG_DELAY_ENVIRONMENT
 494        return 0;
 495#else
 496        return 1;
 497#endif
 498}
 499
 500#if defined(CONFIG_DISPLAY_BOARDINFO_LATE) && defined(CONFIG_OF_CONTROL)
 501static void display_fdt_model(const void *blob)
 502{
 503        const char *model;
 504
 505        model = (char *)fdt_getprop(blob, 0, "model", NULL);
 506        printf("Model: %s\n", model ? model : "<unknown>");
 507}
 508#endif
 509
 510/************************************************************************
 511 *
 512 * This is the next part if the initialization sequence: we are now
 513 * running from RAM and have a "normal" C environment, i. e. global
 514 * data can be written, BSS has been cleared, the stack size in not
 515 * that critical any more, etc.
 516 *
 517 ************************************************************************
 518 */
 519
 520void board_init_r(gd_t *id, ulong dest_addr)
 521{
 522        ulong malloc_start;
 523#if !defined(CONFIG_SYS_NO_FLASH)
 524        ulong flash_size;
 525#endif
 526
 527        gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
 528        bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
 529
 530        monitor_flash_len = _end_ofs;
 531
 532        /* Enable caches */
 533        enable_caches();
 534
 535        debug("monitor flash len: %08lX\n", monitor_flash_len);
 536        board_init();   /* Setup chipselects */
 537        /*
 538         * TODO: printing of the clock inforamtion of the board is now
 539         * implemented as part of bdinfo command. Currently only support for
 540         * davinci SOC's is added. Remove this check once all the board
 541         * implement this.
 542         */
 543#ifdef CONFIG_CLOCKS
 544        set_cpu_clk_info(); /* Setup clock information */
 545#endif
 546        serial_initialize();
 547
 548        debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
 549
 550#ifdef CONFIG_LOGBUFFER
 551        logbuff_init_ptrs();
 552#endif
 553#ifdef CONFIG_POST
 554        post_output_backlog();
 555#endif
 556
 557        /* The Malloc area is immediately below the monitor copy in DRAM */
 558        malloc_start = dest_addr - TOTAL_MALLOC_LEN;
 559        mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
 560
 561#ifdef CONFIG_ARCH_EARLY_INIT_R
 562        arch_early_init_r();
 563#endif
 564        power_init_board();
 565
 566#if !defined(CONFIG_SYS_NO_FLASH)
 567        puts("Flash: ");
 568
 569        flash_size = flash_init();
 570        if (flash_size > 0) {
 571# ifdef CONFIG_SYS_FLASH_CHECKSUM
 572                print_size(flash_size, "");
 573                /*
 574                 * Compute and print flash CRC if flashchecksum is set to 'y'
 575                 *
 576                 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
 577                 */
 578                if (getenv_yesno("flashchecksum") == 1) {
 579                        printf("  CRC: %08X", crc32(0,
 580                                (const unsigned char *) CONFIG_SYS_FLASH_BASE,
 581                                flash_size));
 582                }
 583                putc('\n');
 584# else  /* !CONFIG_SYS_FLASH_CHECKSUM */
 585                print_size(flash_size, "\n");
 586# endif /* CONFIG_SYS_FLASH_CHECKSUM */
 587        } else {
 588                puts(failed);
 589                hang();
 590        }
 591#endif
 592
 593#if defined(CONFIG_CMD_NAND)
 594        puts("NAND:  ");
 595        nand_init();            /* go init the NAND */
 596#endif
 597
 598#if defined(CONFIG_CMD_ONENAND)
 599        onenand_init();
 600#endif
 601
 602#ifdef CONFIG_GENERIC_MMC
 603        puts("MMC:   ");
 604        mmc_initialize(gd->bd);
 605#endif
 606
 607#ifdef CONFIG_HAS_DATAFLASH
 608        AT91F_DataflashInit();
 609        dataflash_print_info();
 610#endif
 611
 612        /* initialize environment */
 613        if (should_load_env())
 614                env_relocate();
 615        else
 616                set_default_env(NULL);
 617
 618#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI)
 619        arm_pci_init();
 620#endif
 621
 622        stdio_init();   /* get the devices list going. */
 623
 624        jumptable_init();
 625
 626#if defined(CONFIG_API)
 627        /* Initialize API */
 628        api_init();
 629#endif
 630
 631        console_init_r();       /* fully init console as a device */
 632
 633#ifdef CONFIG_DISPLAY_BOARDINFO_LATE
 634# ifdef CONFIG_OF_CONTROL
 635        /* Put this here so it appears on the LCD, now it is ready */
 636        display_fdt_model(gd->fdt_blob);
 637# else
 638        checkboard();
 639# endif
 640#endif
 641
 642#if defined(CONFIG_ARCH_MISC_INIT)
 643        /* miscellaneous arch dependent initialisations */
 644        arch_misc_init();
 645#endif
 646#if defined(CONFIG_MISC_INIT_R)
 647        /* miscellaneous platform dependent initialisations */
 648        misc_init_r();
 649#endif
 650
 651         /* set up exceptions */
 652        interrupt_init();
 653        /* enable exceptions */
 654        enable_interrupts();
 655
 656        /* Initialize from environment */
 657        load_addr = getenv_ulong("loadaddr", 16, load_addr);
 658
 659#ifdef CONFIG_BOARD_LATE_INIT
 660        board_late_init();
 661#endif
 662
 663#ifdef CONFIG_BITBANGMII
 664        bb_miiphy_init();
 665#endif
 666#if defined(CONFIG_CMD_NET)
 667        puts("Net:   ");
 668        eth_initialize(gd->bd);
 669#if defined(CONFIG_RESET_PHY_R)
 670        debug("Reset Ethernet PHY\n");
 671        reset_phy();
 672#endif
 673#endif
 674
 675#ifdef CONFIG_POST
 676        post_run(NULL, POST_RAM | post_bootmode_get(0));
 677#endif
 678
 679#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
 680        /*
 681         * Export available size of memory for Linux,
 682         * taking into account the protected RAM at top of memory
 683         */
 684        {
 685                ulong pram = 0;
 686                uchar memsz[32];
 687
 688#ifdef CONFIG_PRAM
 689                pram = getenv_ulong("pram", 10, CONFIG_PRAM);
 690#endif
 691#ifdef CONFIG_LOGBUFFER
 692#ifndef CONFIG_ALT_LB_ADDR
 693                /* Also take the logbuffer into account (pram is in kB) */
 694                pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024;
 695#endif
 696#endif
 697                sprintf((char *)memsz, "%ldk", (gd->ram_size / 1024) - pram);
 698                setenv("mem", (char *)memsz);
 699        }
 700#endif
 701
 702        /* main_loop() can return to retry autoboot, if so just run it again. */
 703        for (;;) {
 704                main_loop();
 705        }
 706
 707        /* NOTREACHED - no way out of command loop except booting */
 708}
 709