return 4;
}
-/*
- * Write a 4 or 8 byte big endian cell
- */
-static void write_cell(u8 *addr, u64 val, int size)
-{
- int shift = (size - 1) * 8;
- while (size-- > 0) {
- *addr++ = (val >> shift) & 0xff;
- shift -= 8;
- }
-}
-
/**
* fdt_getprop_u32_default_node - Return a node's property or a default
*
}
#endif
+static inline int fdt_setprop_uxx(void *fdt, int nodeoffset, const char *name,
+ uint64_t val, int is_u64)
+{
+ if (is_u64)
+ return fdt_setprop_u64(fdt, nodeoffset, name, val);
+ else
+ return fdt_setprop_u32(fdt, nodeoffset, name, (uint32_t)val);
+}
+
+
int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end)
{
- int nodeoffset, addr_cell_len;
+ int nodeoffset;
int err, j, total;
- fdt64_t tmp;
+ int is_u64;
uint64_t addr, size;
+ /* just return if the size of initrd is zero */
+ if (initrd_start == initrd_end)
+ return 0;
+
/* find or create "/chosen" node. */
nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
if (nodeoffset < 0)
return nodeoffset;
- /* just return if initrd_start/end aren't valid */
- if ((initrd_start == 0) || (initrd_end == 0))
- return 0;
-
total = fdt_num_mem_rsv(fdt);
/*
return err;
}
- addr_cell_len = get_cells_len(fdt, "#address-cells");
+ is_u64 = (get_cells_len(fdt, "#address-cells") == 8);
+
+ err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-start",
+ (uint64_t)initrd_start, is_u64);
- write_cell((u8 *)&tmp, initrd_start, addr_cell_len);
- err = fdt_setprop(fdt, nodeoffset,
- "linux,initrd-start", &tmp, addr_cell_len);
if (err < 0) {
printf("WARNING: could not set linux,initrd-start %s.\n",
fdt_strerror(err));
return err;
}
- write_cell((u8 *)&tmp, initrd_end, addr_cell_len);
- err = fdt_setprop(fdt, nodeoffset,
- "linux,initrd-end", &tmp, addr_cell_len);
+
+ err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-end",
+ (uint64_t)initrd_end, is_u64);
+
if (err < 0) {
printf("WARNING: could not set linux,initrd-end %s.\n",
fdt_strerror(err));
do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create);
}
+/*
+ * fdt_pack_reg - pack address and size array into the "reg"-suitable stream
+ */
+static int fdt_pack_reg(const void *fdt, void *buf, uint64_t *address,
+ uint64_t *size, int n)
+{
+ int i;
+ int address_len = get_cells_len(fdt, "#address-cells");
+ int size_len = get_cells_len(fdt, "#size-cells");
+ char *p = buf;
+
+ for (i = 0; i < n; i++) {
+ if (address_len == 8)
+ *(fdt64_t *)p = cpu_to_fdt64(address[i]);
+ else
+ *(fdt32_t *)p = cpu_to_fdt32(address[i]);
+ p += address_len;
+
+ if (size_len == 8)
+ *(fdt64_t *)p = cpu_to_fdt64(size[i]);
+ else
+ *(fdt32_t *)p = cpu_to_fdt32(size[i]);
+ p += size_len;
+ }
+
+ return p - (char *)buf;
+}
+
#ifdef CONFIG_NR_DRAM_BANKS
#define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS
#else
int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
{
int err, nodeoffset;
- int addr_cell_len, size_cell_len, len;
+ int len;
u8 tmp[MEMORY_BANKS_MAX * 16]; /* Up to 64-bit address + 64-bit size */
- int bank;
if (banks > MEMORY_BANKS_MAX) {
printf("%s: num banks %d exceeds hardcoded limit %d."
return err;
}
- addr_cell_len = get_cells_len(blob, "#address-cells");
- size_cell_len = get_cells_len(blob, "#size-cells");
-
- for (bank = 0, len = 0; bank < banks; bank++) {
- write_cell(tmp + len, start[bank], addr_cell_len);
- len += addr_cell_len;
-
- write_cell(tmp + len, size[bank], size_cell_len);
- len += size_cell_len;
- }
+ len = fdt_pack_reg(blob, tmp, start, size, banks);
err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
if (err < 0) {