]>
Commit | Line | Data |
---|---|---|
7b64fef3 WD |
1 | /* |
2 | * Copyright (C) 2004-2006 Atmel Corporation | |
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 | #include <common.h> | |
23 | #include <command.h> | |
24 | #include <image.h> | |
a31e091a | 25 | #include <u-boot/zlib.h> |
7b64fef3 | 26 | #include <asm/byteorder.h> |
a38de083 | 27 | #include <asm/arch/addrspace.h> |
7b64fef3 WD |
28 | #include <asm/io.h> |
29 | #include <asm/setup.h> | |
df548d3c | 30 | #include <asm/arch/clk.h> |
7b64fef3 WD |
31 | |
32 | DECLARE_GLOBAL_DATA_PTR; | |
33 | ||
7b64fef3 WD |
34 | /* CPU-specific hook to allow flushing of caches, etc. */ |
35 | extern void prepare_to_boot(void); | |
36 | ||
7b64fef3 WD |
37 | static struct tag *setup_start_tag(struct tag *params) |
38 | { | |
39 | params->hdr.tag = ATAG_CORE; | |
40 | params->hdr.size = tag_size(tag_core); | |
41 | ||
42 | params->u.core.flags = 0; | |
43 | params->u.core.pagesize = 4096; | |
44 | params->u.core.rootdev = 0; | |
45 | ||
46 | return tag_next(params); | |
47 | } | |
48 | ||
49 | static struct tag *setup_memory_tags(struct tag *params) | |
50 | { | |
51 | bd_t *bd = gd->bd; | |
52 | int i; | |
53 | ||
54 | for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { | |
55 | params->hdr.tag = ATAG_MEM; | |
56 | params->hdr.size = tag_size(tag_mem_range); | |
57 | ||
58 | params->u.mem_range.addr = bd->bi_dram[i].start; | |
59 | params->u.mem_range.size = bd->bi_dram[i].size; | |
60 | ||
61 | params = tag_next(params); | |
62 | } | |
63 | ||
64 | return params; | |
65 | } | |
66 | ||
67 | static struct tag *setup_commandline_tag(struct tag *params, char *cmdline) | |
68 | { | |
69 | if (!cmdline) | |
70 | return params; | |
71 | ||
72 | /* eat leading white space */ | |
73 | while (*cmdline == ' ') cmdline++; | |
74 | ||
75 | /* | |
76 | * Don't include tags for empty command lines; let the kernel | |
77 | * use its default command line. | |
78 | */ | |
79 | if (*cmdline == '\0') | |
80 | return params; | |
81 | ||
82 | params->hdr.tag = ATAG_CMDLINE; | |
83 | params->hdr.size = | |
84 | (sizeof (struct tag_header) + strlen(cmdline) + 1 + 3) >> 2; | |
85 | strcpy(params->u.cmdline.cmdline, cmdline); | |
86 | ||
87 | return tag_next(params); | |
88 | } | |
89 | ||
90 | static struct tag *setup_ramdisk_tag(struct tag *params, | |
91 | unsigned long rd_start, | |
92 | unsigned long rd_end) | |
93 | { | |
94 | if (rd_start == rd_end) | |
95 | return params; | |
96 | ||
97 | params->hdr.tag = ATAG_RDIMG; | |
98 | params->hdr.size = tag_size(tag_mem_range); | |
99 | ||
100 | params->u.mem_range.addr = rd_start; | |
101 | params->u.mem_range.size = rd_end - rd_start; | |
102 | ||
103 | return tag_next(params); | |
104 | } | |
105 | ||
106 | static struct tag *setup_clock_tags(struct tag *params) | |
107 | { | |
108 | params->hdr.tag = ATAG_CLOCK; | |
109 | params->hdr.size = tag_size(tag_clock); | |
110 | params->u.clock.clock_id = ACLOCK_BOOTCPU; | |
111 | params->u.clock.clock_flags = 0; | |
112 | params->u.clock.clock_hz = gd->cpu_hz; | |
113 | ||
114 | #ifdef CONFIG_AT32AP7000 | |
115 | /* | |
116 | * New kernels don't need this, but we should be backwards | |
117 | * compatible for a while... | |
118 | */ | |
119 | params = tag_next(params); | |
120 | ||
121 | params->hdr.tag = ATAG_CLOCK; | |
122 | params->hdr.size = tag_size(tag_clock); | |
123 | params->u.clock.clock_id = ACLOCK_HSB; | |
124 | params->u.clock.clock_flags = 0; | |
df548d3c | 125 | params->u.clock.clock_hz = get_hsb_clk_rate(); |
7b64fef3 WD |
126 | #endif |
127 | ||
128 | return tag_next(params); | |
129 | } | |
130 | ||
131 | static struct tag *setup_ethernet_tag(struct tag *params, | |
132 | char *addr, int index) | |
133 | { | |
134 | char *s, *e; | |
135 | int i; | |
136 | ||
137 | params->hdr.tag = ATAG_ETHERNET; | |
138 | params->hdr.size = tag_size(tag_ethernet); | |
139 | ||
140 | params->u.ethernet.mac_index = index; | |
141 | params->u.ethernet.mii_phy_addr = gd->bd->bi_phy_id[index]; | |
142 | ||
143 | s = addr; | |
144 | for (i = 0; i < 6; i++) { | |
145 | params->u.ethernet.hw_address[i] = simple_strtoul(s, &e, 16); | |
146 | s = e + 1; | |
147 | } | |
148 | ||
149 | return tag_next(params); | |
150 | } | |
151 | ||
152 | static struct tag *setup_ethernet_tags(struct tag *params) | |
153 | { | |
154 | char name[16] = "ethaddr"; | |
155 | char *addr; | |
156 | int i = 0; | |
157 | ||
158 | do { | |
159 | addr = getenv(name); | |
160 | if (addr) | |
161 | params = setup_ethernet_tag(params, addr, i); | |
162 | sprintf(name, "eth%daddr", ++i); | |
163 | } while (i < 4); | |
164 | ||
165 | return params; | |
166 | } | |
167 | ||
168 | static void setup_end_tag(struct tag *params) | |
169 | { | |
170 | params->hdr.tag = ATAG_NONE; | |
171 | params->hdr.size = 0; | |
172 | } | |
173 | ||
40d7e99d | 174 | int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) |
7b64fef3 | 175 | { |
d5934ad7 MB |
176 | void (*theKernel)(int magic, void *tagtable); |
177 | struct tag *params, *params_start; | |
178 | char *commandline = getenv("bootargs"); | |
179 | ||
49c3a861 KG |
180 | if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) |
181 | return 1; | |
182 | ||
c160a954 | 183 | theKernel = (void *)images->ep; |
7b64fef3 | 184 | |
fad63407 | 185 | show_boot_progress (15); |
7b64fef3 WD |
186 | |
187 | params = params_start = (struct tag *)gd->bd->bi_boot_params; | |
188 | params = setup_start_tag(params); | |
189 | params = setup_memory_tags(params); | |
c4f9419c | 190 | if (images->rd_start) { |
7b64fef3 | 191 | params = setup_ramdisk_tag(params, |
c4f9419c KG |
192 | PHYSADDR(images->rd_start), |
193 | PHYSADDR(images->rd_end)); | |
7b64fef3 WD |
194 | } |
195 | params = setup_commandline_tag(params, commandline); | |
196 | params = setup_clock_tags(params); | |
197 | params = setup_ethernet_tags(params); | |
198 | setup_end_tag(params); | |
199 | ||
200 | printf("\nStarting kernel at %p (params at %p)...\n\n", | |
201 | theKernel, params_start); | |
202 | ||
203 | prepare_to_boot(); | |
204 | ||
205 | theKernel(ATAG_MAGIC, params_start); | |
cd7c596e | 206 | /* does not return */ |
a3a08c0c | 207 | |
40d7e99d | 208 | return 1; |
7b64fef3 | 209 | } |