]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/fdt_support.c
karo: tx51: remove duplicate CONFIG_SYS_SDRAM_CLK definition
[karo-tx-uboot.git] / common / fdt_support.c
index 46aa84220b2b981d0ea42be3e67ab50af1ed4958..ce7527a931563f49fa585964451b60c1415a2816 100644 (file)
@@ -2,25 +2,9 @@
  * (C) Copyright 2007
  * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
  *
- * Copyright 2010 Freescale Semiconductor, Inc.
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
  *
- * 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
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
@@ -28,7 +12,6 @@
 #include <linux/ctype.h>
 #include <linux/types.h>
 #include <asm/global_data.h>
-#include <fdt.h>
 #include <libfdt.h>
 #include <fdt_support.h>
 #include <exports.h>
@@ -49,10 +32,10 @@ DECLARE_GLOBAL_DATA_PTR;
  * Convenience function to find a node and return it's property or a
  * default value if it doesn't exist.
  */
-u32 fdt_getprop_u32_default(void *fdt, const char *path, const char *prop,
-                               const u32 dflt)
+u32 fdt_getprop_u32_default(const void *fdt, const char *path,
+                               const char *prop, const u32 dflt)
 {
-       const u32 *val;
+       const fdt32_t *val;
        int off;
 
        off = fdt_path_offset(fdt, path);
@@ -61,7 +44,7 @@ u32 fdt_getprop_u32_default(void *fdt, const char *path, const char *prop,
 
        val = fdt_getprop(fdt, off, prop, NULL);
        if (val)
-               return *val;
+               return fdt32_to_cpu(*val);
        else
                return dflt;
 }
@@ -86,7 +69,7 @@ int fdt_find_and_setprop(void *fdt, const char *node, const char *prop,
        if (nodeoff < 0)
                return nodeoff;
 
-       if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL))
+       if ((!create) && (fdt_get_property(fdt, nodeoff, prop, NULL) == NULL))
                return 0; /* create flag not set; so exit quietly */
 
        return fdt_setprop(fdt, nodeoff, prop, val, len);
@@ -94,7 +77,7 @@ int fdt_find_and_setprop(void *fdt, const char *node, const char *prop,
 
 #ifdef CONFIG_OF_STDOUT_VIA_ALIAS
 
-#ifdef CONFIG_SERIAL_MULTI
+#ifdef CONFIG_CONS_INDEX
 static void fdt_fill_multisername(char *sername, size_t maxlen)
 {
        const char *outname = stdio_devices[stdout]->name;
@@ -106,9 +89,7 @@ static void fdt_fill_multisername(char *sername, size_t maxlen)
        if (strcmp(outname + 1, "serial") > 0)
                strncpy(sername, outname + 1, maxlen);
 }
-#else
-static inline void fdt_fill_multisername(char *sername, size_t maxlen) {}
-#endif /* CONFIG_SERIAL_MULTI */
+#endif
 
 static int fdt_fixup_stdout(void *fdt, int chosenoff)
 {
@@ -152,7 +133,7 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force)
 {
        int   nodeoffset;
        int   err, j, total;
-       u32   tmp;
+       fdt32_t  tmp;
        const char *path;
        uint64_t addr, size;
 
@@ -191,7 +172,7 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force)
 
        path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL);
        if ((path == NULL) || force) {
-               tmp = __cpu_to_be32(initrd_start);
+               tmp = cpu_to_fdt32(initrd_start);
                err = fdt_setprop(fdt, nodeoffset,
                        "linux,initrd-start", &tmp, sizeof(tmp));
                if (err < 0) {
@@ -200,7 +181,7 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force)
                                fdt_strerror(err));
                        return err;
                }
-               tmp = __cpu_to_be32(initrd_end);
+               tmp = cpu_to_fdt32(initrd_end);
                err = fdt_setprop(fdt, nodeoffset,
                        "linux,initrd-end", &tmp, sizeof(tmp));
                if (err < 0) {
@@ -303,8 +284,8 @@ void do_fixup_by_path(void *fdt, const char *path, const char *prop,
 void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop,
                          u32 val, int create)
 {
-       val = cpu_to_fdt32(val);
-       do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create);
+       fdt32_t tmp = cpu_to_fdt32(val);
+       do_fixup_by_path(fdt, path, prop, &tmp, sizeof(tmp), create);
 }
 
 void do_fixup_by_prop(void *fdt,
@@ -322,7 +303,7 @@ void do_fixup_by_prop(void *fdt,
 #endif
        off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen);
        while (off != -FDT_ERR_NOTFOUND) {
-               if (create || (fdt_get_property(fdt, off, prop, 0) != NULL))
+               if (create || (fdt_get_property(fdt, off, prop, NULL) != NULL))
                        fdt_setprop(fdt, off, prop, val, len);
                off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen);
        }
@@ -332,8 +313,8 @@ void do_fixup_by_prop_u32(void *fdt,
                          const char *pname, const void *pval, int plen,
                          const char *prop, u32 val, int create)
 {
-       val = cpu_to_fdt32(val);
-       do_fixup_by_prop(fdt, pname, pval, plen, prop, &val, 4, create);
+       fdt32_t tmp = cpu_to_fdt32(val);
+       do_fixup_by_prop(fdt, pname, pval, plen, prop, &tmp, 4, create);
 }
 
 void do_fixup_by_compat(void *fdt, const char *compat,
@@ -349,7 +330,7 @@ void do_fixup_by_compat(void *fdt, const char *compat,
 #endif
        off = fdt_node_offset_by_compatible(fdt, -1, compat);
        while (off != -FDT_ERR_NOTFOUND) {
-               if (create || (fdt_get_property(fdt, off, prop, 0) != NULL))
+               if (create || (fdt_get_property(fdt, off, prop, NULL) != NULL))
                        fdt_setprop(fdt, off, prop, val, len);
                off = fdt_node_offset_by_compatible(fdt, off, compat);
        }
@@ -358,8 +339,8 @@ void do_fixup_by_compat(void *fdt, const char *compat,
 void do_fixup_by_compat_u32(void *fdt, const char *compat,
                            const char *prop, u32 val, int create)
 {
-       val = cpu_to_fdt32(val);
-       do_fixup_by_compat(fdt, compat, prop, &val, 4, create);
+       fdt32_t tmp = cpu_to_fdt32(val);
+       do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create);
 }
 
 /*
@@ -369,10 +350,10 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat,
  */
 static int get_cells_len(void *blob, char *nr_cells_name)
 {
-       const u32 *cell;
+       const fdt32_t *cell;
 
        cell = fdt_getprop(blob, 0, nr_cells_name, NULL);
-       if (cell && *cell == 2)
+       if (cell && fdt32_to_cpu(*cell) == 2)
                return 8;
 
        return 4;
@@ -390,13 +371,25 @@ static void write_cell(u8 *addr, u64 val, int size)
        }
 }
 
+#ifdef CONFIG_NR_DRAM_BANKS
+#define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS
+#else
+#define MEMORY_BANKS_MAX 4
+#endif
 int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
 {
        int err, nodeoffset;
        int addr_cell_len, size_cell_len, len;
-       u8 tmp[banks * 16]; /* Up to 64-bit address + 64-bit size */
+       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."
+                      " Recompile with higher MEMORY_BANKS_MAX?\n",
+                      __FUNCTION__, banks, MEMORY_BANKS_MAX);
+               return -1;
+       }
+
        err = fdt_check_header(blob);
        if (err < 0) {
                printf("%s: %s\n", __FUNCTION__, fdt_strerror(err));
@@ -449,7 +442,7 @@ void fdt_fixup_ethernet(void *fdt)
 {
        int node, i, j;
        char enet[16], *tmp, *end;
-       char mac[16] = "ethaddr";
+       char mac[16];
        const char *path;
        unsigned char mac_addr[6];
 
@@ -458,6 +451,7 @@ void fdt_fixup_ethernet(void *fdt)
                return;
 
        i = 0;
+       strcpy(mac, "ethaddr");
        while ((tmp = getenv(mac)) != NULL) {
                sprintf(enet, "ethernet%d", i);
                path = fdt_getprop(fdt, node, enet, NULL);
@@ -495,7 +489,7 @@ int fdt_resize(void *blob)
        total = fdt_num_mem_rsv(blob);
        for (i = 0; i < total; i++) {
                fdt_get_mem_rsv(blob, i, &addr, &size);
-               if (addr == (uint64_t)(u32)blob) {
+               if (addr == (uintptr_t)blob) {
                        fdt_del_mem_rsv(blob, i);
                        break;
                }
@@ -511,17 +505,18 @@ int fdt_resize(void *blob)
                fdt_size_dt_strings(blob) + 5 * sizeof(struct fdt_reserve_entry);
 
        /* Make it so the fdt ends on a page boundary */
-       actualsize = ALIGN(actualsize + ((uint)blob & 0xfff), 0x1000);
-       actualsize = actualsize - ((uint)blob & 0xfff);
+       actualsize = ALIGN(actualsize + ((uintptr_t)blob & 0xfff), 0x1000);
+       actualsize = actualsize - ((uintptr_t)blob & 0xfff);
 
        /* Change the fdt header to reflect the correct size */
        fdt_set_totalsize(blob, actualsize);
 
        /* Add the new reservation */
-       ret = fdt_add_mem_rsv(blob, (uint)blob, actualsize);
+       ret = fdt_add_mem_rsv(blob, (uintptr_t)blob, actualsize);
        if (ret < 0)
                return ret;
-
+       if (getenv("fdtsize"))
+               setenv_hex("fdtsize", actualsize);
        return actualsize;
 }
 
@@ -905,11 +900,11 @@ void fdt_del_node_and_alias(void *blob, const char *alias)
 }
 
 /* Helper to read a big number; size is in cells (not bytes) */
-static inline u64 of_read_number(const __be32 *cell, int size)
+static inline u64 of_read_number(const fdt32_t *cell, int size)
 {
        u64 r = 0;
        while (size--)
-               r = (r << 32) | be32_to_cpu(*(cell++));
+               r = (r << 32) | fdt32_to_cpu(*(cell++));
        return r;
 }
 
@@ -923,7 +918,7 @@ static inline u64 of_read_number(const __be32 *cell, int size)
 
 /* Debug utility */
 #ifdef DEBUG
-static void of_dump_addr(const char *s, const u32 *addr, int na)
+static void of_dump_addr(const char *s, const fdt32_t *addr, int na)
 {
        printf("%s", s);
        while(na--)
@@ -931,7 +926,7 @@ static void of_dump_addr(const char *s, const u32 *addr, int na)
        printf("\n");
 }
 #else
-static void of_dump_addr(const char *s, const u32 *addr, int na) { }
+static void of_dump_addr(const char *s, const fdt32_t *addr, int na) { }
 #endif
 
 /* Callbacks for bus specific translators */
@@ -940,21 +935,21 @@ struct of_bus {
        const char      *addresses;
        void            (*count_cells)(void *blob, int parentoffset,
                                int *addrc, int *sizec);
-       u64             (*map)(u32 *addr, const u32 *range,
+       u64             (*map)(fdt32_t *addr, const fdt32_t *range,
                                int na, int ns, int pna);
-       int             (*translate)(u32 *addr, u64 offset, int na);
+       int             (*translate)(fdt32_t *addr, u64 offset, int na);
 };
 
 /* Default translator (generic bus) */
 static void of_bus_default_count_cells(void *blob, int parentoffset,
                                        int *addrc, int *sizec)
 {
-       const u32 *prop;
+       const fdt32_t *prop;
 
        if (addrc) {
                prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL);
                if (prop)
-                       *addrc = be32_to_cpup((u32 *)prop);
+                       *addrc = be32_to_cpup(prop);
                else
                        *addrc = 2;
        }
@@ -962,13 +957,13 @@ static void of_bus_default_count_cells(void *blob, int parentoffset,
        if (sizec) {
                prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL);
                if (prop)
-                       *sizec = be32_to_cpup((u32 *)prop);
+                       *sizec = be32_to_cpup(prop);
                else
                        *sizec = 1;
        }
 }
 
-static u64 of_bus_default_map(u32 *addr, const u32 *range,
+static u64 of_bus_default_map(fdt32_t *addr, const fdt32_t *range,
                int na, int ns, int pna)
 {
        u64 cp, s, da;
@@ -985,14 +980,14 @@ static u64 of_bus_default_map(u32 *addr, const u32 *range,
        return da - cp;
 }
 
-static int of_bus_default_translate(u32 *addr, u64 offset, int na)
+static int of_bus_default_translate(fdt32_t *addr, u64 offset, int na)
 {
        u64 a = of_read_number(addr, na);
        memset(addr, 0, na * 4);
        a += offset;
        if (na > 1)
-               addr[na - 2] = a >> 32;
-       addr[na - 1] = a & 0xffffffffu;
+               addr[na - 2] = cpu_to_fdt32(a >> 32);
+       addr[na - 1] = cpu_to_fdt32(a & 0xffffffffu);
 
        return 0;
 }
@@ -1010,10 +1005,10 @@ static struct of_bus of_busses[] = {
 };
 
 static int of_translate_one(void * blob, int parent, struct of_bus *bus,
-                           struct of_bus *pbus, u32 *addr,
+                           struct of_bus *pbus, fdt32_t *addr,
                            int na, int ns, int pna, const char *rprop)
 {
-       const u32 *ranges;
+       const fdt32_t *ranges;
        int rlen;
        int rone;
        u64 offset = OF_BAD_ADDR;
@@ -1030,7 +1025,7 @@ static int of_translate_one(void * blob, int parent, struct of_bus *bus,
         * to translate addresses that aren't supposed to be translated in
         * the first place. --BenH.
         */
-       ranges = (u32 *)fdt_getprop(blob, parent, rprop, &rlen);
+       ranges = fdt_getprop(blob, parent, rprop, &rlen);
        if (ranges == NULL || rlen == 0) {
                offset = of_read_number(addr, na);
                memset(addr, 0, pna * 4);
@@ -1072,12 +1067,12 @@ static int of_translate_one(void * blob, int parent, struct of_bus *bus,
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
  */
-u64 __of_translate_address(void *blob, int node_offset, const u32 *in_addr,
-                          const char *rprop)
+static u64 __of_translate_address(void *blob, int node_offset, const fdt32_t *in_addr,
+                                 const char *rprop)
 {
        int parent;
        struct of_bus *bus, *pbus;
-       u32 addr[OF_MAX_ADDR_CELLS];
+       fdt32_t addr[OF_MAX_ADDR_CELLS];
        int na, ns, pna, pns;
        u64 result = OF_BAD_ADDR;
 
@@ -1090,7 +1085,7 @@ u64 __of_translate_address(void *blob, int node_offset, const u32 *in_addr,
                goto bail;
        bus = &of_busses[0];
 
-       /* Cound address cells & copy address locally */
+       /* Count address cells & copy address locally */
        bus->count_cells(blob, parent, &na, &ns);
        if (!OF_CHECK_COUNTS(na, ns)) {
                printf("%s: Bad cell count for %s\n", __FUNCTION__,
@@ -1145,7 +1140,7 @@ u64 __of_translate_address(void *blob, int node_offset, const u32 *in_addr,
        return result;
 }
 
-u64 fdt_translate_address(void *blob, int node_offset, const u32 *in_addr)
+u64 fdt_translate_address(void *blob, int node_offset, const fdt32_t *in_addr)
 {
        return __of_translate_address(blob, node_offset, in_addr, "ranges");
 }
@@ -1164,7 +1159,7 @@ int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
 {
        int len, off = fdt_node_offset_by_compatible(blob, -1, compat);
        while (off != -FDT_ERR_NOTFOUND) {
-               u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", &len);
+               const fdt32_t *reg = fdt_getprop(blob, off, "reg", &len);
                if (reg) {
                        if (compat_off == fdt_translate_address(blob, off, reg))
                                return off;
@@ -1182,14 +1177,11 @@ int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
  */
 int fdt_alloc_phandle(void *blob)
 {
-       int offset, len, phandle = 0;
-       const u32 *val;
+       int offset, phandle = 0;
 
        for (offset = fdt_next_node(blob, -1, NULL); offset >= 0;
             offset = fdt_next_node(blob, offset, NULL)) {
-               val = fdt_getprop(blob, offset, "linux,phandle", &len);
-               if (val)
-                       phandle = max(*val, phandle);
+               phandle = max(phandle, fdt_get_phandle(blob, offset));
        }
 
        return phandle + 1;
@@ -1241,21 +1233,86 @@ int fdt_set_phandle(void *fdt, int nodeoffset, uint32_t phandle)
  * @fdt: ptr to device tree
  * @nodeoffset: node to update
  */
-int fdt_create_phandle(void *fdt, int nodeoffset)
+unsigned int fdt_create_phandle(void *fdt, int nodeoffset)
 {
        /* see if there is a phandle already */
        int phandle = fdt_get_phandle(fdt, nodeoffset);
 
        /* if we got 0, means no phandle so create one */
        if (phandle == 0) {
+               int ret;
+
                phandle = fdt_alloc_phandle(fdt);
-               fdt_set_phandle(fdt, nodeoffset, phandle);
+               ret = fdt_set_phandle(fdt, nodeoffset, phandle);
+               if (ret < 0) {
+                       printf("Can't set phandle %u: %s\n", phandle,
+                              fdt_strerror(ret));
+                       return 0;
+               }
        }
 
        return phandle;
 }
 
-#if defined(CONFIG_VIDEO)
+/*
+ * fdt_set_node_status: Set status for the given node
+ *
+ * @fdt: ptr to device tree
+ * @nodeoffset: node to update
+ * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED,
+ *         FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE
+ * @error_code: optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE
+ */
+int fdt_set_node_status(void *fdt, int nodeoffset,
+                       enum fdt_status status, unsigned int error_code)
+{
+       char buf[16];
+       int ret = 0;
+
+       if (nodeoffset < 0)
+               return nodeoffset;
+
+       switch (status) {
+       case FDT_STATUS_OKAY:
+               ret = fdt_setprop_string(fdt, nodeoffset, "status", "okay");
+               break;
+       case FDT_STATUS_DISABLED:
+               ret = fdt_setprop_string(fdt, nodeoffset, "status", "disabled");
+               break;
+       case FDT_STATUS_FAIL:
+               ret = fdt_setprop_string(fdt, nodeoffset, "status", "fail");
+               break;
+       case FDT_STATUS_FAIL_ERROR_CODE:
+               sprintf(buf, "fail-%d", error_code);
+               ret = fdt_setprop_string(fdt, nodeoffset, "status", buf);
+               break;
+       default:
+               printf("Invalid fdt status: %x\n", status);
+               ret = -1;
+               break;
+       }
+
+       return ret;
+}
+
+/*
+ * fdt_set_status_by_alias: Set status for the given node given an alias
+ *
+ * @fdt: ptr to device tree
+ * @alias: alias of node to update
+ * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED,
+ *         FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE
+ * @error_code: optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE
+ */
+int fdt_set_status_by_alias(void *fdt, const char* alias,
+                           enum fdt_status status, unsigned int error_code)
+{
+       int offset = fdt_path_offset(fdt, alias);
+
+       return fdt_set_node_status(fdt, offset, status, error_code);
+}
+
+#if defined(CONFIG_VIDEO) || defined(CONFIG_LCD)
 int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf)
 {
        int noff;
@@ -1296,7 +1353,7 @@ err_size:
 int fdt_verify_alias_address(void *fdt, int anode, const char *alias, u64 addr)
 {
        const char *path;
-       const u32 *reg;
+       const fdt32_t *reg;
        int node, len;
        u64 dt_addr;
 
@@ -1338,11 +1395,11 @@ u64 fdt_get_base_address(void *fdt, int node)
 {
        int size;
        u32 naddr;
-       const u32 *prop;
+       const fdt32_t *prop;
 
        prop = fdt_getprop(fdt, node, "#address-cells", &size);
        if (prop && size == 4)
-               naddr = *prop;
+               naddr = be32_to_cpup(prop);
        else
                naddr = 2;