]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - lib/fdtdec.c
sandbox: Correct data sizes and printf() strings in fdtdec.c
[karo-tx-uboot.git] / lib / fdtdec.c
index 23e020572122cbd1203b821ec02002c24d6918af..207314fa72fb34f643c0d9424916c9dbfefba4c9 100644 (file)
@@ -1,22 +1,6 @@
 /*
  * Copyright (c) 2011 The Chromium OS Authors.
 /*
  * Copyright (c) 2011 The Chromium OS Authors.
- * 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>
  */
 
 #include <common.h>
@@ -37,6 +21,9 @@ DECLARE_GLOBAL_DATA_PTR;
 static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(UNKNOWN, "<none>"),
        COMPAT(NVIDIA_TEGRA20_USB, "nvidia,tegra20-ehci"),
 static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(UNKNOWN, "<none>"),
        COMPAT(NVIDIA_TEGRA20_USB, "nvidia,tegra20-ehci"),
+       COMPAT(NVIDIA_TEGRA30_USB, "nvidia,tegra30-ehci"),
+       COMPAT(NVIDIA_TEGRA114_USB, "nvidia,tegra114-ehci"),
+       COMPAT(NVIDIA_TEGRA114_I2C, "nvidia,tegra114-i2c"),
        COMPAT(NVIDIA_TEGRA20_I2C, "nvidia,tegra20-i2c"),
        COMPAT(NVIDIA_TEGRA20_DVC, "nvidia,tegra20-i2c-dvc"),
        COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"),
        COMPAT(NVIDIA_TEGRA20_I2C, "nvidia,tegra20-i2c"),
        COMPAT(NVIDIA_TEGRA20_DVC, "nvidia,tegra20-i2c-dvc"),
        COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"),
@@ -45,6 +32,34 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
        COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
        COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
        COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
        COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
        COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
+       COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"),
+       COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"),
+       COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
+       COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
+       COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"),
+       COMPAT(SMSC_LAN9215, "smsc,lan9215"),
+       COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"),
+       COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"),
+       COMPAT(SAMSUNG_EXYNOS5_SOUND, "samsung,exynos-sound"),
+       COMPAT(WOLFSON_WM8994_CODEC, "wolfson,wm8994-codec"),
+       COMPAT(SAMSUNG_EXYNOS_SPI, "samsung,exynos-spi"),
+       COMPAT(GOOGLE_CROS_EC, "google,cros-ec"),
+       COMPAT(GOOGLE_CROS_EC_KEYB, "google,cros-ec-keyb"),
+       COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
+       COMPAT(SAMSUNG_EXYNOS5_XHCI, "samsung,exynos5250-xhci"),
+       COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
+       COMPAT(SAMSUNG_EXYNOS5_USB3_PHY, "samsung,exynos5250-usb3-phy"),
+       COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),
+       COMPAT(SAMSUNG_EXYNOS_FIMD, "samsung,exynos-fimd"),
+       COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"),
+       COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"),
+       COMPAT(SAMSUNG_EXYNOS_SERIAL, "samsung,exynos4210-uart"),
+       COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
+       COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
+       COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"),
+       COMPAT(INFINEON_SLB9635_TPM, "infineon,slb9635-tpm"),
+       COMPAT(INFINEON_SLB9645_TPM, "infineon,slb9645-tpm"),
+       COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
@@ -54,47 +69,40 @@ const char *fdtdec_get_compatible(enum fdt_compat_id id)
        return compat_names[id];
 }
 
        return compat_names[id];
 }
 
-/**
- * Look in the FDT for an alias with the given name and return its node.
- *
- * @param blob FDT blob
- * @param name alias name to look up
- * @return node offset if found, or an error code < 0 otherwise
- */
-static int find_alias_node(const void *blob, const char *name)
-{
-       const char *path;
-       int alias_node;
-
-       debug("find_alias_node: %s\n", name);
-       alias_node = fdt_path_offset(blob, "/aliases");
-       if (alias_node < 0)
-               return alias_node;
-       path = fdt_getprop(blob, alias_node, name, NULL);
-       if (!path)
-               return -FDT_ERR_NOTFOUND;
-       return fdt_path_offset(blob, path);
-}
-
-fdt_addr_t fdtdec_get_addr(const void *blob, int node,
-               const char *prop_name)
+fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
+               const char *prop_name, fdt_size_t *sizep)
 {
        const fdt_addr_t *cell;
        int len;
 
        debug("%s: %s: ", __func__, prop_name);
        cell = fdt_getprop(blob, node, prop_name, &len);
 {
        const fdt_addr_t *cell;
        int len;
 
        debug("%s: %s: ", __func__, prop_name);
        cell = fdt_getprop(blob, node, prop_name, &len);
-       if (cell && (len == sizeof(fdt_addr_t) ||
-                       len == sizeof(fdt_addr_t) * 2)) {
+       if (cell && ((!sizep && len == sizeof(fdt_addr_t)) ||
+                    len == sizeof(fdt_addr_t) * 2)) {
                fdt_addr_t addr = fdt_addr_to_cpu(*cell);
                fdt_addr_t addr = fdt_addr_to_cpu(*cell);
-
-               debug("%p\n", (void *)addr);
+               if (sizep) {
+                       const fdt_size_t *size;
+
+                       size = (fdt_size_t *)((char *)cell +
+                                       sizeof(fdt_addr_t));
+                       *sizep = fdt_size_to_cpu(*size);
+                       debug("addr=%08lx, size=%08x\n",
+                             (ulong)addr, *sizep);
+               } else {
+                       debug("%08lx\n", (ulong)addr);
+               }
                return addr;
        }
        debug("(not found)\n");
        return FDT_ADDR_T_NONE;
 }
 
                return addr;
        }
        debug("(not found)\n");
        return FDT_ADDR_T_NONE;
 }
 
+fdt_addr_t fdtdec_get_addr(const void *blob, int node,
+               const char *prop_name)
+{
+       return fdtdec_get_addr_size(blob, node, prop_name, NULL);
+}
+
 s32 fdtdec_get_int(const void *blob, int node, const char *prop_name,
                s32 default_val)
 {
 s32 fdtdec_get_int(const void *blob, int node, const char *prop_name,
                s32 default_val)
 {
@@ -113,6 +121,19 @@ s32 fdtdec_get_int(const void *blob, int node, const char *prop_name,
        return default_val;
 }
 
        return default_val;
 }
 
+uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
+               uint64_t default_val)
+{
+       const uint64_t *cell64;
+       int length;
+
+       cell64 = fdt_getprop(blob, node, prop_name, &length);
+       if (!cell64 || length < sizeof(*cell64))
+               return default_val;
+
+       return fdt64_to_cpu(*cell64);
+}
+
 int fdtdec_get_is_enabled(const void *blob, int node)
 {
        const char *cell;
 int fdtdec_get_is_enabled(const void *blob, int node)
 {
        const char *cell;
@@ -130,7 +151,7 @@ int fdtdec_get_is_enabled(const void *blob, int node)
        return 1;
 }
 
        return 1;
 }
 
-enum fdt_compat_id fd_dec_lookup(const void *blob, int node)
+enum fdt_compat_id fdtdec_lookup(const void *blob, int node)
 {
        enum fdt_compat_id id;
 
 {
        enum fdt_compat_id id;
 
@@ -173,7 +194,7 @@ int fdtdec_next_alias(const void *blob, const char *name,
        /* snprintf() is not available */
        assert(strlen(name) < MAX_STR_LEN);
        sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto);
        /* snprintf() is not available */
        assert(strlen(name) < MAX_STR_LEN);
        sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto);
-       node = find_alias_node(blob, str);
+       node = fdt_path_offset(blob, str);
        if (node < 0)
                return node;
        err = fdt_node_check_compatible(blob, node, compat_names[id]);
        if (node < 0)
                return node;
        err = fdt_node_check_compatible(blob, node, compat_names[id]);
@@ -327,10 +348,11 @@ int fdtdec_check_fdt(void)
  */
 int fdtdec_prepare_fdt(void)
 {
  */
 int fdtdec_prepare_fdt(void)
 {
-       if (((uintptr_t)gd->fdt_blob & 3) || fdt_check_header(gd->fdt_blob)) {
+       if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) ||
+           fdt_check_header(gd->fdt_blob)) {
                printf("No valid FDT found - please append one to U-Boot "
                        "binary, use u-boot-dtb.bin or define "
                printf("No valid FDT found - please append one to U-Boot "
                        "binary, use u-boot-dtb.bin or define "
-                       "CONFIG_OF_EMBED\n");
+                       "CONFIG_OF_EMBED. For sandbox, use -d <file.dtb>\n");
                return -1;
        }
        return 0;
                return -1;
        }
        return 0;
@@ -428,9 +450,8 @@ int fdtdec_get_bool(const void *blob, int node, const char *prop_name)
  * @return number of GPIOs read if ok, -FDT_ERR_BADLAYOUT if max_count would
  * be exceeded, or -FDT_ERR_NOTFOUND if the property is missing.
  */
  * @return number of GPIOs read if ok, -FDT_ERR_BADLAYOUT if max_count would
  * be exceeded, or -FDT_ERR_NOTFOUND if the property is missing.
  */
-static int fdtdec_decode_gpios(const void *blob, int node,
-               const char *prop_name, struct fdt_gpio_state *gpio,
-               int max_count)
+int fdtdec_decode_gpios(const void *blob, int node, const char *prop_name,
+               struct fdt_gpio_state *gpio, int max_count)
 {
        const struct fdt_property *prop;
        const u32 *cell;
 {
        const struct fdt_property *prop;
        const u32 *cell;
@@ -477,6 +498,26 @@ int fdtdec_decode_gpio(const void *blob, int node, const char *prop_name,
        return err == 1 ? 0 : err;
 }
 
        return err == 1 ? 0 : err;
 }
 
+int fdtdec_get_gpio(struct fdt_gpio_state *gpio)
+{
+       int val;
+
+       if (!fdt_gpio_isvalid(gpio))
+               return -1;
+
+       val = gpio_get_value(gpio->gpio);
+       return gpio->flags & FDT_GPIO_ACTIVE_LOW ? val ^ 1 : val;
+}
+
+int fdtdec_set_gpio(struct fdt_gpio_state *gpio, int val)
+{
+       if (!fdt_gpio_isvalid(gpio))
+               return -1;
+
+       val = gpio->flags & FDT_GPIO_ACTIVE_LOW ? val ^ 1 : val;
+       return gpio_set_value(gpio->gpio, val);
+}
+
 int fdtdec_setup_gpio(struct fdt_gpio_state *gpio)
 {
        /*
 int fdtdec_setup_gpio(struct fdt_gpio_state *gpio)
 {
        /*
@@ -514,3 +555,64 @@ const u8 *fdtdec_locate_byte_array(const void *blob, int node,
                return NULL;
        return cell;
 }
                return NULL;
        return cell;
 }
+
+int fdtdec_get_config_int(const void *blob, const char *prop_name,
+               int default_val)
+{
+       int config_node;
+
+       debug("%s: %s\n", __func__, prop_name);
+       config_node = fdt_path_offset(blob, "/config");
+       if (config_node < 0)
+               return default_val;
+       return fdtdec_get_int(blob, config_node, prop_name, default_val);
+}
+
+int fdtdec_get_config_bool(const void *blob, const char *prop_name)
+{
+       int config_node;
+       const void *prop;
+
+       debug("%s: %s\n", __func__, prop_name);
+       config_node = fdt_path_offset(blob, "/config");
+       if (config_node < 0)
+               return 0;
+       prop = fdt_get_property(blob, config_node, prop_name, NULL);
+
+       return prop != NULL;
+}
+
+char *fdtdec_get_config_string(const void *blob, const char *prop_name)
+{
+       const char *nodep;
+       int nodeoffset;
+       int len;
+
+       debug("%s: %s\n", __func__, prop_name);
+       nodeoffset = fdt_path_offset(blob, "/config");
+       if (nodeoffset < 0)
+               return NULL;
+
+       nodep = fdt_getprop(blob, nodeoffset, prop_name, &len);
+       if (!nodep)
+               return NULL;
+
+       return (char *)nodep;
+}
+
+int fdtdec_decode_region(const void *blob, int node,
+               const char *prop_name, void **ptrp, size_t *size)
+{
+       const fdt_addr_t *cell;
+       int len;
+
+       debug("%s: %s\n", __func__, prop_name);
+       cell = fdt_getprop(blob, node, prop_name, &len);
+       if (!cell || (len != sizeof(fdt_addr_t) * 2))
+               return -1;
+
+       *ptrp = map_sysmem(fdt_addr_to_cpu(*cell), *size);
+       *size = fdt_size_to_cpu(cell[1]);
+       debug("%s: size=%zx\n", __func__, *size);
+       return 0;
+}