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