blob: 914259d9022a8f320638662bc0728d6da6f2d620 [file] [log] [blame]
xf.libfc6e712025-02-07 01:54:34 -08001/*
2 * (C) Copyright 2002
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <mgroeger@sysgo.de>
5 *
6 * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <common.h>
25#include <command.h>
26#include <image.h>
27#include <u-boot/zlib.h>
28#include <asm/byteorder.h>
29#include <fdt.h>
30#include <libfdt.h>
31#include <fdt_support.h>
32#include <bootimg.h>
33#include <load_image.h>
34#include <asm/arch/cpu.h>
35#include <asm/io.h>
36#include <fdt_support.h>
37#include <asm/arch/efuse.h>
38
39DECLARE_GLOBAL_DATA_PTR;
40
41#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
42 defined (CONFIG_CMDLINE_TAG) || \
43 defined (CONFIG_INITRD_TAG) || \
44 defined (CONFIG_SERIAL_TAG) || \
45 defined (CONFIG_REVISION_TAG)
46static void setup_start_tag (bd_t *bd);
47
48# ifdef CONFIG_SETUP_MEMORY_TAGS
49static void setup_memory_tags (bd_t *bd);
50# endif
51static void setup_commandline_tag (bd_t *bd, char *commandline);
52
53# ifdef CONFIG_INITRD_TAG
54static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
55 ulong initrd_end);
56# endif
57static void setup_end_tag (bd_t *bd);
58
59static struct tag *params;
60#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
61
62static ulong get_sp(void);
63#if defined(CONFIG_OF_LIBFDT)
64static int bootm_linux_fdt(int machid, bootm_headers_t *images);
65#endif
66extern int rd_offset ;
67extern int rd_size;
68extern unsigned int g_sys_kernel_sdram_size;
69extern unsigned char g_ddr_size_flag;
70
71#define reg32(addr) (*(volatile unsigned long *)(addr))
72
73void arch_lmb_reserve(struct lmb *lmb)
74{
75 ulong sp;
76
77 /*
78 * Booting a (Linux) kernel image
79 *
80 * Allocate space for command line and board info - the
81 * address should be as high as possible within the reach of
82 * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
83 * memory, which means far enough below the current stack
84 * pointer.
85 */
86 sp = get_sp();
87 debug("## Current stack ends at 0x%08lx ", sp);
88
89 /* adjust sp by 1K to be safe */
90 sp -= 1024;
91 lmb_reserve(lmb, sp,
92 gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp);
93}
94
95static void announce_and_cleanup(void)
96{
97 printf("\nStarting kernel ...\n");
98
99#ifdef CONFIG_USB_DEVICE
100 {
101 extern void udc_disconnect(void);
102 udc_disconnect();
103 }
104#endif
105 cleanup_before_linux();
106}
107
108//#ifdef CONFIG_ZX297520V3E_WATCH_CAP
109#if defined(CONFIG_ZX297520V3E_WATCH_CAP) || defined (CONFIG_ZX297520V3E_VEHICLE_DC) || defined (CONFIG_ZX297520V3E_VEHICLE_DC_REF)
110#define SYS_CPUCAP_PARAM_ADDR 0x10200C
111extern uint32_t arm_cpucap_ep;
112void set_cpucap_tag(int arch, uint parameter)
113{
114 uint32_t cap_tag_addr = 0;
115
116 cap_tag_addr = arm_cpucap_ep - 0x8000 + 0x100;
117
118 writel(0x0, SYS_CPUCAP_PARAM_ADDR);
119 writel(arch, SYS_CPUCAP_PARAM_ADDR+0x4);
120 writel(cap_tag_addr, SYS_CPUCAP_PARAM_ADDR+0x8);
121
122 memcpy(cap_tag_addr, parameter, 0x800);
123}
124#endif
125
126int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
127{
128 bd_t *bd = gd->bd;
129 char *s;
130 int machid = bd->bi_arch_number;
131 void (*kernel_entry)(int zero, int arch, uint params);
132
133
134#ifdef CONFIG_CMDLINE_TAG
135 char *commandline = getenv ("bootargs");
136#endif
137
138 if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
139 {
140 return 1;
141 }
142
143
144 s = getenv ("machid");
145 if (s)
146 {
147 machid = simple_strtoul (s, NULL, 16);
148 printf ("Using machid 0x%x from environment\n", machid);
149 }
150
151 show_boot_progress (15);
152
153#ifdef CONFIG_OF_LIBFDT
154#if 0
155 if (images->ft_len)
156 {
157 debug("start device tree...\n");
158 //return bootm_linux_fdt(machid, images);
159 bootm_linux_fdt(machid, images);
160 }
161#endif
162#if defined(CONFIG_ZX297520V3E_VEHICLE_DC) || defined(CONFIG_ZX297520V3E_VEHICLE_DC_REF)
163 debug("start device tree...\n");
164 bootm_linux_fdt(machid, images);
165 //fdt_chosen(images->ft_addr, 1);
166#endif
167
168#endif
169
170 kernel_entry = (void (*)(int, int, uint))images->ep;
171
172 debug ("## Transferring control to Linux (at address %08lx) ...\n",
173 (ulong) kernel_entry);
174
175#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
176 defined (CONFIG_CMDLINE_TAG) || \
177 defined (CONFIG_INITRD_TAG) || \
178 defined (CONFIG_SERIAL_TAG) || \
179 defined (CONFIG_REVISION_TAG)
180 setup_start_tag (bd);
181#ifdef CONFIG_SERIAL_TAG
182 setup_serial_tag (&params);
183#endif
184#ifdef CONFIG_REVISION_TAG
185 setup_revision_tag (&params);
186#endif
187#ifdef CONFIG_SETUP_MEMORY_TAGS
188 setup_memory_tags (bd);
189#endif
190#ifdef CONFIG_CMDLINE_TAG
191 setup_commandline_tag (bd, commandline);
192#endif
193#ifdef CONFIG_INITRD_TAG
194 if (images->rd_start && images->rd_end)
195 setup_initrd_tag (bd, images->rd_start, images->rd_end);
196#endif
197 setup_end_tag(bd);
198#endif
199
200//#ifdef CONFIG_ZX297520V3E_WATCH_CAP
201#if defined(CONFIG_ZX297520V3E_WATCH_CAP) || defined (CONFIG_ZX297520V3E_VEHICLE_DC) || defined (CONFIG_ZX297520V3E_VEHICLE_DC_REF)
202 memset(ICP_CAP_BUF_ADDR, 0, ICP_CAP_BUF_LEN);
203 memset(IRAM_BASE_ADDR_SYS_TRACE, 0, IRAM_BASE_LEN_SYS_TRACE);
204 if(!read_fota_update_flag())
205 {
206 cap_poweron();
207 set_cpucap_tag(machid, bd->bi_boot_params);
208 start_cpucap_cores();
209 }
210#endif
211 printf("===chiid=0x%x,boot_params=0x%x\n", machid, bd->bi_boot_params);
212 announce_and_cleanup();
213 kernel_entry(0, machid, bd->bi_boot_params);
214
215 /* does not return */
216 return 1;
217}
218
219//add by zhouqi
220int do_booti_linux( boot_img_hdr *hdr )
221{
222 bd_t *bd = gd->bd;
223 char *s;
224 int machid = bd->bi_arch_number;
225 void (*kernel_entry)(int zero, int arch, uint params);
226
227#ifdef CONFIG_CMDLINE_TAG
228 char *commandline = getenv ("bootargs");
229#endif
230
231 s = getenv ("machid");
232 if (s) {
233 machid = simple_strtoul (s, NULL, 16);
234 printf ("Using machid 0x%x from environment\n", machid);
235 }
236
237 show_boot_progress (15);
238
239#ifdef CONFIG_OF_LIBFDT
240 //if (images->ft_len)
241 //return bootm_linux_fdt(machid, images);
242#endif
243
244 kernel_entry = (void (*)(int, int, uint))hdr->kernel_addr;
245
246 debug ("## Transferring control to Linux (at address %08lx) ...\n",
247 (ulong) kernel_entry);
248
249#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
250 defined (CONFIG_CMDLINE_TAG) || \
251 defined (CONFIG_INITRD_TAG) || \
252 defined (CONFIG_SERIAL_TAG) || \
253 defined (CONFIG_REVISION_TAG)
254 setup_start_tag (bd);
255#ifdef CONFIG_SERIAL_TAG
256 setup_serial_tag (&params);
257#endif
258#ifdef CONFIG_REVISION_TAG
259 setup_revision_tag (&params);
260#endif
261#ifdef CONFIG_SETUP_MEMORY_TAGS
262 setup_memory_tags (bd);
263#endif
264#ifdef CONFIG_CMDLINE_TAG
265 setup_commandline_tag (bd, commandline);
266#endif
267#ifdef CONFIG_INITRD_TAG
268 if (hdr->ramdisk_size)
269 setup_initrd_tag (bd, hdr->ramdisk_addr, hdr->ramdisk_size + hdr->ramdisk_addr);
270#endif
271 setup_end_tag(bd);
272#endif
273
274 announce_and_cleanup();
275
276 kernel_entry(0, machid, bd->bi_boot_params);
277 /* does not return */
278
279 return 1;
280}
281
282
283#if defined(CONFIG_OF_LIBFDT)
284static int fixup_memory_node(void *blob)
285{
286 bd_t *bd = gd->bd;
287 int bank;
288 u64 start[CONFIG_NR_DRAM_BANKS];
289 u64 size[CONFIG_NR_DRAM_BANKS];
290
291 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
292 //start[bank] = bd->bi_dram[bank].start;
293 //size[bank] = bd->bi_dram[bank].size;
294 start[bank] = DDR_BASE_ADDR_CAP;
295 if(g_ddr_size_flag == CHIP_DDR_IS_128M)
296 {
297 size[bank] = DDR_BASE_LEN_CAP;
298 reg32(IRAM_BASE_ADDR_BOOT_DDR) = DDR_BASE_LEN_CAP;
299 }
300 else if(g_ddr_size_flag == CHIP_DDR_IS_256M)
301 {
302 size[bank] = DDR_BASE_LEN_CAP + 0x8000000;
303 reg32(IRAM_BASE_ADDR_BOOT_DDR) = (DDR_BASE_LEN_CAP + 0x8000000);
304 }
305 else if(g_ddr_size_flag == CHIP_DDR_IS_512M)
306 {
307 size[bank] = DDR_BASE_LEN_CAP + 0x18000000;
308 reg32(IRAM_BASE_ADDR_BOOT_DDR) = (DDR_BASE_LEN_CAP + 0x18000000);
309 }
310 else
311 {
312 debug("ddr size is error.\n");
313 return 0;
314 }
315 }
316 debug("size is 0x%llx\n",size[0]);
317 return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
318}
319
320static int bootm_linux_fdt(int machid, bootm_headers_t *images)
321{
322 ulong rd_len;
323 void (*kernel_entry)(int zero, int dt_machid, void *dtblob);
324 ulong of_size = images->ft_len;
325 char **of_flat_tree = &images->ft_addr;
326 ulong *initrd_start = &images->initrd_start;
327 ulong *initrd_end = &images->initrd_end;
328 struct lmb *lmb = &images->lmb;
329 int ret;
330
331 kernel_entry = (void (*)(int, int, void *))images->ep;
332
333 boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
334
335 rd_len = images->rd_end - images->rd_start;
336 ret = boot_ramdisk_high(lmb, images->rd_start, rd_len,
337 initrd_start, initrd_end);
338 if (ret)
339 return ret;
340
341 ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
342 if (ret)
343 return ret;
344
345 debug("## Transferring control to Linux (at address %08lx) ...\n",
346 (ulong) kernel_entry);
347
348 fdt_chosen(*of_flat_tree, 1);
349
350 fixup_memory_node(*of_flat_tree);
351
352#if 0
353 fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1);
354
355 announce_and_cleanup();
356
357 kernel_entry(0, machid, *of_flat_tree);
358 /* does not return */
359#endif
360 return 1;
361}
362#endif
363
364#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
365 defined (CONFIG_CMDLINE_TAG) || \
366 defined (CONFIG_INITRD_TAG) || \
367 defined (CONFIG_SERIAL_TAG) || \
368 defined (CONFIG_REVISION_TAG)
369static void setup_start_tag (bd_t *bd)
370{
371 params = (struct tag *) bd->bi_boot_params;
372
373 params->hdr.tag = ATAG_CORE;
374 params->hdr.size = tag_size (tag_core);
375
376 params->u.core.flags = 0x1;//0;
377 params->u.core.pagesize =0x1000; //0;
378 params->u.core.rootdev = 0x0;//0;
379
380 params = tag_next (params);
381}
382
383
384#ifdef CONFIG_SETUP_MEMORY_TAGS
385static void setup_memory_tags (bd_t *bd)
386{
387 int i;
388
389 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
390 {
391 params->hdr.tag = ATAG_MEM;
392 params->hdr.size = tag_size (tag_mem32);
393
394 /* modify by zhouqi 2013/06/27 */
395 params->u.mem.start = read_sys_ddr_kernel_start();
396 params->u.mem.size = g_sys_kernel_sdram_size; //CONFIG_SYS_SDRAM_A9_SIZE;
397
398 params = tag_next (params);
399 }
400}
401#endif /* CONFIG_SETUP_MEMORY_TAGS */
402
403
404static void setup_commandline_tag (bd_t *bd, char *commandline)
405{
406 char *p;
407
408 if (!commandline)
409 return;
410
411 /* eat leading white space */
412 for (p = commandline; *p == ' '; p++);
413
414 /* skip non-existent command lines so the kernel will still
415 * use its default command line.
416 */
417 if (*p == '\0')
418 return;
419
420 params->hdr.tag = ATAG_CMDLINE;
421 params->hdr.size =
422 (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
423
424 strcpy (params->u.cmdline.cmdline, p);
425
426 params = tag_next (params);
427}
428
429
430#ifdef CONFIG_INITRD_TAG
431static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)
432{
433 /* an ATAG_INITRD node tells the kernel where the compressed
434 * ramdisk can be found. ATAG_RDIMG is a better name, actually.
435 */
436 params->hdr.tag = ATAG_INITRD2;
437 params->hdr.size = tag_size (tag_initrd);
438
439 params->u.initrd.start = rd_offset;//initrd_start;
440 params->u.initrd.size =rd_size;//initrd_end - initrd_start;
441
442
443 params = tag_next (params);
444}
445#endif /* CONFIG_INITRD_TAG */
446
447#ifdef CONFIG_SERIAL_TAG
448void setup_serial_tag (struct tag **tmp)
449{
450 struct tag *params = *tmp;
451 struct tag_serialnr serialnr;
452 void get_board_serial(struct tag_serialnr *serialnr);
453
454 get_board_serial(&serialnr);
455 params->hdr.tag = ATAG_SERIAL;
456 params->hdr.size = tag_size (tag_serialnr);
457 params->u.serialnr.low = serialnr.low;
458 params->u.serialnr.high= serialnr.high;
459 params = tag_next (params);
460 *tmp = params;
461}
462#endif
463
464#ifdef CONFIG_REVISION_TAG
465void setup_revision_tag(struct tag **in_params)
466{
467 u32 rev = 0;
468 u32 get_board_rev(void);
469
470 rev = get_board_rev();
471 params->hdr.tag = ATAG_REVISION;
472 params->hdr.size = tag_size (tag_revision);
473 params->u.revision.rev = rev;
474 params = tag_next (params);
475}
476#endif /* CONFIG_REVISION_TAG */
477
478static void setup_end_tag (bd_t *bd)
479{
480 params->hdr.tag = ATAG_NONE;
481 params->hdr.size = 0;
482}
483#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
484
485static ulong get_sp(void)
486{
487 ulong ret;
488
489 asm("mov %0, sp" : "=r"(ret) : );
490 return ret;
491}