1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 #include <config.h>
20 #include <linux/kconfig.h>
21 #include <asm/io.h>
22 #include <compiler.h>
23
24 /******************************************************************************/
25 extern void uart_early_init(void);
26 extern void uart_early_puts(const char *ss);
27 extern void reset_cpu(unsigned long addr);
28
29 extern void mmu_pagedir_init(unsigned long);
30 extern void mmu_pagedir_cached_range(unsigned long,
31 unsigned long, unsigned long);
32 extern void mmu_startup(unsigned long);
33
34 extern void dcache_flush_all(void);
35 extern void dcache_inv_all(void);
36 extern void mmu_turnoff(void);
37
38
39 /******************************************************************************/
40 const unsigned long IMAGE_ENTRY = (CONFIG_SYS_TEXT_BASE);
41
42 extern unsigned char input_data[];
43 extern unsigned char input_data_end[];
44 extern unsigned long _start;
45
46 /******************************************************************************/
47 #define error(_s) uart_early_puts(_s)
48 #define putstr(_s) uart_early_puts(_s)
49
50 #define large_malloc(_n) malloc(_n)
51 #define large_free(_n) free(_n)
52
53 /******************************************************************************/
54 /*
55 * this value will be (_start - CONFIG_SYS_MALLOC_LEN)
56 */
57 static long malloc_start_lzma;
58
59 /******************************************************************************/
malloc(unsigned int size)60 static void *malloc(unsigned int size)
61 {
62 void *ptr = (void *)malloc_start_lzma;
63 malloc_start_lzma += size;
64
65 if (malloc_start_lzma >= (unsigned long)&_start)
66 return NULL;
67
68 return ptr;
69 }
70 /******************************************************************************/
free(void * ptr)71 static void free(void *ptr)
72 {
73 }
74 /******************************************************************************/
75
76 #include "unlzma.c"
77
78 #ifndef CONFIG_SYS_ICACHE_OFF
79 /* Invalidate entire I-cache and branch predictor array */
invalidate_icache_all(void)80 static void invalidate_icache_all(void)
81 {
82 /*
83 * Invalidate all instruction caches to PoU.
84 * Also flushes branch target cache.
85 */
86 asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
87
88 /* Invalidate entire branch predictor array */
89 asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (0));
90
91 /* Full system DSB - make sure that the invalidation is complete */
92 dsb();
93
94 /* ISB - make sure the instruction stream sees it */
95 isb();
96 }
97 #else
invalidate_icache_all(void)98 static void invalidate_icache_all(void)
99 {
100 }
101 #endif
102
103 #ifdef CONFIG_EARLY_DCACHE_ENABLE
early_dcache_enable(void)104 static int early_dcache_enable(void)
105 {
106 unsigned long pdt = CONFIG_SYS_SDRAM_BASE + SZ_64K;
107 mmu_pagedir_init(pdt);
108 mmu_pagedir_cached_range(pdt, CONFIG_SYS_SDRAM_BASE, SZ_256M);
109 mmu_startup(pdt);
110
111 return 0;
112 }
113
early_dcache_disable(void)114 static int early_dcache_disable(void)
115 {
116 int i = 0;
117
118 dcache_flush_all();
119
120 /* mem barrier to sync up things */
121 asm("mcr p15, 0, %0, c7, c10, 4" : : "r"(i));
122
123 dcache_inv_all();
124
125 mmu_turnoff();
126
127 return 0;
128 }
129 #endif
130
131 /******************************************************************************/
start_armboot(void)132 void start_armboot(void)
133 {
134 unsigned char *pdst = (unsigned char *)(uintptr_t)IMAGE_ENTRY;
135 unsigned int image_data_len = input_data_end - input_data;
136
137 malloc_start_lzma = ((uintptr_t)&_start - CONFIG_SYS_MALLOC_LEN);
138 uart_early_init();
139
140 if (input_data[0] == 0x5D) {
141 uart_early_puts("\nUncompress");
142 //early_dcache_enable();
143 decompress(input_data, image_data_len, pdst);
144 //early_dcache_disable();
145 uart_early_puts("Ok\r\n");
146 } else {
147 int *s = (int *)input_data;
148 int *d = (int *)pdst;
149 unsigned int len = ((image_data_len + 3) >> 2);
150 while (len--)
151 *d++ = *s++;
152 }
153
154 void (*uboot)(void);
155 uboot = (void (*))CONFIG_SYS_TEXT_BASE;
156 invalidate_icache_all();
157 uboot();
158 }
159
160 /******************************************************************************/
hang(void)161 void hang(void)
162 {
163 uart_early_puts("### ERROR ### Please RESET the board ###\n");
164 for (;;)
165 ;
166 }
167
168
do_bad_sync(void)169 void do_bad_sync(void)
170 {
171 uart_early_puts("bad sync abort\r\n");
172 uart_early_puts("Resetting CPU ...\r\n");
173 reset_cpu(0);
174 }
175
do_sync(void)176 void do_sync(void)
177 {
178 uart_early_puts("sync abort\r\n");
179 uart_early_puts("Resetting CPU ...\r\n");
180 reset_cpu(0);
181 }
182
do_bad_error(void)183 void do_bad_error(void)
184 {
185 uart_early_puts("bad error\r\n");
186 uart_early_puts("Resetting CPU ...\r\n");
187 reset_cpu(0);
188 }
189
do_error(void)190 void do_error(void)
191 {
192 uart_early_puts("error\r\n");
193 uart_early_puts("Resetting CPU ...\r\n");
194 reset_cpu(0);
195 }
196
do_bad_fiq(void)197 void do_bad_fiq(void)
198 {
199 uart_early_puts("bad fast interrupt request\r\n");
200 uart_early_puts("Resetting CPU ...\r\n");
201 reset_cpu(0);
202 }
203
do_bad_irq(void)204 void do_bad_irq(void)
205 {
206 uart_early_puts("bad interrupt request\r\n");
207 uart_early_puts("Resetting CPU ...\r\n");
208 reset_cpu(0);
209 }
210
do_fiq(void)211 void do_fiq(void)
212 {
213 uart_early_puts("fast interrupt request\r\n");
214 uart_early_puts("Resetting CPU ...\r\n");
215 reset_cpu(0);
216 }
217
do_irq(void)218 void do_irq(void)
219 {
220 uart_early_puts("interrupt request\r\n");
221 uart_early_puts("Resetting CPU ...\r\n");
222 reset_cpu(0);
223 }
224