]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/avr32/lib/bootm.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[karo-tx-uboot.git] / arch / avr32 / lib / bootm.c
1 /*
2  * Copyright (C) 2004-2006 Atmel Corporation
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6 #include <common.h>
7 #include <command.h>
8 #include <image.h>
9 #include <u-boot/zlib.h>
10 #include <asm/byteorder.h>
11 #include <asm/arch/addrspace.h>
12 #include <asm/io.h>
13 #include <asm/setup.h>
14 #include <asm/arch/clk.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 /* CPU-specific hook to allow flushing of caches, etc. */
19 extern void prepare_to_boot(void);
20
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;
96         params->u.clock.clock_hz = gd->arch.cpu_hz;
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;
109         params->u.clock.clock_hz = get_hsb_clk_rate();
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
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
162 static void setup_end_tag(struct tag *params)
163 {
164         params->hdr.tag = ATAG_NONE;
165         params->hdr.size = 0;
166 }
167
168 int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images)
169 {
170         void    (*theKernel)(int magic, void *tagtable);
171         struct  tag *params, *params_start;
172         char    *commandline = getenv("bootargs");
173
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
183         if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
184                 return 1;
185
186         theKernel = (void *)images->ep;
187
188         bootstage_mark(BOOTSTAGE_ID_RUN_OS);
189
190         params = params_start = (struct tag *)gd->bd->bi_boot_params;
191         params = setup_start_tag(params);
192         params = setup_memory_tags(params);
193         if (images->rd_start) {
194                 params = setup_ramdisk_tag(params,
195                                            PHYSADDR(images->rd_start),
196                                            PHYSADDR(images->rd_end));
197         }
198         params = setup_commandline_tag(params, commandline);
199         params = setup_clock_tags(params);
200         params = setup_ethernet_tags(params);
201         params = setup_boardinfo_tag(params);
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);
210         /* does not return */
211
212         return 1;
213 }