xref: /rk3399_rockchip-uboot/arch/arm/lib/bootm.c (revision ea0364f1bbfed1e3ea711147420875cf338fe77a)
1*ea0364f1SPeter Tyser /*
2*ea0364f1SPeter Tyser  * (C) Copyright 2002
3*ea0364f1SPeter Tyser  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4*ea0364f1SPeter Tyser  * Marius Groeger <mgroeger@sysgo.de>
5*ea0364f1SPeter Tyser  *
6*ea0364f1SPeter Tyser  * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
7*ea0364f1SPeter Tyser  *
8*ea0364f1SPeter Tyser  * This program is free software; you can redistribute it and/or modify
9*ea0364f1SPeter Tyser  * it under the terms of the GNU General Public License as published by
10*ea0364f1SPeter Tyser  * the Free Software Foundation; either version 2 of the License, or
11*ea0364f1SPeter Tyser  * (at your option) any later version.
12*ea0364f1SPeter Tyser  *
13*ea0364f1SPeter Tyser  * This program is distributed in the hope that it will be useful,
14*ea0364f1SPeter Tyser  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*ea0364f1SPeter Tyser  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
16*ea0364f1SPeter Tyser  * GNU General Public License for more details.
17*ea0364f1SPeter Tyser  *
18*ea0364f1SPeter Tyser  * You should have received a copy of the GNU General Public License
19*ea0364f1SPeter Tyser  * along with this program; if not, write to the Free Software
20*ea0364f1SPeter Tyser  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
21*ea0364f1SPeter Tyser  *
22*ea0364f1SPeter Tyser  */
23*ea0364f1SPeter Tyser 
24*ea0364f1SPeter Tyser #include <common.h>
25*ea0364f1SPeter Tyser #include <command.h>
26*ea0364f1SPeter Tyser #include <image.h>
27*ea0364f1SPeter Tyser #include <u-boot/zlib.h>
28*ea0364f1SPeter Tyser #include <asm/byteorder.h>
29*ea0364f1SPeter Tyser 
30*ea0364f1SPeter Tyser DECLARE_GLOBAL_DATA_PTR;
31*ea0364f1SPeter Tyser 
32*ea0364f1SPeter Tyser #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
33*ea0364f1SPeter Tyser     defined (CONFIG_CMDLINE_TAG) || \
34*ea0364f1SPeter Tyser     defined (CONFIG_INITRD_TAG) || \
35*ea0364f1SPeter Tyser     defined (CONFIG_SERIAL_TAG) || \
36*ea0364f1SPeter Tyser     defined (CONFIG_REVISION_TAG) || \
37*ea0364f1SPeter Tyser     defined (CONFIG_VFD) || \
38*ea0364f1SPeter Tyser     defined (CONFIG_LCD)
39*ea0364f1SPeter Tyser static void setup_start_tag (bd_t *bd);
40*ea0364f1SPeter Tyser 
41*ea0364f1SPeter Tyser # ifdef CONFIG_SETUP_MEMORY_TAGS
42*ea0364f1SPeter Tyser static void setup_memory_tags (bd_t *bd);
43*ea0364f1SPeter Tyser # endif
44*ea0364f1SPeter Tyser static void setup_commandline_tag (bd_t *bd, char *commandline);
45*ea0364f1SPeter Tyser 
46*ea0364f1SPeter Tyser # ifdef CONFIG_INITRD_TAG
47*ea0364f1SPeter Tyser static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
48*ea0364f1SPeter Tyser 			      ulong initrd_end);
49*ea0364f1SPeter Tyser # endif
50*ea0364f1SPeter Tyser static void setup_end_tag (bd_t *bd);
51*ea0364f1SPeter Tyser 
52*ea0364f1SPeter Tyser # if defined (CONFIG_VFD) || defined (CONFIG_LCD)
53*ea0364f1SPeter Tyser static void setup_videolfb_tag (gd_t *gd);
54*ea0364f1SPeter Tyser # endif
55*ea0364f1SPeter Tyser 
56*ea0364f1SPeter Tyser static struct tag *params;
57*ea0364f1SPeter Tyser #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
58*ea0364f1SPeter Tyser 
59*ea0364f1SPeter Tyser int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
60*ea0364f1SPeter Tyser {
61*ea0364f1SPeter Tyser 	bd_t	*bd = gd->bd;
62*ea0364f1SPeter Tyser 	char	*s;
63*ea0364f1SPeter Tyser 	int	machid = bd->bi_arch_number;
64*ea0364f1SPeter Tyser 	void	(*theKernel)(int zero, int arch, uint params);
65*ea0364f1SPeter Tyser 
66*ea0364f1SPeter Tyser #ifdef CONFIG_CMDLINE_TAG
67*ea0364f1SPeter Tyser 	char *commandline = getenv ("bootargs");
68*ea0364f1SPeter Tyser #endif
69*ea0364f1SPeter Tyser 
70*ea0364f1SPeter Tyser 	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
71*ea0364f1SPeter Tyser 		return 1;
72*ea0364f1SPeter Tyser 
73*ea0364f1SPeter Tyser 	theKernel = (void (*)(int, int, uint))images->ep;
74*ea0364f1SPeter Tyser 
75*ea0364f1SPeter Tyser 	s = getenv ("machid");
76*ea0364f1SPeter Tyser 	if (s) {
77*ea0364f1SPeter Tyser 		machid = simple_strtoul (s, NULL, 16);
78*ea0364f1SPeter Tyser 		printf ("Using machid 0x%x from environment\n", machid);
79*ea0364f1SPeter Tyser 	}
80*ea0364f1SPeter Tyser 
81*ea0364f1SPeter Tyser 	show_boot_progress (15);
82*ea0364f1SPeter Tyser 
83*ea0364f1SPeter Tyser 	debug ("## Transferring control to Linux (at address %08lx) ...\n",
84*ea0364f1SPeter Tyser 	       (ulong) theKernel);
85*ea0364f1SPeter Tyser 
86*ea0364f1SPeter Tyser #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
87*ea0364f1SPeter Tyser     defined (CONFIG_CMDLINE_TAG) || \
88*ea0364f1SPeter Tyser     defined (CONFIG_INITRD_TAG) || \
89*ea0364f1SPeter Tyser     defined (CONFIG_SERIAL_TAG) || \
90*ea0364f1SPeter Tyser     defined (CONFIG_REVISION_TAG) || \
91*ea0364f1SPeter Tyser     defined (CONFIG_LCD) || \
92*ea0364f1SPeter Tyser     defined (CONFIG_VFD)
93*ea0364f1SPeter Tyser 	setup_start_tag (bd);
94*ea0364f1SPeter Tyser #ifdef CONFIG_SERIAL_TAG
95*ea0364f1SPeter Tyser 	setup_serial_tag (&params);
96*ea0364f1SPeter Tyser #endif
97*ea0364f1SPeter Tyser #ifdef CONFIG_REVISION_TAG
98*ea0364f1SPeter Tyser 	setup_revision_tag (&params);
99*ea0364f1SPeter Tyser #endif
100*ea0364f1SPeter Tyser #ifdef CONFIG_SETUP_MEMORY_TAGS
101*ea0364f1SPeter Tyser 	setup_memory_tags (bd);
102*ea0364f1SPeter Tyser #endif
103*ea0364f1SPeter Tyser #ifdef CONFIG_CMDLINE_TAG
104*ea0364f1SPeter Tyser 	setup_commandline_tag (bd, commandline);
105*ea0364f1SPeter Tyser #endif
106*ea0364f1SPeter Tyser #ifdef CONFIG_INITRD_TAG
107*ea0364f1SPeter Tyser 	if (images->rd_start && images->rd_end)
108*ea0364f1SPeter Tyser 		setup_initrd_tag (bd, images->rd_start, images->rd_end);
109*ea0364f1SPeter Tyser #endif
110*ea0364f1SPeter Tyser #if defined (CONFIG_VFD) || defined (CONFIG_LCD)
111*ea0364f1SPeter Tyser 	setup_videolfb_tag ((gd_t *) gd);
112*ea0364f1SPeter Tyser #endif
113*ea0364f1SPeter Tyser 	setup_end_tag (bd);
114*ea0364f1SPeter Tyser #endif
115*ea0364f1SPeter Tyser 
116*ea0364f1SPeter Tyser 	/* we assume that the kernel is in place */
117*ea0364f1SPeter Tyser 	printf ("\nStarting kernel ...\n\n");
118*ea0364f1SPeter Tyser 
119*ea0364f1SPeter Tyser #ifdef CONFIG_USB_DEVICE
120*ea0364f1SPeter Tyser 	{
121*ea0364f1SPeter Tyser 		extern void udc_disconnect (void);
122*ea0364f1SPeter Tyser 		udc_disconnect ();
123*ea0364f1SPeter Tyser 	}
124*ea0364f1SPeter Tyser #endif
125*ea0364f1SPeter Tyser 
126*ea0364f1SPeter Tyser 	cleanup_before_linux ();
127*ea0364f1SPeter Tyser 
128*ea0364f1SPeter Tyser 	theKernel (0, machid, bd->bi_boot_params);
129*ea0364f1SPeter Tyser 	/* does not return */
130*ea0364f1SPeter Tyser 
131*ea0364f1SPeter Tyser 	return 1;
132*ea0364f1SPeter Tyser }
133*ea0364f1SPeter Tyser 
134*ea0364f1SPeter Tyser 
135*ea0364f1SPeter Tyser #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
136*ea0364f1SPeter Tyser     defined (CONFIG_CMDLINE_TAG) || \
137*ea0364f1SPeter Tyser     defined (CONFIG_INITRD_TAG) || \
138*ea0364f1SPeter Tyser     defined (CONFIG_SERIAL_TAG) || \
139*ea0364f1SPeter Tyser     defined (CONFIG_REVISION_TAG) || \
140*ea0364f1SPeter Tyser     defined (CONFIG_LCD) || \
141*ea0364f1SPeter Tyser     defined (CONFIG_VFD)
142*ea0364f1SPeter Tyser static void setup_start_tag (bd_t *bd)
143*ea0364f1SPeter Tyser {
144*ea0364f1SPeter Tyser 	params = (struct tag *) bd->bi_boot_params;
145*ea0364f1SPeter Tyser 
146*ea0364f1SPeter Tyser 	params->hdr.tag = ATAG_CORE;
147*ea0364f1SPeter Tyser 	params->hdr.size = tag_size (tag_core);
148*ea0364f1SPeter Tyser 
149*ea0364f1SPeter Tyser 	params->u.core.flags = 0;
150*ea0364f1SPeter Tyser 	params->u.core.pagesize = 0;
151*ea0364f1SPeter Tyser 	params->u.core.rootdev = 0;
152*ea0364f1SPeter Tyser 
153*ea0364f1SPeter Tyser 	params = tag_next (params);
154*ea0364f1SPeter Tyser }
155*ea0364f1SPeter Tyser 
156*ea0364f1SPeter Tyser 
157*ea0364f1SPeter Tyser #ifdef CONFIG_SETUP_MEMORY_TAGS
158*ea0364f1SPeter Tyser static void setup_memory_tags (bd_t *bd)
159*ea0364f1SPeter Tyser {
160*ea0364f1SPeter Tyser 	int i;
161*ea0364f1SPeter Tyser 
162*ea0364f1SPeter Tyser 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
163*ea0364f1SPeter Tyser 		params->hdr.tag = ATAG_MEM;
164*ea0364f1SPeter Tyser 		params->hdr.size = tag_size (tag_mem32);
165*ea0364f1SPeter Tyser 
166*ea0364f1SPeter Tyser 		params->u.mem.start = bd->bi_dram[i].start;
167*ea0364f1SPeter Tyser 		params->u.mem.size = bd->bi_dram[i].size;
168*ea0364f1SPeter Tyser 
169*ea0364f1SPeter Tyser 		params = tag_next (params);
170*ea0364f1SPeter Tyser 	}
171*ea0364f1SPeter Tyser }
172*ea0364f1SPeter Tyser #endif /* CONFIG_SETUP_MEMORY_TAGS */
173*ea0364f1SPeter Tyser 
174*ea0364f1SPeter Tyser 
175*ea0364f1SPeter Tyser static void setup_commandline_tag (bd_t *bd, char *commandline)
176*ea0364f1SPeter Tyser {
177*ea0364f1SPeter Tyser 	char *p;
178*ea0364f1SPeter Tyser 
179*ea0364f1SPeter Tyser 	if (!commandline)
180*ea0364f1SPeter Tyser 		return;
181*ea0364f1SPeter Tyser 
182*ea0364f1SPeter Tyser 	/* eat leading white space */
183*ea0364f1SPeter Tyser 	for (p = commandline; *p == ' '; p++);
184*ea0364f1SPeter Tyser 
185*ea0364f1SPeter Tyser 	/* skip non-existent command lines so the kernel will still
186*ea0364f1SPeter Tyser 	 * use its default command line.
187*ea0364f1SPeter Tyser 	 */
188*ea0364f1SPeter Tyser 	if (*p == '\0')
189*ea0364f1SPeter Tyser 		return;
190*ea0364f1SPeter Tyser 
191*ea0364f1SPeter Tyser 	params->hdr.tag = ATAG_CMDLINE;
192*ea0364f1SPeter Tyser 	params->hdr.size =
193*ea0364f1SPeter Tyser 		(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
194*ea0364f1SPeter Tyser 
195*ea0364f1SPeter Tyser 	strcpy (params->u.cmdline.cmdline, p);
196*ea0364f1SPeter Tyser 
197*ea0364f1SPeter Tyser 	params = tag_next (params);
198*ea0364f1SPeter Tyser }
199*ea0364f1SPeter Tyser 
200*ea0364f1SPeter Tyser 
201*ea0364f1SPeter Tyser #ifdef CONFIG_INITRD_TAG
202*ea0364f1SPeter Tyser static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)
203*ea0364f1SPeter Tyser {
204*ea0364f1SPeter Tyser 	/* an ATAG_INITRD node tells the kernel where the compressed
205*ea0364f1SPeter Tyser 	 * ramdisk can be found. ATAG_RDIMG is a better name, actually.
206*ea0364f1SPeter Tyser 	 */
207*ea0364f1SPeter Tyser 	params->hdr.tag = ATAG_INITRD2;
208*ea0364f1SPeter Tyser 	params->hdr.size = tag_size (tag_initrd);
209*ea0364f1SPeter Tyser 
210*ea0364f1SPeter Tyser 	params->u.initrd.start = initrd_start;
211*ea0364f1SPeter Tyser 	params->u.initrd.size = initrd_end - initrd_start;
212*ea0364f1SPeter Tyser 
213*ea0364f1SPeter Tyser 	params = tag_next (params);
214*ea0364f1SPeter Tyser }
215*ea0364f1SPeter Tyser #endif /* CONFIG_INITRD_TAG */
216*ea0364f1SPeter Tyser 
217*ea0364f1SPeter Tyser 
218*ea0364f1SPeter Tyser #if defined (CONFIG_VFD) || defined (CONFIG_LCD)
219*ea0364f1SPeter Tyser extern ulong calc_fbsize (void);
220*ea0364f1SPeter Tyser static void setup_videolfb_tag (gd_t *gd)
221*ea0364f1SPeter Tyser {
222*ea0364f1SPeter Tyser 	/* An ATAG_VIDEOLFB node tells the kernel where and how large
223*ea0364f1SPeter Tyser 	 * the framebuffer for video was allocated (among other things).
224*ea0364f1SPeter Tyser 	 * Note that a _physical_ address is passed !
225*ea0364f1SPeter Tyser 	 *
226*ea0364f1SPeter Tyser 	 * We only use it to pass the address and size, the other entries
227*ea0364f1SPeter Tyser 	 * in the tag_videolfb are not of interest.
228*ea0364f1SPeter Tyser 	 */
229*ea0364f1SPeter Tyser 	params->hdr.tag = ATAG_VIDEOLFB;
230*ea0364f1SPeter Tyser 	params->hdr.size = tag_size (tag_videolfb);
231*ea0364f1SPeter Tyser 
232*ea0364f1SPeter Tyser 	params->u.videolfb.lfb_base = (u32) gd->fb_base;
233*ea0364f1SPeter Tyser 	/* Fb size is calculated according to parameters for our panel
234*ea0364f1SPeter Tyser 	 */
235*ea0364f1SPeter Tyser 	params->u.videolfb.lfb_size = calc_fbsize();
236*ea0364f1SPeter Tyser 
237*ea0364f1SPeter Tyser 	params = tag_next (params);
238*ea0364f1SPeter Tyser }
239*ea0364f1SPeter Tyser #endif /* CONFIG_VFD || CONFIG_LCD */
240*ea0364f1SPeter Tyser 
241*ea0364f1SPeter Tyser #ifdef CONFIG_SERIAL_TAG
242*ea0364f1SPeter Tyser void setup_serial_tag (struct tag **tmp)
243*ea0364f1SPeter Tyser {
244*ea0364f1SPeter Tyser 	struct tag *params = *tmp;
245*ea0364f1SPeter Tyser 	struct tag_serialnr serialnr;
246*ea0364f1SPeter Tyser 	void get_board_serial(struct tag_serialnr *serialnr);
247*ea0364f1SPeter Tyser 
248*ea0364f1SPeter Tyser 	get_board_serial(&serialnr);
249*ea0364f1SPeter Tyser 	params->hdr.tag = ATAG_SERIAL;
250*ea0364f1SPeter Tyser 	params->hdr.size = tag_size (tag_serialnr);
251*ea0364f1SPeter Tyser 	params->u.serialnr.low = serialnr.low;
252*ea0364f1SPeter Tyser 	params->u.serialnr.high= serialnr.high;
253*ea0364f1SPeter Tyser 	params = tag_next (params);
254*ea0364f1SPeter Tyser 	*tmp = params;
255*ea0364f1SPeter Tyser }
256*ea0364f1SPeter Tyser #endif
257*ea0364f1SPeter Tyser 
258*ea0364f1SPeter Tyser #ifdef CONFIG_REVISION_TAG
259*ea0364f1SPeter Tyser void setup_revision_tag(struct tag **in_params)
260*ea0364f1SPeter Tyser {
261*ea0364f1SPeter Tyser 	u32 rev = 0;
262*ea0364f1SPeter Tyser 	u32 get_board_rev(void);
263*ea0364f1SPeter Tyser 
264*ea0364f1SPeter Tyser 	rev = get_board_rev();
265*ea0364f1SPeter Tyser 	params->hdr.tag = ATAG_REVISION;
266*ea0364f1SPeter Tyser 	params->hdr.size = tag_size (tag_revision);
267*ea0364f1SPeter Tyser 	params->u.revision.rev = rev;
268*ea0364f1SPeter Tyser 	params = tag_next (params);
269*ea0364f1SPeter Tyser }
270*ea0364f1SPeter Tyser #endif  /* CONFIG_REVISION_TAG */
271*ea0364f1SPeter Tyser 
272*ea0364f1SPeter Tyser 
273*ea0364f1SPeter Tyser static void setup_end_tag (bd_t *bd)
274*ea0364f1SPeter Tyser {
275*ea0364f1SPeter Tyser 	params->hdr.tag = ATAG_NONE;
276*ea0364f1SPeter Tyser 	params->hdr.size = 0;
277*ea0364f1SPeter Tyser }
278*ea0364f1SPeter Tyser 
279*ea0364f1SPeter Tyser #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
280