uboot/arch/m68k/lib/board.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003
   3 * Josef Baumgartner <josef.baumgartner@telex.de>
   4 *
   5 * (C) Copyright 2000-2002
   6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12#include <watchdog.h>
  13#include <command.h>
  14#include <malloc.h>
  15#include <stdio_dev.h>
  16#include <linux/compiler.h>
  17
  18#include <asm/immap.h>
  19
  20#if defined(CONFIG_CMD_IDE)
  21#include <ide.h>
  22#endif
  23#if defined(CONFIG_CMD_SCSI)
  24#include <scsi.h>
  25#endif
  26#if defined(CONFIG_CMD_KGDB)
  27#include <kgdb.h>
  28#endif
  29#ifdef CONFIG_STATUS_LED
  30#include <status_led.h>
  31#endif
  32#include <net.h>
  33#include <serial.h>
  34#if defined(CONFIG_CMD_BEDBUG)
  35#include <cmd_bedbug.h>
  36#endif
  37#ifdef CONFIG_SYS_ALLOC_DPRAM
  38#include <commproc.h>
  39#endif
  40#include <version.h>
  41
  42#if defined(CONFIG_HARD_I2C) || \
  43        defined(CONFIG_SYS_I2C)
  44#include <i2c.h>
  45#endif
  46
  47#ifdef CONFIG_CMD_SPI
  48#include <spi.h>
  49#endif
  50
  51#ifdef CONFIG_BITBANGMII
  52#include <miiphy.h>
  53#endif
  54
  55#include <nand.h>
  56
  57DECLARE_GLOBAL_DATA_PTR;
  58
  59static char *failed = "*** failed ***\n";
  60
  61#include <environment.h>
  62
  63extern ulong __init_end;
  64extern ulong __bss_end;
  65
  66#if defined(CONFIG_WATCHDOG)
  67# undef INIT_FUNC_WATCHDOG_INIT
  68# define INIT_FUNC_WATCHDOG_INIT        watchdog_init,
  69# define WATCHDOG_DISABLE               watchdog_disable
  70
  71extern int watchdog_init(void);
  72extern int watchdog_disable(void);
  73#else
  74# define INIT_FUNC_WATCHDOG_INIT        /* undef */
  75# define WATCHDOG_DISABLE               /* undef */
  76#endif /* CONFIG_WATCHDOG */
  77
  78ulong monitor_flash_len;
  79
  80/************************************************************************
  81 * Utilities                                                            *
  82 ************************************************************************
  83 */
  84
  85/*
  86 * All attempts to come up with a "common" initialization sequence
  87 * that works for all boards and architectures failed: some of the
  88 * requirements are just _too_ different. To get rid of the resulting
  89 * mess of board dependend #ifdef'ed code we now make the whole
  90 * initialization sequence configurable to the user.
  91 *
  92 * The requirements for any new initalization function is simple: it
  93 * receives a pointer to the "global data" structure as it's only
  94 * argument, and returns an integer return code, where 0 means
  95 * "continue" and != 0 means "fatal error, hang the system".
  96 */
  97typedef int (init_fnc_t) (void);
  98
  99/************************************************************************
 100 * Init Utilities
 101 ************************************************************************
 102 * Some of this code should be moved into the core functions,
 103 * but let's get it working (again) first...
 104 */
 105
 106static int init_baudrate (void)
 107{
 108        gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
 109        return 0;
 110}
 111
 112/***********************************************************************/
 113
 114static int init_func_ram (void)
 115{
 116        int board_type = 0;     /* use dummy arg */
 117        puts ("DRAM:  ");
 118
 119        if ((gd->ram_size = initdram (board_type)) > 0) {
 120                print_size (gd->ram_size, "\n");
 121                return (0);
 122        }
 123        puts (failed);
 124        return (1);
 125}
 126
 127/***********************************************************************/
 128
 129#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
 130static int init_func_i2c (void)
 131{
 132        puts ("I2C:   ");
 133#ifdef CONFIG_SYS_I2C
 134        i2c_init_all();
 135#else
 136        i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 137#endif
 138        puts ("ready\n");
 139        return (0);
 140}
 141#endif
 142
 143#if defined(CONFIG_HARD_SPI)
 144static int init_func_spi (void)
 145{
 146        puts ("SPI:   ");
 147        spi_init ();
 148        puts ("ready\n");
 149        return (0);
 150}
 151#endif
 152
 153/***********************************************************************/
 154
 155/************************************************************************
 156 * Initialization sequence                                              *
 157 ************************************************************************
 158 */
 159
 160init_fnc_t *init_sequence[] = {
 161        get_clocks,
 162        env_init,
 163        init_baudrate,
 164        serial_init,
 165        console_init_f,
 166        display_options,
 167        checkcpu,
 168        checkboard,
 169#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
 170        init_func_i2c,
 171#endif
 172#if defined(CONFIG_HARD_SPI)
 173        init_func_spi,
 174#endif
 175        init_func_ram,
 176#if defined(CONFIG_SYS_DRAM_TEST)
 177        testdram,
 178#endif /* CONFIG_SYS_DRAM_TEST */
 179        INIT_FUNC_WATCHDOG_INIT
 180        NULL,                   /* Terminate this list */
 181};
 182
 183
 184/************************************************************************
 185 *
 186 * This is the first part of the initialization sequence that is
 187 * implemented in C, but still running from ROM.
 188 *
 189 * The main purpose is to provide a (serial) console interface as
 190 * soon as possible (so we can see any error messages), and to
 191 * initialize the RAM so that we can relocate the monitor code to
 192 * RAM.
 193 *
 194 * Be aware of the restrictions: global data is read-only, BSS is not
 195 * initialized, and stack space is limited to a few kB.
 196 *
 197 ************************************************************************
 198 */
 199
 200void
 201board_init_f (ulong bootflag)
 202{
 203        bd_t *bd;
 204        ulong len, addr, addr_sp;
 205        ulong *paddr;
 206        gd_t *id;
 207        init_fnc_t **init_fnc_ptr;
 208#ifdef CONFIG_PRAM
 209        ulong reg;
 210#endif
 211
 212        /* Pointer is writable since we allocated a register for it */
 213        gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
 214        /* compiler optimization barrier needed for GCC >= 3.4 */
 215        __asm__ __volatile__("": : :"memory");
 216
 217        /* Clear initial global data */
 218        memset ((void *) gd, 0, sizeof (gd_t));
 219
 220        for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 221                if ((*init_fnc_ptr)() != 0) {
 222                        hang ();
 223                }
 224        }
 225
 226        /*
 227         * Now that we have DRAM mapped and working, we can
 228         * relocate the code and continue running from DRAM.
 229         *
 230         * Reserve memory at end of RAM for (top down in that order):
 231         *      - protected RAM
 232         *      - LCD framebuffer
 233         *      - monitor code
 234         *      - board info struct
 235         */
 236        len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE;
 237
 238        addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
 239
 240#ifdef CONFIG_LOGBUFFER
 241        /* reserve kernel log buffer */
 242        addr -= (LOGBUFF_RESERVE);
 243        debug ("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr);
 244#endif
 245
 246#ifdef CONFIG_PRAM
 247        /*
 248         * reserve protected RAM
 249         */
 250        reg = getenv_ulong("pram", 10, CONFIG_PRAM);
 251        addr -= (reg << 10);            /* size is in kB */
 252        debug ("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
 253#endif /* CONFIG_PRAM */
 254
 255        /* round down to next 4 kB limit */
 256        addr &= ~(4096 - 1);
 257        debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
 258
 259#ifdef CONFIG_LCD
 260#ifdef CONFIG_FB_ADDR
 261        gd->fb_base = CONFIG_FB_ADDR;
 262#else
 263        /* reserve memory for LCD display (always full pages) */
 264        addr = lcd_setmem (addr);
 265        gd->fb_base = addr;
 266#endif /* CONFIG_FB_ADDR */
 267#endif /* CONFIG_LCD */
 268
 269        /*
 270         * reserve memory for U-Boot code, data & bss
 271         * round down to next 4 kB limit
 272         */
 273        addr -= len;
 274        addr &= ~(4096 - 1);
 275
 276        debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
 277
 278        /*
 279         * reserve memory for malloc() arena
 280         */
 281        addr_sp = addr - TOTAL_MALLOC_LEN;
 282        debug ("Reserving %dk for malloc() at: %08lx\n",
 283                        TOTAL_MALLOC_LEN >> 10, addr_sp);
 284
 285        /*
 286         * (permanently) allocate a Board Info struct
 287         * and a permanent copy of the "global" data
 288         */
 289        addr_sp -= sizeof (bd_t);
 290        bd = (bd_t *) addr_sp;
 291        gd->bd = bd;
 292        debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
 293                        sizeof (bd_t), addr_sp);
 294        addr_sp -= sizeof (gd_t);
 295        id = (gd_t *) addr_sp;
 296        debug ("Reserving %zu Bytes for Global Data at: %08lx\n",
 297                        sizeof (gd_t), addr_sp);
 298
 299        /* Reserve memory for boot params. */
 300        addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;
 301        bd->bi_boot_params = addr_sp;
 302        debug ("Reserving %dk for boot parameters at: %08lx\n",
 303                        CONFIG_SYS_BOOTPARAMS_LEN >> 10, addr_sp);
 304
 305        /*
 306         * Finally, we set up a new (bigger) stack.
 307         *
 308         * Leave some safety gap for SP, force alignment on 16 byte boundary
 309         * Clear initial stack frame
 310         */
 311        addr_sp -= 16;
 312        addr_sp &= ~0xF;
 313
 314        paddr = (ulong *)addr_sp;
 315        *paddr-- = 0;
 316        *paddr-- = 0;
 317        addr_sp = (ulong)paddr;
 318
 319        debug ("Stack Pointer at: %08lx\n", addr_sp);
 320
 321        /*
 322         * Save local variables to board info struct
 323         */
 324        bd->bi_memstart  = CONFIG_SYS_SDRAM_BASE;       /* start of  DRAM memory      */
 325        bd->bi_memsize   = gd->ram_size;        /* size  of  DRAM memory in bytes */
 326#ifdef CONFIG_SYS_INIT_RAM_ADDR
 327        bd->bi_sramstart = CONFIG_SYS_INIT_RAM_ADDR;    /* start of  SRAM memory        */
 328        bd->bi_sramsize  = CONFIG_SYS_INIT_RAM_SIZE;    /* size  of  SRAM memory        */
 329#endif
 330        bd->bi_mbar_base = CONFIG_SYS_MBAR;             /* base of internal registers */
 331
 332        bd->bi_bootflags = bootflag;            /* boot / reboot flag (for LynxOS)    */
 333
 334        WATCHDOG_RESET ();
 335        bd->bi_intfreq = gd->cpu_clk;   /* Internal Freq, in Hz */
 336        bd->bi_busfreq = gd->bus_clk;   /* Bus Freq,      in Hz */
 337#ifdef CONFIG_PCI
 338        bd->bi_pcifreq = gd->pci_clk;           /* PCI Freq in Hz */
 339#endif
 340#ifdef CONFIG_EXTRA_CLOCK
 341        bd->bi_inpfreq = gd->arch.inp_clk;              /* input Freq in Hz */
 342        bd->bi_vcofreq = gd->arch.vco_clk;              /* vco Freq in Hz */
 343        bd->bi_flbfreq = gd->arch.flb_clk;              /* flexbus Freq in Hz */
 344#endif
 345        bd->bi_baudrate = gd->baudrate; /* Console Baudrate     */
 346
 347#ifdef CONFIG_SYS_EXTBDINFO
 348        strncpy (bd->bi_s_version, "1.2", sizeof (bd->bi_s_version));
 349        strncpy (bd->bi_r_version, U_BOOT_VERSION, sizeof (bd->bi_r_version));
 350#endif
 351
 352        WATCHDOG_RESET ();
 353
 354#ifdef CONFIG_POST
 355        post_bootmode_init();
 356        post_run (NULL, POST_ROM | post_bootmode_get(0));
 357#endif
 358
 359        WATCHDOG_RESET();
 360
 361        memcpy (id, (void *)gd, sizeof (gd_t));
 362
 363        debug ("Start relocate of code from %08x to %08lx\n", CONFIG_SYS_MONITOR_BASE, addr);
 364        relocate_code (addr_sp, id, addr);
 365
 366        /* NOTREACHED - jump_to_ram() does not return */
 367}
 368
 369/************************************************************************
 370 *
 371 * This is the next part if the initialization sequence: we are now
 372 * running from RAM and have a "normal" C environment, i. e. global
 373 * data can be written, BSS has been cleared, the stack size in not
 374 * that critical any more, etc.
 375 *
 376 ************************************************************************
 377 */
 378void board_init_r (gd_t *id, ulong dest_addr)
 379{
 380        char *s __maybe_unused;
 381        bd_t *bd;
 382
 383#ifndef CONFIG_ENV_IS_NOWHERE
 384        extern char * env_name_spec;
 385#endif
 386#ifndef CONFIG_SYS_NO_FLASH
 387        ulong flash_size;
 388#endif
 389        gd = id;                /* initialize RAM version of global data */
 390        bd = gd->bd;
 391
 392        gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
 393
 394        WATCHDOG_RESET ();
 395
 396        gd->reloc_off =  dest_addr - CONFIG_SYS_MONITOR_BASE;
 397
 398        serial_initialize();
 399
 400        debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
 401
 402        monitor_flash_len = (ulong)&__init_end - dest_addr;
 403
 404#if defined(CONFIG_NEEDS_MANUAL_RELOC)
 405        /*
 406         * We have to relocate the command table manually
 407         */
 408        fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd),
 409                        ll_entry_count(cmd_tbl_t, cmd));
 410#endif /* defined(CONFIG_NEEDS_MANUAL_RELOC) */
 411
 412        /* there are some other pointer constants we must deal with */
 413#ifndef CONFIG_ENV_IS_NOWHERE
 414        env_name_spec += gd->reloc_off;
 415#endif
 416
 417        WATCHDOG_RESET ();
 418
 419#ifdef CONFIG_LOGBUFFER
 420        logbuff_init_ptrs ();
 421#endif
 422#ifdef CONFIG_POST
 423        post_output_backlog ();
 424        post_reloc ();
 425#endif
 426        WATCHDOG_RESET();
 427
 428#if 0
 429        /* instruction cache enabled in cpu_init_f() for faster relocation */
 430        icache_enable ();       /* it's time to enable the instruction cache */
 431#endif
 432
 433        /*
 434         * Setup trap handlers
 435         */
 436        trap_init (CONFIG_SYS_SDRAM_BASE);
 437
 438        /* The Malloc area is immediately below the monitor copy in DRAM */
 439        mem_malloc_init (CONFIG_SYS_MONITOR_BASE + gd->reloc_off -
 440                        TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);
 441
 442#if !defined(CONFIG_SYS_NO_FLASH)
 443        puts ("Flash: ");
 444
 445        if ((flash_size = flash_init ()) > 0) {
 446# ifdef CONFIG_SYS_FLASH_CHECKSUM
 447                print_size (flash_size, "");
 448                /*
 449                 * Compute and print flash CRC if flashchecksum is set to 'y'
 450                 *
 451                 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
 452                 */
 453                if (getenv_yesno("flashchecksum") == 1) {
 454                        printf ("  CRC: %08X",
 455                                        crc32 (0,
 456                                                   (const unsigned char *) CONFIG_SYS_FLASH_BASE,
 457                                                   flash_size)
 458                                        );
 459                }
 460                putc ('\n');
 461# else  /* !CONFIG_SYS_FLASH_CHECKSUM */
 462                print_size (flash_size, "\n");
 463# endif /* CONFIG_SYS_FLASH_CHECKSUM */
 464        } else {
 465                puts (failed);
 466                hang ();
 467        }
 468
 469        bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;      /* update start of FLASH memory    */
 470        bd->bi_flashsize = flash_size;  /* size of FLASH memory (final value) */
 471        bd->bi_flashoffset = 0;
 472#else   /* CONFIG_SYS_NO_FLASH */
 473        bd->bi_flashsize = 0;
 474        bd->bi_flashstart = 0;
 475        bd->bi_flashoffset = 0;
 476#endif /* !CONFIG_SYS_NO_FLASH */
 477
 478        WATCHDOG_RESET ();
 479
 480        /* initialize higher level parts of CPU like time base and timers */
 481        cpu_init_r ();
 482
 483        WATCHDOG_RESET ();
 484
 485#ifdef CONFIG_SPI
 486# if !defined(CONFIG_ENV_IS_IN_EEPROM)
 487        spi_init_f ();
 488# endif
 489        spi_init_r ();
 490#endif
 491
 492#if defined(CONFIG_SYS_I2C)
 493        /* Adjust I2C subsystem pointers after relocation */
 494        i2c_reloc_fixup();
 495#endif
 496
 497        /* relocate environment function pointers etc. */
 498        env_relocate ();
 499
 500        WATCHDOG_RESET ();
 501
 502#if defined(CONFIG_PCI)
 503        /*
 504         * Do pci configuration
 505         */
 506        pci_init ();
 507#endif
 508
 509        /** leave this here (after malloc(), environment and PCI are working) **/
 510        /* Initialize stdio devices */
 511        stdio_init ();
 512
 513        /* Initialize the jump table for applications */
 514        jumptable_init ();
 515
 516        /* Initialize the console (after the relocation and devices init) */
 517        console_init_r ();
 518
 519#if defined(CONFIG_MISC_INIT_R)
 520        /* miscellaneous platform dependent initialisations */
 521        misc_init_r ();
 522#endif
 523
 524#if defined(CONFIG_CMD_KGDB)
 525        WATCHDOG_RESET ();
 526        puts ("KGDB:  ");
 527        kgdb_init ();
 528#endif
 529
 530        debug ("U-Boot relocated to %08lx\n", dest_addr);
 531
 532        /*
 533         * Enable Interrupts
 534         */
 535        interrupt_init ();
 536
 537        /* Must happen after interrupts are initialized since
 538         * an irq handler gets installed
 539         */
 540        timer_init();
 541
 542#ifdef CONFIG_STATUS_LED
 543        status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
 544#endif
 545
 546        udelay (20);
 547
 548        /* Insert function pointers now that we have relocated the code */
 549
 550        /* Initialize from environment */
 551        load_addr = getenv_ulong("loadaddr", 16, load_addr);
 552
 553        WATCHDOG_RESET ();
 554
 555#if defined(CONFIG_CMD_DOC)
 556        WATCHDOG_RESET ();
 557        puts ("DOC:   ");
 558        doc_init ();
 559#endif
 560
 561#if defined(CONFIG_CMD_NAND)
 562        WATCHDOG_RESET ();
 563        puts ("NAND:  ");
 564        nand_init();            /* go init the NAND */
 565#endif
 566
 567#ifdef CONFIG_BITBANGMII
 568        bb_miiphy_init();
 569#endif
 570#if defined(CONFIG_CMD_NET)
 571        WATCHDOG_RESET();
 572#if defined(FEC_ENET)
 573        eth_init(bd);
 574#endif
 575        puts ("Net:   ");
 576        eth_initialize (bd);
 577#endif
 578
 579#ifdef CONFIG_POST
 580        post_run (NULL, POST_RAM | post_bootmode_get(0));
 581#endif
 582
 583#if defined(CONFIG_CMD_PCMCIA) \
 584    && !defined(CONFIG_CMD_IDE)
 585        WATCHDOG_RESET ();
 586        puts ("PCMCIA:");
 587        pcmcia_init ();
 588#endif
 589
 590#if defined(CONFIG_CMD_IDE)
 591        WATCHDOG_RESET ();
 592        puts ("IDE:   ");
 593        ide_init ();
 594#endif
 595
 596#ifdef CONFIG_LAST_STAGE_INIT
 597        WATCHDOG_RESET ();
 598        /*
 599         * Some parts can be only initialized if all others (like
 600         * Interrupts) are up and running (i.e. the PC-style ISA
 601         * keyboard).
 602         */
 603        last_stage_init ();
 604#endif
 605
 606#if defined(CONFIG_CMD_BEDBUG)
 607        WATCHDOG_RESET ();
 608        bedbug_init ();
 609#endif
 610
 611#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
 612        /*
 613         * Export available size of memory for Linux,
 614         * taking into account the protected RAM at top of memory
 615         */
 616        {
 617                ulong pram = 0;
 618                char memsz[32];
 619
 620#ifdef CONFIG_PRAM
 621                pram = getenv_ulong("pram", 10, CONFIG_PRAM);
 622#endif
 623#ifdef CONFIG_LOGBUFFER
 624                /* Also take the logbuffer into account (pram is in kB) */
 625                pram += (LOGBUFF_LEN+LOGBUFF_OVERHEAD)/1024;
 626#endif
 627                sprintf (memsz, "%ldk", (bd->bi_memsize / 1024) - pram);
 628                setenv ("mem", memsz);
 629        }
 630#endif
 631
 632#ifdef CONFIG_MODEM_SUPPORT
 633 {
 634         extern int do_mdm_init;
 635         do_mdm_init = gd->do_mdm_init;
 636 }
 637#endif
 638
 639#ifdef CONFIG_WATCHDOG
 640        /* disable watchdog if environment is set */
 641        if ((s = getenv ("watchdog")) != NULL) {
 642                if (strncmp (s, "off", 3) == 0) {
 643                        WATCHDOG_DISABLE ();
 644                }
 645        }
 646#endif /* CONFIG_WATCHDOG*/
 647
 648
 649        /* Initialization complete - start the monitor */
 650
 651        /* main_loop() can return to retry autoboot, if so just run it again. */
 652        for (;;) {
 653                WATCHDOG_RESET ();
 654                main_loop ();
 655        }
 656
 657        /* NOTREACHED - no way out of command loop except booting */
 658}
 659