]> git.ipfire.org Git - people/ms/u-boot.git/blame - common/fdt_support.c
Moved fdt command support code to fdt_support.c
[people/ms/u-boot.git] / common / fdt_support.c
CommitLineData
64dbbd40
GVB
1/*
2 * (C) Copyright 2007
3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (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,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25#include <linux/ctype.h>
26#include <linux/types.h>
27
28#ifdef CONFIG_OF_LIBFDT
29
30#include <asm/global_data.h>
31#include <fdt.h>
32#include <libfdt.h>
33#include <fdt_support.h>
34
35/*
36 * Global data (for the gd->bd)
37 */
38DECLARE_GLOBAL_DATA_PTR;
39
40
41/********************************************************************/
42
43int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
44{
45 bd_t *bd = gd->bd;
46 int nodeoffset;
47 int err;
48 u32 tmp; /* used to set 32 bit integer properties */
49 char *str; /* used to set string properties */
50 ulong clock;
51
52 err = fdt_check_header(fdt);
53 if (err < 0) {
54 printf("libfdt: %s\n", fdt_strerror(err));
55 return err;
56 }
57
58#warning "Don't double-add the reserved map"
59 if (initrd_start && initrd_end) {
60 err = fdt_add_reservemap_entry(fdt,
61 initrd_start, initrd_end - initrd_start + 1);
62 if (err < 0) {
63 printf("libfdt: %s\n", fdt_strerror(err));
64 return err;
65 }
66 }
67
68 /*
69 * Find the "chosen" node.
70 */
71 nodeoffset = fdt_path_offset (fdt, "/chosen");
72
73 /*
74 * If we have a "chosen" node already the "force the writing"
75 * is not set, our job is done.
76 */
77 if ((nodeoffset >= 0) && !force)
78 return 0;
79
80 /*
81 * No "chosen" node in the blob: create it.
82 */
83 if (nodeoffset < 0) {
84 /*
85 * Create a new node "/chosen" (offset 0 is root level)
86 */
87 nodeoffset = fdt_add_subnode(fdt, 0, "chosen");
88 if (nodeoffset < 0) {
89 printf("libfdt: %s\n", fdt_strerror(nodeoffset));
90 return nodeoffset;
91 }
92 }
93
94 /*
95 * Update pre-existing properties, create them if non-existant.
96 */
97 str = getenv("bootargs");
98 if (str != NULL) {
99 err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str)+1);
100 if (err < 0)
101 printf("libfdt: %s\n", fdt_strerror(err));
102 }
103 if (initrd_start && initrd_end) {
104 tmp = __cpu_to_be32(initrd_start);
105 err = fdt_setprop(fdt, nodeoffset, "linux,initrd-start", &tmp, sizeof(tmp));
106 if (err < 0)
107 printf("libfdt: %s\n", fdt_strerror(err));
108 tmp = __cpu_to_be32(initrd_end);
109 err = fdt_setprop(fdt, nodeoffset, "linux,initrd-end", &tmp, sizeof(tmp));
110 if (err < 0)
111 printf("libfdt: %s\n", fdt_strerror(err));
112 }
113#ifdef OF_STDOUT_PATH
114 err = fdt_setprop(fdt, nodeoffset, "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
115 if (err < 0)
116 printf("libfdt: %s\n", fdt_strerror(err));
117#endif
118
119 nodeoffset = fdt_path_offset (fdt, "/cpus");
120 if (nodeoffset >= 0) {
121 clock = cpu_to_be32(bd->bi_intfreq);
122 err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4);
123 if (err < 0)
124 printf("libfdt: %s\n", fdt_strerror(err));
125 }
126#ifdef OF_TBCLK
127 nodeoffset = fdt_path_offset (fdt, "/cpus/" OF_CPU "/timebase-frequency");
128 if (nodeoffset >= 0) {
129 clock = cpu_to_be32(OF_TBCLK);
130 err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4);
131 if (err < 0)
132 printf("libfdt: %s\n", fdt_strerror(err));
133 }
134#endif
135 return err;
136}
137
138/********************************************************************/
139
140#ifdef CONFIG_OF_HAS_UBOOT_ENV
141
142/* Function that returns a character from the environment */
143extern uchar(*env_get_char) (int);
144
145
146int fdt_env(void *fdt)
147{
148 int nodeoffset;
149 int err;
150 int k, nxt;
151 int i;
152 static char tmpenv[256];
153
154 err = fdt_check_header(fdt);
155 if (err < 0) {
156 printf("libfdt: %s\n", fdt_strerror(err));
157 return err;
158 }
159
160 /*
161 * See if we already have a "u-boot-env" node, delete it if so.
162 * Then create a new empty node.
163 */
164 nodeoffset = fdt_path_offset (fdt, "/u-boot-env");
165 if (nodeoffset >= 0) {
166 err = fdt_del_node(fdt, nodeoffset);
167 if (err < 0) {
168 printf("libfdt: %s\n", fdt_strerror(err));
169 return err;
170 }
171 }
172 /*
173 * Create a new node "/u-boot-env" (offset 0 is root level)
174 */
175 nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env");
176 if (nodeoffset < 0) {
177 printf("libfdt: %s\n", fdt_strerror(nodeoffset));
178 return nodeoffset;
179 }
180
181 for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
182 char *s, *lval, *rval;
183
184 /*
185 * Find the end of the name=definition
186 */
187 for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
188 ;
189 s = tmpenv;
190 for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k)
191 *s++ = env_get_char(k);
192 *s++ = '\0';
193 lval = tmpenv;
194 /*
195 * Find the first '=': it separates the name from the value
196 */
197 s = strchr(tmpenv, '=');
198 if (s != NULL) {
199 *s++ = '\0';
200 rval = s;
201 } else
202 continue;
203 err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1);
204 if (err < 0) {
205 printf("libfdt: %s\n", lval, fdt_strerror(err));
206 return err;
207 }
208 }
209 return 0;
210}
211#endif /* CONFIG_OF_HAS_UBOOT_ENV */
212
213/********************************************************************/
214
215#ifdef CONFIG_OF_HAS_BD_T
216
217#define BDM(x) { .name = #x, .offset = offsetof(bd_t, bi_ ##x ) }
218
219static const struct {
220 const char *name;
221 int offset;
222} bd_map[] = {
223 BDM(memstart),
224 BDM(memsize),
225 BDM(flashstart),
226 BDM(flashsize),
227 BDM(flashoffset),
228 BDM(sramstart),
229 BDM(sramsize),
230#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \
231 || defined(CONFIG_E500)
232 BDM(immr_base),
233#endif
234#if defined(CONFIG_MPC5xxx)
235 BDM(mbar_base),
236#endif
237#if defined(CONFIG_MPC83XX)
238 BDM(immrbar),
239#endif
240#if defined(CONFIG_MPC8220)
241 BDM(mbar_base),
242 BDM(inpfreq),
243 BDM(pcifreq),
244 BDM(pevfreq),
245 BDM(flbfreq),
246 BDM(vcofreq),
247#endif
248 BDM(bootflags),
249 BDM(ip_addr),
250 BDM(intfreq),
251 BDM(busfreq),
252#ifdef CONFIG_CPM2
253 BDM(cpmfreq),
254 BDM(brgfreq),
255 BDM(sccfreq),
256 BDM(vco),
257#endif
258#if defined(CONFIG_MPC5xxx)
259 BDM(ipbfreq),
260 BDM(pcifreq),
261#endif
262 BDM(baudrate),
263};
264
265
266int fdt_bd_t(void *fdt)
267{
268 bd_t *bd = gd->bd;
269 int nodeoffset;
270 int err;
271 u32 tmp; /* used to set 32 bit integer properties */
272 int i;
273
274 err = fdt_check_header(fdt);
275 if (err < 0) {
276 printf("libfdt: %s\n", fdt_strerror(err));
277 return err;
278 }
279
280 /*
281 * See if we already have a "bd_t" node, delete it if so.
282 * Then create a new empty node.
283 */
284 nodeoffset = fdt_path_offset (fdt, "/bd_t");
285 if (nodeoffset >= 0) {
286 err = fdt_del_node(fdt, nodeoffset);
287 if (err < 0) {
288 printf("libfdt: %s\n", fdt_strerror(err));
289 return err;
290 }
291 }
292 /*
293 * Create a new node "/bd_t" (offset 0 is root level)
294 */
295 nodeoffset = fdt_add_subnode(fdt, 0, "bd_t");
296 if (nodeoffset < 0) {
297 printf("libfdt: %s\n", fdt_strerror(nodeoffset));
298 return nodeoffset;
299 }
300 /*
301 * Use the string/pointer structure to create the entries...
302 */
303 for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) {
304 tmp = cpu_to_be32(getenv("bootargs"));
305 err = fdt_setprop(fdt, nodeoffset, bd_map[i].name, &tmp, sizeof(tmp));
306 if (err < 0)
307 printf("libfdt: %s\n", fdt_strerror(err));
308 }
309 /*
310 * Add a couple of oddball entries...
311 */
312 err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6);
313 if (err < 0)
314 printf("libfdt: %s\n", fdt_strerror(err));
315 err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4);
316 if (err < 0)
317 printf("libfdt: %s\n", fdt_strerror(err));
318
319 return 0;
320}
321#endif /* CONFIG_OF_HAS_BD_T */
322
323#endif /* CONFIG_OF_LIBFDT */