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