mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-18 21:21:37 +00:00
Merge with /home/wd/git/u-boot/custodian/u-boot-fdt
This commit is contained in:
commit
5cca4092bd
14 changed files with 770 additions and 343 deletions
|
@ -664,19 +664,28 @@ U_BOOT_CMD(ecc, 4, 0, do_ecc,
|
|||
|
||||
#if (defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)) \
|
||||
&& defined(CONFIG_OF_BOARD_SETUP)
|
||||
|
||||
/*
|
||||
* Prototypes of functions that we use.
|
||||
*/
|
||||
void ft_cpu_setup(void *blob, bd_t *bd);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
void ft_pci_setup(void *blob, bd_t *bd);
|
||||
#endif
|
||||
|
||||
void
|
||||
ft_board_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
int nodeoffset;
|
||||
int err;
|
||||
int tmp[2];
|
||||
|
||||
nodeoffset = fdt_path_offset (fdt, "/memory");
|
||||
if (nodeoffset >= 0) {
|
||||
tmp[0] = cpu_to_be32(bd->bi_memstart);
|
||||
tmp[1] = cpu_to_be32(bd->bi_memsize);
|
||||
err = fdt_setprop(fdt, nodeoffset, "reg", tmp, sizeof(tmp));
|
||||
fdt_setprop(fdt, nodeoffset, "reg", tmp, sizeof(tmp));
|
||||
}
|
||||
#else
|
||||
u32 *p;
|
||||
|
@ -694,4 +703,5 @@ ft_board_setup(void *blob, bd_t *bd)
|
|||
#endif
|
||||
ft_cpu_setup(blob, bd);
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_OF_x */
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ COBJS = main.o ACEX1K.o altera.o bedbug.o circbuf.o cmd_autoscript.o \
|
|||
env_nand.o env_dataflash.o env_flash.o env_eeprom.o \
|
||||
env_nvram.o env_nowhere.o \
|
||||
exports.o \
|
||||
flash.o fpga.o ft_build.o \
|
||||
fdt_support.o flash.o fpga.o ft_build.o \
|
||||
hush.o kgdb.o lcd.o lists.o lynxkdi.o \
|
||||
memsize.o miiphybb.o miiphyutil.o \
|
||||
s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#if defined(CONFIG_OF_LIBFDT)
|
||||
#include <fdt.h>
|
||||
#include <libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
#endif
|
||||
#if defined(CONFIG_OF_FLAT_TREE)
|
||||
#include <ft_build.h>
|
||||
|
@ -748,7 +749,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
|
|||
of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16);
|
||||
hdr = (image_header_t *)of_flat_tree;
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
if (be32_to_cpu(fdt_magic(of_flat_tree)) == FDT_MAGIC) {
|
||||
if (fdt_check_header(of_flat_tree) == 0) {
|
||||
#else
|
||||
if (*(ulong *)of_flat_tree == OF_DT_HEADER) {
|
||||
#endif
|
||||
|
@ -795,7 +796,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
|
|||
return;
|
||||
}
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
if (be32_to_cpu(fdt_magic(of_flat_tree + sizeof(image_header_t))) != FDT_MAGIC) {
|
||||
if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) == 0) {
|
||||
#else
|
||||
if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) {
|
||||
#endif
|
||||
|
@ -836,7 +837,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
|
|||
}
|
||||
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
if (be32_to_cpu(fdt_magic(of_data)) != FDT_MAGIC) {
|
||||
if (fdt_check_header((void *)of_data) != 0) {
|
||||
#else
|
||||
if (((struct boot_param_header *)of_data)->magic != OF_DT_HEADER) {
|
||||
#endif
|
||||
|
@ -937,23 +938,44 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
|
|||
if (of_data) {
|
||||
int err;
|
||||
ulong of_start, of_len;
|
||||
|
||||
of_len = be32_to_cpu(fdt_totalsize(of_data));
|
||||
/* provide extra 8k pad */
|
||||
/* position on a 4K boundary before the initrd/kbd */
|
||||
if (initrd_start)
|
||||
of_start = initrd_start - of_len - 8192;
|
||||
of_start = initrd_start - of_len;
|
||||
else
|
||||
of_start = (ulong)kbd - of_len - 8192;
|
||||
of_start = (ulong)kbd - of_len;
|
||||
of_start &= ~(4096 - 1); /* align on page */
|
||||
debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
|
||||
of_data, of_data + of_len - 1, of_len, of_len);
|
||||
|
||||
|
||||
of_flat_tree = (char *)of_start;
|
||||
printf (" Loading Device Tree to %08lx, end %08lx ... ",
|
||||
of_start, of_start + of_len - 1);
|
||||
err = fdt_open_into(of_start, of_data, of_len);
|
||||
err = fdt_open_into((void *)of_start, (void *)of_data, of_len);
|
||||
if (err != 0) {
|
||||
printf ("libfdt: %s\n", fdt_strerror(err));
|
||||
printf ("libfdt: %s " __FILE__ " %d\n", fdt_strerror(err), __LINE__);
|
||||
}
|
||||
/*
|
||||
* Add the chosen node if it doesn't exist, add the env and bd_t
|
||||
* if the user wants it (the logic is in the subroutines).
|
||||
*/
|
||||
if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) {
|
||||
printf("Failed creating the /chosen node (0x%08X), aborting.\n", of_flat_tree);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_OF_HAS_UBOOT_ENV
|
||||
if (fdt_env(of_flat_tree) < 0) {
|
||||
printf("Failed creating the /u-boot-env node, aborting.\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_OF_HAS_BD_T
|
||||
if (fdt_bd_t(of_flat_tree) < 0) {
|
||||
printf("Failed creating the /bd_t node, aborting.\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_OF_FLAT_TREE)
|
||||
|
@ -1004,6 +1026,24 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
|
|||
ft_setup(of_flat_tree, kbd, initrd_start, initrd_end);
|
||||
/* ft_dump_blob(of_flat_tree); */
|
||||
#endif
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) {
|
||||
printf("Failed creating the /chosen node (0x%08X), aborting.\n", of_flat_tree);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_OF_HAS_UBOOT_ENV
|
||||
if (fdt_env(of_flat_tree) < 0) {
|
||||
printf("Failed creating the /u-boot-env node, aborting.\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_OF_HAS_BD_T
|
||||
if (fdt_bd_t(of_flat_tree) < 0) {
|
||||
printf("Failed creating the /bd_t node, aborting.\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif /* if defined(CONFIG_OF_LIBFDT) */
|
||||
|
||||
(*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);
|
||||
#endif
|
||||
|
|
301
common/cmd_fdt.c
301
common/cmd_fdt.c
|
@ -30,9 +30,11 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
#ifdef CONFIG_OF_LIBFDT
|
||||
|
||||
#include <asm/global_data.h>
|
||||
#include <fdt.h>
|
||||
#include <libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
|
||||
#define MAX_LEVEL 32 /* how deeply nested we will go */
|
||||
#define SCRATCHPAD 1024 /* bytes of scratchpad memory */
|
||||
|
@ -53,9 +55,6 @@ static char data[SCRATCHPAD];
|
|||
*/
|
||||
static int fdt_valid(void);
|
||||
static void print_data(const void *data, int len);
|
||||
static int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end);
|
||||
static int fdt_env(void *fdt);
|
||||
static int fdt_bd_t(void *fdt);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -437,7 +436,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
|||
* Create a chosen node
|
||||
********************************************************************/
|
||||
} else if (op == 'c') {
|
||||
fdt_chosen(fdt, 0, 0);
|
||||
fdt_chosen(fdt, 0, 0, 1);
|
||||
|
||||
/********************************************************************
|
||||
* Create a u-boot-env node
|
||||
|
@ -466,25 +465,36 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
|||
|
||||
static int fdt_valid(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (fdt == NULL) {
|
||||
printf ("The address of the fdt is invalid.\n");
|
||||
printf ("The address of the fdt is invalid (NULL).\n");
|
||||
return 0;
|
||||
}
|
||||
if (!fdt || (fdt_magic(fdt) != FDT_MAGIC)) {
|
||||
fdt = NULL;
|
||||
printf ("Unrecognized fdt: bad magic\n");
|
||||
return 0;
|
||||
}
|
||||
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) {
|
||||
printf ("Unsupported fdt version: $d < %d\n",
|
||||
FDT_FIRST_SUPPORTED_VERSION, fdt_version(fdt));
|
||||
fdt = NULL;
|
||||
return 0;
|
||||
}
|
||||
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) {
|
||||
printf ("Unsupported fdt version: $d > %d\n",
|
||||
fdt_version(fdt), FDT_LAST_SUPPORTED_VERSION);
|
||||
fdt = NULL;
|
||||
|
||||
err = fdt_check_header(fdt);
|
||||
if (err == 0)
|
||||
return 1; /* valid */
|
||||
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s", fdt_strerror(err));
|
||||
/*
|
||||
* Be more informative on bad version.
|
||||
*/
|
||||
if (err == -FDT_ERR_BADVERSION) {
|
||||
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) {
|
||||
printf (" - too old, fdt $d < %d",
|
||||
fdt_version(fdt), FDT_FIRST_SUPPORTED_VERSION);
|
||||
fdt = NULL;
|
||||
}
|
||||
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) {
|
||||
printf (" - too new, fdt $d > %d",
|
||||
fdt_version(fdt), FDT_LAST_SUPPORTED_VERSION);
|
||||
fdt = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
@ -593,255 +603,6 @@ static void print_data(const void *data, int len)
|
|||
|
||||
/********************************************************************/
|
||||
|
||||
static int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end)
|
||||
{
|
||||
bd_t *bd = gd->bd;
|
||||
int nodeoffset;
|
||||
int err;
|
||||
u32 tmp; /* used to set 32 bit integer properties */
|
||||
char *str; /* used to set string properties */
|
||||
ulong clock;
|
||||
|
||||
if (initrd_start && initrd_end) {
|
||||
err = fdt_add_reservemap_entry(fdt,
|
||||
initrd_start, initrd_end - initrd_start + 1);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we already have a "chosen" node, create it if not.
|
||||
*/
|
||||
nodeoffset = fdt_path_offset (fdt, "/chosen");
|
||||
if (nodeoffset < 0) {
|
||||
/*
|
||||
* Create a new node "/chosen" (offset 0 is root level)
|
||||
*/
|
||||
nodeoffset = fdt_add_subnode(fdt, 0, "chosen");
|
||||
if (nodeoffset < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(nodeoffset));
|
||||
return nodeoffset;
|
||||
}
|
||||
}
|
||||
|
||||
str = getenv("bootargs");
|
||||
if (str != NULL) {
|
||||
err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str)+1);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
}
|
||||
if (initrd_start && initrd_end) {
|
||||
tmp = __cpu_to_be32(initrd_start);
|
||||
err = fdt_setprop(fdt, nodeoffset, "linux,initrd-start", &tmp, sizeof(tmp));
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
tmp = __cpu_to_be32(initrd_end);
|
||||
err = fdt_setprop(fdt, nodeoffset, "linux,initrd-end", &tmp, sizeof(tmp));
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
}
|
||||
#ifdef OF_STDOUT_PATH
|
||||
err = fdt_setprop(fdt, nodeoffset, "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
#endif
|
||||
|
||||
nodeoffset = fdt_path_offset (fdt, "/cpus");
|
||||
if (nodeoffset >= 0) {
|
||||
clock = cpu_to_be32(bd->bi_intfreq);
|
||||
err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
}
|
||||
#ifdef OF_TBCLK
|
||||
nodeoffset = fdt_path_offset (fdt, "/cpus/" OF_CPU "/timebase-frequency");
|
||||
if (nodeoffset >= 0) {
|
||||
clock = cpu_to_be32(OF_TBCLK);
|
||||
err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#ifdef CONFIG_OF_HAS_BD_T
|
||||
|
||||
/* Function that returns a character from the environment */
|
||||
extern uchar(*env_get_char) (int);
|
||||
|
||||
#define BDM(x) { .name = #x, .offset = offsetof(bd_t, bi_ ##x ) }
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
int offset;
|
||||
} bd_map[] = {
|
||||
BDM(memstart),
|
||||
BDM(memsize),
|
||||
BDM(flashstart),
|
||||
BDM(flashsize),
|
||||
BDM(flashoffset),
|
||||
BDM(sramstart),
|
||||
BDM(sramsize),
|
||||
#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \
|
||||
|| defined(CONFIG_E500)
|
||||
BDM(immr_base),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC5xxx)
|
||||
BDM(mbar_base),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC83XX)
|
||||
BDM(immrbar),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC8220)
|
||||
BDM(mbar_base),
|
||||
BDM(inpfreq),
|
||||
BDM(pcifreq),
|
||||
BDM(pevfreq),
|
||||
BDM(flbfreq),
|
||||
BDM(vcofreq),
|
||||
#endif
|
||||
BDM(bootflags),
|
||||
BDM(ip_addr),
|
||||
BDM(intfreq),
|
||||
BDM(busfreq),
|
||||
#ifdef CONFIG_CPM2
|
||||
BDM(cpmfreq),
|
||||
BDM(brgfreq),
|
||||
BDM(sccfreq),
|
||||
BDM(vco),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC5xxx)
|
||||
BDM(ipbfreq),
|
||||
BDM(pcifreq),
|
||||
#endif
|
||||
BDM(baudrate),
|
||||
};
|
||||
|
||||
static int fdt_env(void *fdt)
|
||||
{
|
||||
int nodeoffset;
|
||||
int err;
|
||||
int k, nxt;
|
||||
int i;
|
||||
static char tmpenv[256];
|
||||
|
||||
/*
|
||||
* See if we already have a "u-boot-env" node, delete it if so.
|
||||
* Then create a new empty node.
|
||||
*/
|
||||
nodeoffset = fdt_path_offset (fdt, "/u-boot-env");
|
||||
if (nodeoffset >= 0) {
|
||||
err = fdt_del_node(fdt, nodeoffset);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Create a new node "/u-boot-env" (offset 0 is root level)
|
||||
*/
|
||||
nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env");
|
||||
if (nodeoffset < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(nodeoffset));
|
||||
return nodeoffset;
|
||||
}
|
||||
|
||||
for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
|
||||
char *s, *lval, *rval;
|
||||
|
||||
/*
|
||||
* Find the end of the name=definition
|
||||
*/
|
||||
for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
|
||||
;
|
||||
s = tmpenv;
|
||||
for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k)
|
||||
*s++ = env_get_char(k);
|
||||
*s++ = '\0';
|
||||
lval = tmpenv;
|
||||
/*
|
||||
* Find the first '=': it separates the name from the value
|
||||
*/
|
||||
s = strchr(tmpenv, '=');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
rval = s;
|
||||
} else
|
||||
continue;
|
||||
err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1);
|
||||
if (err < 0) {
|
||||
printf("\"%s\" - libfdt: %s\n", lval, fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_OF_HAS_UBOOT_ENV */
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#ifdef CONFIG_OF_HAS_BD_T
|
||||
static int fdt_bd_t(void *fdt)
|
||||
{
|
||||
bd_t *bd = gd->bd;
|
||||
int nodeoffset;
|
||||
int err;
|
||||
u32 tmp; /* used to set 32 bit integer properties */
|
||||
int i;
|
||||
|
||||
/*
|
||||
* See if we already have a "bd_t" node, delete it if so.
|
||||
* Then create a new empty node.
|
||||
*/
|
||||
nodeoffset = fdt_path_offset (fdt, "/bd_t");
|
||||
if (nodeoffset >= 0) {
|
||||
err = fdt_del_node(fdt, nodeoffset);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Create a new node "/bd_t" (offset 0 is root level)
|
||||
*/
|
||||
nodeoffset = fdt_add_subnode(fdt, 0, "bd_t");
|
||||
if (nodeoffset < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(nodeoffset));
|
||||
return nodeoffset;
|
||||
}
|
||||
/*
|
||||
* Use the string/pointer structure to create the entries...
|
||||
*/
|
||||
for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) {
|
||||
tmp = cpu_to_be32(getenv("bootargs"));
|
||||
err = fdt_setprop(fdt, nodeoffset, bd_map[i].name, &tmp, sizeof(tmp));
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
}
|
||||
/*
|
||||
* Add a couple of oddball entries...
|
||||
*/
|
||||
err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
|
||||
#ifdef CONFIG_OF_BOARD_SETUP
|
||||
ft_board_setup(fdt, bd);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_OF_HAS_BD_T */
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
fdt, 5, 0, do_fdt,
|
||||
"fdt - flattened device tree utility commands\n",
|
||||
|
@ -871,4 +632,4 @@ U_BOOT_CMD(
|
|||
" fdt set /cpus \"#address-cells\" \"[00 00 00 01]\"\n"
|
||||
);
|
||||
|
||||
#endif /* CONFIG_OF_FLAT_TREE */
|
||||
#endif /* CONFIG_OF_LIBFDT */
|
||||
|
|
347
common/fdt_support.c
Normal file
347
common/fdt_support.c
Normal file
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* (C) Copyright 2007
|
||||
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef CONFIG_OF_LIBFDT
|
||||
|
||||
#include <asm/global_data.h>
|
||||
#include <fdt.h>
|
||||
#include <libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
|
||||
/*
|
||||
* Global data (for the gd->bd)
|
||||
*/
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
|
||||
{
|
||||
bd_t *bd = gd->bd;
|
||||
int nodeoffset;
|
||||
int err;
|
||||
u32 tmp; /* used to set 32 bit integer properties */
|
||||
char *str; /* used to set string properties */
|
||||
ulong clock;
|
||||
|
||||
err = fdt_check_header(fdt);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
if (initrd_start && initrd_end) {
|
||||
struct fdt_reserve_entry *re;
|
||||
int used;
|
||||
int total;
|
||||
int j;
|
||||
|
||||
err = fdt_num_reservemap(fdt, &used, &total);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
if (used >= total) {
|
||||
printf("fdt_chosen: no room in the reserved map (%d of %d)\n",
|
||||
used, total);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Look for an existing entry and update it. If we don't find
|
||||
* the entry, we will j be the next available slot.
|
||||
*/
|
||||
for (j = 0; j < used; j++) {
|
||||
err = fdt_get_reservemap(fdt, j, &re);
|
||||
if (re->address == initrd_start) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
err = fdt_replace_reservemap_entry(fdt, j,
|
||||
initrd_start, initrd_end - initrd_start + 1);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the "chosen" node.
|
||||
*/
|
||||
nodeoffset = fdt_path_offset (fdt, "/chosen");
|
||||
|
||||
/*
|
||||
* If we have a "chosen" node already the "force the writing"
|
||||
* is not set, our job is done.
|
||||
*/
|
||||
if ((nodeoffset >= 0) && !force)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* No "chosen" node in the blob: create it.
|
||||
*/
|
||||
if (nodeoffset < 0) {
|
||||
/*
|
||||
* Create a new node "/chosen" (offset 0 is root level)
|
||||
*/
|
||||
nodeoffset = fdt_add_subnode(fdt, 0, "chosen");
|
||||
if (nodeoffset < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(nodeoffset));
|
||||
return nodeoffset;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update pre-existing properties, create them if non-existant.
|
||||
*/
|
||||
str = getenv("bootargs");
|
||||
if (str != NULL) {
|
||||
err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str)+1);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
}
|
||||
if (initrd_start && initrd_end) {
|
||||
tmp = __cpu_to_be32(initrd_start);
|
||||
err = fdt_setprop(fdt, nodeoffset, "linux,initrd-start", &tmp, sizeof(tmp));
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
tmp = __cpu_to_be32(initrd_end);
|
||||
err = fdt_setprop(fdt, nodeoffset, "linux,initrd-end", &tmp, sizeof(tmp));
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
}
|
||||
#ifdef OF_STDOUT_PATH
|
||||
err = fdt_setprop(fdt, nodeoffset, "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
#endif
|
||||
|
||||
nodeoffset = fdt_path_offset (fdt, "/cpus");
|
||||
if (nodeoffset >= 0) {
|
||||
clock = cpu_to_be32(bd->bi_intfreq);
|
||||
err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
}
|
||||
#ifdef OF_TBCLK
|
||||
nodeoffset = fdt_path_offset (fdt, "/cpus/" OF_CPU "/timebase-frequency");
|
||||
if (nodeoffset >= 0) {
|
||||
clock = cpu_to_be32(OF_TBCLK);
|
||||
err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#ifdef CONFIG_OF_HAS_UBOOT_ENV
|
||||
|
||||
/* Function that returns a character from the environment */
|
||||
extern uchar(*env_get_char) (int);
|
||||
|
||||
|
||||
int fdt_env(void *fdt)
|
||||
{
|
||||
int nodeoffset;
|
||||
int err;
|
||||
int k, nxt;
|
||||
int i;
|
||||
static char tmpenv[256];
|
||||
|
||||
err = fdt_check_header(fdt);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we already have a "u-boot-env" node, delete it if so.
|
||||
* Then create a new empty node.
|
||||
*/
|
||||
nodeoffset = fdt_path_offset (fdt, "/u-boot-env");
|
||||
if (nodeoffset >= 0) {
|
||||
err = fdt_del_node(fdt, nodeoffset);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Create a new node "/u-boot-env" (offset 0 is root level)
|
||||
*/
|
||||
nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env");
|
||||
if (nodeoffset < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(nodeoffset));
|
||||
return nodeoffset;
|
||||
}
|
||||
|
||||
for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
|
||||
char *s, *lval, *rval;
|
||||
|
||||
/*
|
||||
* Find the end of the name=definition
|
||||
*/
|
||||
for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
|
||||
;
|
||||
s = tmpenv;
|
||||
for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k)
|
||||
*s++ = env_get_char(k);
|
||||
*s++ = '\0';
|
||||
lval = tmpenv;
|
||||
/*
|
||||
* Find the first '=': it separates the name from the value
|
||||
*/
|
||||
s = strchr(tmpenv, '=');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
rval = s;
|
||||
} else
|
||||
continue;
|
||||
err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* ifdef CONFIG_OF_HAS_UBOOT_ENV */
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#ifdef CONFIG_OF_HAS_BD_T
|
||||
|
||||
#define BDM(x) { .name = #x, .offset = offsetof(bd_t, bi_ ##x ) }
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
int offset;
|
||||
} bd_map[] = {
|
||||
BDM(memstart),
|
||||
BDM(memsize),
|
||||
BDM(flashstart),
|
||||
BDM(flashsize),
|
||||
BDM(flashoffset),
|
||||
BDM(sramstart),
|
||||
BDM(sramsize),
|
||||
#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \
|
||||
|| defined(CONFIG_E500)
|
||||
BDM(immr_base),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC5xxx)
|
||||
BDM(mbar_base),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC83XX)
|
||||
BDM(immrbar),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC8220)
|
||||
BDM(mbar_base),
|
||||
BDM(inpfreq),
|
||||
BDM(pcifreq),
|
||||
BDM(pevfreq),
|
||||
BDM(flbfreq),
|
||||
BDM(vcofreq),
|
||||
#endif
|
||||
BDM(bootflags),
|
||||
BDM(ip_addr),
|
||||
BDM(intfreq),
|
||||
BDM(busfreq),
|
||||
#ifdef CONFIG_CPM2
|
||||
BDM(cpmfreq),
|
||||
BDM(brgfreq),
|
||||
BDM(sccfreq),
|
||||
BDM(vco),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC5xxx)
|
||||
BDM(ipbfreq),
|
||||
BDM(pcifreq),
|
||||
#endif
|
||||
BDM(baudrate),
|
||||
};
|
||||
|
||||
|
||||
int fdt_bd_t(void *fdt)
|
||||
{
|
||||
bd_t *bd = gd->bd;
|
||||
int nodeoffset;
|
||||
int err;
|
||||
u32 tmp; /* used to set 32 bit integer properties */
|
||||
int i;
|
||||
|
||||
err = fdt_check_header(fdt);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we already have a "bd_t" node, delete it if so.
|
||||
* Then create a new empty node.
|
||||
*/
|
||||
nodeoffset = fdt_path_offset (fdt, "/bd_t");
|
||||
if (nodeoffset >= 0) {
|
||||
err = fdt_del_node(fdt, nodeoffset);
|
||||
if (err < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Create a new node "/bd_t" (offset 0 is root level)
|
||||
*/
|
||||
nodeoffset = fdt_add_subnode(fdt, 0, "bd_t");
|
||||
if (nodeoffset < 0) {
|
||||
printf("libfdt: %s\n", fdt_strerror(nodeoffset));
|
||||
return nodeoffset;
|
||||
}
|
||||
/*
|
||||
* Use the string/pointer structure to create the entries...
|
||||
*/
|
||||
for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) {
|
||||
tmp = cpu_to_be32(getenv("bootargs"));
|
||||
err = fdt_setprop(fdt, nodeoffset, bd_map[i].name, &tmp, sizeof(tmp));
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
}
|
||||
/*
|
||||
* Add a couple of oddball entries...
|
||||
*/
|
||||
err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4);
|
||||
if (err < 0)
|
||||
printf("libfdt: %s\n", fdt_strerror(err));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* ifdef CONFIG_OF_HAS_BD_T */
|
||||
|
||||
#endif /* CONFIG_OF_LIBFDT */
|
|
@ -299,93 +299,175 @@ void watchdog_reset (void)
|
|||
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
|
||||
/*
|
||||
* "Setter" functions used to add/modify FDT entries.
|
||||
*/
|
||||
static int fdt_set_eth0(void *fdt, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
/*
|
||||
* Fix it up if it exists, don't create it if it doesn't exist.
|
||||
*/
|
||||
if (fdt_get_property(fdt, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6);
|
||||
}
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
#ifdef CONFIG_HAS_ETH1
|
||||
/* second onboard ethernet port */
|
||||
static int fdt_set_eth1(void *fdt, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
/*
|
||||
* Fix it up if it exists, don't create it if it doesn't exist.
|
||||
*/
|
||||
if (fdt_get_property(fdt, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet1addr, 6);
|
||||
}
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_HAS_ETH2
|
||||
/* third onboard ethernet port */
|
||||
static int fdt_set_eth2(void *fdt, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
/*
|
||||
* Fix it up if it exists, don't create it if it doesn't exist.
|
||||
*/
|
||||
if (fdt_get_property(fdt, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet2addr, 6);
|
||||
}
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_HAS_ETH3
|
||||
/* fourth onboard ethernet port */
|
||||
static int fdt_set_eth3(void *fdt, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
/*
|
||||
* Fix it up if it exists, don't create it if it doesn't exist.
|
||||
*/
|
||||
if (fdt_get_property(fdt, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet3addr, 6);
|
||||
}
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
u32 tmp;
|
||||
/*
|
||||
* Create or update the property.
|
||||
*/
|
||||
tmp = cpu_to_be32(bd->bi_busfreq);
|
||||
return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Fixups to the fdt. If "create" is TRUE, the node is created
|
||||
* unconditionally. If "create" is FALSE, the node is updated
|
||||
* only if it already exists.
|
||||
*/
|
||||
#define FT_UPDATE 0x00000000 /* update existing property only */
|
||||
#define FT_CREATE 0x00000001 /* create property if it doesn't exist */
|
||||
#define FT_BUSFREQ 0x00000002 /* source is bd->bi_busfreq */
|
||||
#define FT_ENETADDR 0x00000004 /* source is bd->bi_enetaddr */
|
||||
static const struct {
|
||||
int createflags;
|
||||
char *node;
|
||||
char *prop;
|
||||
int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd);
|
||||
} fixup_props[] = {
|
||||
{ FT_CREATE | FT_BUSFREQ,
|
||||
"/cpus/" OF_CPU,
|
||||
{ "/cpus/" OF_CPU,
|
||||
"bus-frequency",
|
||||
fdt_set_busfreq
|
||||
},
|
||||
{ FT_CREATE | FT_BUSFREQ,
|
||||
"/cpus/" OF_SOC,
|
||||
"bus-frequency"
|
||||
{ "/cpus/" OF_SOC,
|
||||
"bus-frequency",
|
||||
fdt_set_busfreq
|
||||
},
|
||||
{ FT_CREATE | FT_BUSFREQ,
|
||||
"/" OF_SOC "/serial@4500/",
|
||||
"clock-frequency"
|
||||
{ "/" OF_SOC "/serial@4500/",
|
||||
"clock-frequency",
|
||||
fdt_set_busfreq
|
||||
},
|
||||
{ FT_CREATE | FT_BUSFREQ,
|
||||
"/" OF_SOC "/serial@4600/",
|
||||
"clock-frequency"
|
||||
{ "/" OF_SOC "/serial@4600/",
|
||||
"clock-frequency",
|
||||
fdt_set_busfreq
|
||||
},
|
||||
#ifdef CONFIG_MPC83XX_TSEC1
|
||||
{ FT_UPDATE | FT_ENETADDR,
|
||||
"/" OF_SOC "/ethernet@24000,
|
||||
{ "/" OF_SOC "/ethernet@24000,
|
||||
"mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
{ FT_UPDATE | FT_ENETADDR,
|
||||
"/" OF_SOC "/ethernet@24000,
|
||||
{ "/" OF_SOC "/ethernet@24000,
|
||||
"local-mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_MPC83XX_TSEC2
|
||||
{ FT_UPDATE | FT_ENETADDR,
|
||||
"/" OF_SOC "/ethernet@25000,
|
||||
{ "/" OF_SOC "/ethernet@25000,
|
||||
"mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
{ FT_UPDATE | FT_ENETADDR,
|
||||
"/" OF_SOC "/ethernet@25000,
|
||||
{ "/" OF_SOC "/ethernet@25000,
|
||||
"local-mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_UEC_ETH1
|
||||
#if CFG_UEC1_UCC_NUM == 0 /* UCC1 */
|
||||
{ "/" OF_QE "/ucc@2000/mac-address",
|
||||
"mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
{ "/" OF_QE "/ucc@2000/mac-address",
|
||||
"local-mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
#elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */
|
||||
{ "/" OF_QE "/ucc@2200/mac-address",
|
||||
"mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
{ "/" OF_QE "/ucc@2200/mac-address",
|
||||
"local-mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_UEC_ETH2
|
||||
#if CFG_UEC2_UCC_NUM == 1 /* UCC2 */
|
||||
{ "/" OF_QE "/ucc@3000/mac-address",
|
||||
"mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
{ "/" OF_QE "/ucc@3000/mac-address",
|
||||
"local-mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
#elif CFG_UEC1_UCC_NUM == 3 /* UCC4 */
|
||||
{ "/" OF_QE "/ucc@3200/mac-address",
|
||||
"mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
{ "/" OF_QE "/ucc@3200/mac-address",
|
||||
"local-mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
ft_cpu_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
int nodeoffset;
|
||||
int err;
|
||||
int j;
|
||||
int nodeoffset;
|
||||
int err;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) {
|
||||
nodeoffset = fdt_path_offset (fdt, fixup_props[j].node);
|
||||
nodeoffset = fdt_path_offset(fdt, fixup_props[j].node);
|
||||
if (nodeoffset >= 0) {
|
||||
/*
|
||||
* If unconditional create or the property already exists...
|
||||
*/
|
||||
if ((fixup_props[j].createflags & FT_CREATE) ||
|
||||
(fdt_get_property(fdt, nodeoffset, fixup_props[j].prop, 0))) {
|
||||
if (fixup_props[j].createflags & FT_BUSFREQ) {
|
||||
u32 tmp;
|
||||
|
||||
tmp = cpu_to_be32(bd->bi_busfreq);
|
||||
err = fdt_setprop(fdt, nodeoffset,
|
||||
fixup_props[j].prop, &tmp, sizeof(tmp));
|
||||
} else if (fixup_props[j].createflags & FT_ENETADDR) {
|
||||
err = fdt_setprop(fdt, nodeoffset,
|
||||
fixup_props[j].prop, bd->bi_enetaddr, 6);
|
||||
} else {
|
||||
printf("ft_cpu_setup: %s %s has no flag for the value to set\n",
|
||||
fixup_props[j].node,
|
||||
fixup_props[j].prop);
|
||||
}
|
||||
if (err < 0)
|
||||
printf("libfdt: %s %s returned %s\n",
|
||||
fixup_props[j].node,
|
||||
fixup_props[j].prop,
|
||||
fdt_strerror(err));
|
||||
}
|
||||
err = (*fixup_props[j].set_fn)(blob, nodeoffset, fixup_props[j].prop, bd);
|
||||
if (err < 0)
|
||||
printf("set_fn/libfdt: %s %s returned %s\n",
|
||||
fixup_props[j].node,
|
||||
fixup_props[j].prop,
|
||||
fdt_strerror(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
* libfdt - Flat Device Tree manipulation
|
||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _FDT_H
|
||||
#define _FDT_H
|
||||
|
||||
|
|
42
include/fdt_support.h
Normal file
42
include/fdt_support.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* (C) Copyright 2007
|
||||
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __FDT_SUPPORT_H
|
||||
#define __FDT_SUPPORT_H
|
||||
|
||||
#ifdef CONFIG_OF_LIBFDT
|
||||
|
||||
#include <fdt.h>
|
||||
|
||||
int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force);
|
||||
|
||||
#ifdef CONFIG_OF_HAS_UBOOT_ENV
|
||||
int fdt_env(void *fdt);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF_HAS_BD_T
|
||||
int fdt_bd_t(void *fdt);
|
||||
#endif
|
||||
|
||||
#endif /* ifdef CONFIG_OF_LIBFDT */
|
||||
#endif /* ifndef __FDT_SUPPORT_H */
|
|
@ -1,5 +1,3 @@
|
|||
#ifndef _LIBFDT_H
|
||||
#define _LIBFDT_H
|
||||
/*
|
||||
* libfdt - Flat Device Tree manipulation
|
||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||
|
@ -19,6 +17,9 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _LIBFDT_H
|
||||
#define _LIBFDT_H
|
||||
|
||||
#include <fdt.h>
|
||||
#include <libfdt_env.h>
|
||||
|
||||
|
@ -60,6 +61,8 @@
|
|||
#define fdt_set_header(fdt, field, val) \
|
||||
((struct fdt_header *)(fdt))->field = cpu_to_fdt32(val)
|
||||
|
||||
int fdt_check_header(const void *fdt);
|
||||
|
||||
void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
|
||||
|
||||
#define fdt_offset_ptr_typed(fdt, offset, var) \
|
||||
|
@ -83,6 +86,8 @@ void *fdt_getprop(const void *fdt, int nodeoffset,
|
|||
|
||||
uint32_t fdt_next_tag(const void *fdt, int offset,
|
||||
int *nextoffset, char **namep);
|
||||
int fdt_num_reservemap(void *fdt, int *used, int *total);
|
||||
int fdt_get_reservemap(void *fdt, int n, struct fdt_reserve_entry *re);
|
||||
|
||||
/* Write-in-place functions */
|
||||
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
||||
|
@ -96,6 +101,8 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
|||
|
||||
int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
|
||||
int fdt_nop_node(void *fdt, int nodeoffset);
|
||||
int fdt_insert_reservemap_entry(void *fdt, int n, uint64_t addr, uint64_t size);
|
||||
|
||||
|
||||
/* Sequential-write functions */
|
||||
int fdt_create(void *buf, int bufsize);
|
||||
|
@ -112,6 +119,7 @@ int fdt_property(void *fdt, const char *name, const void *val, int len);
|
|||
fdt_property(fdt, name, str, strlen(str)+1)
|
||||
int fdt_end_node(void *fdt);
|
||||
int fdt_finish(void *fdt);
|
||||
int fdt_replace_reservemap_entry(void *fdt, int n, uint64_t addr, uint64_t size);
|
||||
|
||||
/* Read-write functions */
|
||||
int fdt_open_into(void *fdt, void *buf, int bufsize);
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* libfdt - Flat Device Tree manipulation (build/run environment adaptation)
|
||||
* Copyright (C) 2007 Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
|
||||
* Original version written by David Gibson, IBM Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _LIBFDT_ENV_H
|
||||
#define _LIBFDT_ENV_H
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "libfdt_internal.h"
|
||||
|
||||
int _fdt_check_header(const void *fdt)
|
||||
int fdt_check_header(const void *fdt)
|
||||
{
|
||||
if (fdt_magic(fdt) == FDT_MAGIC) {
|
||||
/* Complete tree */
|
||||
|
@ -72,7 +72,7 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
|
|||
|
||||
int fdt_move(const void *fdt, void *buf, int bufsize)
|
||||
{
|
||||
int err = _fdt_check_header(fdt);
|
||||
int err = fdt_check_header(fdt);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#define CHECK_HEADER(fdt) { \
|
||||
int err; \
|
||||
if ((err = _fdt_check_header(fdt)) != 0) \
|
||||
if ((err = fdt_check_header(fdt)) != 0) \
|
||||
return err; \
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ struct fdt_property *fdt_get_property(const void *fdt,
|
|||
int offset, nextoffset;
|
||||
int err;
|
||||
|
||||
if ((err = _fdt_check_header(fdt)) != 0)
|
||||
if ((err = fdt_check_header(fdt)) != 0)
|
||||
goto fail;
|
||||
|
||||
err = -FDT_ERR_BADOFFSET;
|
||||
|
@ -329,3 +329,75 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset, char **namep
|
|||
|
||||
return tag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of used reserve map entries and total slots available.
|
||||
*/
|
||||
int fdt_num_reservemap(void *fdt, int *used, int *total)
|
||||
{
|
||||
struct fdt_reserve_entry *re;
|
||||
int start;
|
||||
int end;
|
||||
int err = fdt_check_header(fdt);
|
||||
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
start = fdt_off_mem_rsvmap(fdt);
|
||||
|
||||
/*
|
||||
* Convention is that the reserve map is before the dt_struct,
|
||||
* but it does not have to be.
|
||||
*/
|
||||
end = fdt_totalsize(fdt);
|
||||
if (end > fdt_off_dt_struct(fdt))
|
||||
end = fdt_off_dt_struct(fdt);
|
||||
if (end > fdt_off_dt_strings(fdt))
|
||||
end = fdt_off_dt_strings(fdt);
|
||||
|
||||
/*
|
||||
* Since the reserved area list is zero terminated, you get one fewer.
|
||||
*/
|
||||
if (total)
|
||||
*total = ((end - start) / sizeof(struct fdt_reserve_entry)) - 1;
|
||||
|
||||
if (used) {
|
||||
*used = 0;
|
||||
while (start < end) {
|
||||
re = (struct fdt_reserve_entry *)(fdt + start);
|
||||
if (re->size == 0)
|
||||
return 0; /* zero size terminates the list */
|
||||
|
||||
*used += 1;
|
||||
start += sizeof(struct fdt_reserve_entry);
|
||||
}
|
||||
/*
|
||||
* If we get here, there was no zero size termination.
|
||||
*/
|
||||
return -FDT_ERR_BADLAYOUT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the nth reserve map entry.
|
||||
*/
|
||||
int fdt_get_reservemap(void *fdt, int n, struct fdt_reserve_entry *re)
|
||||
{
|
||||
int used;
|
||||
int total;
|
||||
int err;
|
||||
|
||||
err = fdt_num_reservemap(fdt, &used, &total);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
if (n >= total)
|
||||
return -FDT_ERR_NOSPACE;
|
||||
if (re) {
|
||||
*re = *(struct fdt_reserve_entry *)
|
||||
_fdt_offset_ptr(fdt, n * sizeof(struct fdt_reserve_entry));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ static int rw_check_header(void *fdt)
|
|||
{
|
||||
int err;
|
||||
|
||||
if ((err = _fdt_check_header(fdt)))
|
||||
if ((err = fdt_check_header(fdt)))
|
||||
return err;
|
||||
if (fdt_version(fdt) < 0x11)
|
||||
return -FDT_ERR_BADVERSION;
|
||||
|
|
|
@ -110,3 +110,29 @@ int fdt_nop_node(void *fdt, int nodeoffset)
|
|||
nop_region(fdt_offset_ptr(fdt, nodeoffset, 0), endoffset - nodeoffset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace a reserve map entry in the nth slot.
|
||||
*/
|
||||
int fdt_replace_reservemap_entry(void *fdt, int n, uint64_t addr, uint64_t size)
|
||||
{
|
||||
struct fdt_reserve_entry *re;
|
||||
int used;
|
||||
int total;
|
||||
int err;
|
||||
|
||||
err = fdt_num_reservemap(fdt, &used, &total);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
if (n >= total)
|
||||
return -FDT_ERR_NOSPACE;
|
||||
re = (struct fdt_reserve_entry *)
|
||||
(fdt + fdt_off_mem_rsvmap(fdt) +
|
||||
(n * sizeof(struct fdt_reserve_entry)));
|
||||
re->address = cpu_to_fdt64(addr);
|
||||
re->size = cpu_to_fdt64(size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue