uboot/arch/arm/cpu/armv7/exynos/spl_boot.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Samsung Electronics
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include<common.h>
   8#include<config.h>
   9
  10#include <asm/arch/clock.h>
  11#include <asm/arch/clk.h>
  12#include <asm/arch/dmc.h>
  13#include <asm/arch/power.h>
  14#include <asm/arch/spl.h>
  15
  16#include "common_setup.h"
  17#include "clock_init.h"
  18
  19DECLARE_GLOBAL_DATA_PTR;
  20#define OM_STAT         (0x1f << 1)
  21
  22/* Index into irom ptr table */
  23enum index {
  24        MMC_INDEX,
  25        EMMC44_INDEX,
  26        EMMC44_END_INDEX,
  27        SPI_INDEX,
  28        USB_INDEX,
  29};
  30
  31/* IROM Function Pointers Table */
  32u32 irom_ptr_table[] = {
  33        [MMC_INDEX] = 0x02020030,       /* iROM Function Pointer-SDMMC boot */
  34        [EMMC44_INDEX] = 0x02020044,    /* iROM Function Pointer-EMMC4.4 boot*/
  35        [EMMC44_END_INDEX] = 0x02020048,/* iROM Function Pointer
  36                                                -EMMC4.4 end boot operation */
  37        [SPI_INDEX] = 0x02020058,       /* iROM Function Pointer-SPI boot */
  38        [USB_INDEX] = 0x02020070,       /* iROM Function Pointer-USB boot*/
  39        };
  40
  41void *get_irom_func(int index)
  42{
  43        return (void *)*(u32 *)irom_ptr_table[index];
  44}
  45
  46#ifdef CONFIG_USB_BOOTING
  47/*
  48 * Set/clear program flow prediction and return the previous state.
  49 */
  50static int config_branch_prediction(int set_cr_z)
  51{
  52        unsigned int cr;
  53
  54        /* System Control Register: 11th bit Z Branch prediction enable */
  55        cr = get_cr();
  56        set_cr(set_cr_z ? cr | CR_Z : cr & ~CR_Z);
  57
  58        return cr & CR_Z;
  59}
  60#endif
  61
  62/*
  63* Copy U-boot from mmc to RAM:
  64* COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains
  65* Pointer to API (Data transfer from mmc to ram)
  66*/
  67void copy_uboot_to_ram(void)
  68{
  69        enum boot_mode bootmode = BOOT_MODE_OM;
  70
  71        u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL;
  72        u32 offset = 0, size = 0;
  73#ifdef CONFIG_SUPPORT_EMMC_BOOT
  74        u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst);
  75        void (*end_bootop_from_emmc)(void);
  76#endif
  77#ifdef CONFIG_USB_BOOTING
  78        u32 (*usb_copy)(void);
  79        int is_cr_z_set;
  80        unsigned int sec_boot_check;
  81
  82        /* Read iRAM location to check for secondary USB boot mode */
  83        sec_boot_check = readl(EXYNOS_IRAM_SECONDARY_BASE);
  84        if (sec_boot_check == EXYNOS_USB_SECONDARY_BOOT)
  85                bootmode = BOOT_MODE_USB;
  86#endif
  87
  88        if (bootmode == BOOT_MODE_OM)
  89                bootmode = readl(samsung_get_base_power()) & OM_STAT;
  90
  91        switch (bootmode) {
  92#ifdef CONFIG_SPI_BOOTING
  93        case BOOT_MODE_SERIAL:
  94                offset = SPI_FLASH_UBOOT_POS;
  95                size = CONFIG_BL2_SIZE;
  96                copy_bl2 = get_irom_func(SPI_INDEX);
  97                break;
  98#endif
  99        case BOOT_MODE_MMC:
 100                offset = BL2_START_OFFSET;
 101                size = BL2_SIZE_BLOC_COUNT;
 102                copy_bl2 = get_irom_func(MMC_INDEX);
 103                break;
 104#ifdef CONFIG_SUPPORT_EMMC_BOOT
 105        case BOOT_MODE_EMMC:
 106                /* Set the FSYS1 clock divisor value for EMMC boot */
 107                emmc_boot_clk_div_set();
 108
 109                copy_bl2_from_emmc = get_irom_func(EMMC44_INDEX);
 110                end_bootop_from_emmc = get_irom_func(EMMC44_END_INDEX);
 111
 112                copy_bl2_from_emmc(BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE);
 113                end_bootop_from_emmc();
 114                break;
 115#endif
 116#ifdef CONFIG_USB_BOOTING
 117        case BOOT_MODE_USB:
 118                /*
 119                 * iROM needs program flow prediction to be disabled
 120                 * before copy from USB device to RAM
 121                 */
 122                is_cr_z_set = config_branch_prediction(0);
 123                usb_copy = get_irom_func(USB_INDEX);
 124                usb_copy();
 125                config_branch_prediction(is_cr_z_set);
 126                break;
 127#endif
 128        default:
 129                break;
 130        }
 131
 132        if (copy_bl2)
 133                copy_bl2(offset, size, CONFIG_SYS_TEXT_BASE);
 134}
 135
 136void memzero(void *s, size_t n)
 137{
 138        char *ptr = s;
 139        size_t i;
 140
 141        for (i = 0; i < n; i++)
 142                *ptr++ = '\0';
 143}
 144
 145/**
 146 * Set up the U-Boot global_data pointer
 147 *
 148 * This sets the address of the global data, and sets up basic values.
 149 *
 150 * @param gdp   Value to give to gd
 151 */
 152static void setup_global_data(gd_t *gdp)
 153{
 154        gd = gdp;
 155        memzero((void *)gd, sizeof(gd_t));
 156        gd->flags |= GD_FLG_RELOC;
 157        gd->baudrate = CONFIG_BAUDRATE;
 158        gd->have_console = 1;
 159}
 160
 161void board_init_f(unsigned long bootflag)
 162{
 163        __aligned(8) gd_t local_gd;
 164        __attribute__((noreturn)) void (*uboot)(void);
 165
 166        setup_global_data(&local_gd);
 167
 168        if (do_lowlevel_init())
 169                power_exit_wakeup();
 170
 171        copy_uboot_to_ram();
 172
 173        /* Jump to U-Boot image */
 174        uboot = (void *)CONFIG_SYS_TEXT_BASE;
 175        (*uboot)();
 176        /* Never returns Here */
 177}
 178
 179/* Place Holders */
 180void board_init_r(gd_t *id, ulong dest_addr)
 181{
 182        /* Function attribute is no-return */
 183        /* This Function never executes */
 184        while (1)
 185                ;
 186}
 187void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {}
 188