]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Merge git://git.denx.de/u-boot-fdt
authorTom Rini <trini@ti.com>
Tue, 25 Nov 2014 16:08:52 +0000 (11:08 -0500)
committerTom Rini <trini@ti.com>
Wed, 26 Nov 2014 16:21:14 +0000 (11:21 -0500)
1  2 
README
board/compulab/cm_fx6/cm_fx6.c
board/tqc/tqma6/tqma6.c
common/fdt_support.c
include/fdtdec.h
lib/fdtdec.c

diff --combined README
index e7cd1bcb436dff45feb2be387eaee30323cc15ae,bf3ec67b8eac68b13fd6f6977e7b816651ae07f5..66770b648539701fe0fdd8b36b1076359557ddd3
--- 1/README
--- 2/README
+++ b/README
@@@ -623,120 -623,6 +623,120 @@@ The following options need to be config
                exists, unlike the similar options in the Linux kernel. Do not
                set these options unless they apply!
  
 +- Driver Model
 +              Driver model is a new framework for devices in U-Boot
 +              introduced in early 2014. U-Boot is being progressively
 +              moved over to this. It offers a consistent device structure,
 +              supports grouping devices into classes and has built-in
 +              handling of platform data and device tree.
 +
 +              To enable transition to driver model in a relatively
 +              painful fashion, each subsystem can be independently
 +              switched between the legacy/ad-hoc approach and the new
 +              driver model using the options below. Also, many uclass
 +              interfaces include compatibility features which may be
 +              removed once the conversion of that subsystem is complete.
 +              As a result, the API provided by the subsystem may in fact
 +              not change with driver model.
 +
 +              See doc/driver-model/README.txt for more information.
 +
 +              CONFIG_DM
 +
 +              Enable driver model. This brings in the core support,
 +              including scanning of platform data on start-up. If
 +              CONFIG_OF_CONTROL is enabled, the device tree will be
 +              scanned also when available.
 +
 +              CONFIG_CMD_DM
 +
 +              Enable driver model test commands. These allow you to print
 +              out the driver model tree and the uclasses.
 +
 +              CONFIG_DM_DEMO
 +
 +              Enable some demo devices and the 'demo' command. These are
 +              really only useful for playing around while trying to
 +              understand driver model in sandbox.
 +
 +              CONFIG_SPL_DM
 +
 +              Enable driver model in SPL. You will need to provide a
 +              suitable malloc() implementation. If you are not using the
 +              full malloc() enabled by CONFIG_SYS_SPL_MALLOC_START,
 +              consider using CONFIG_SYS_MALLOC_SIMPLE. In that case you
 +              must provide CONFIG_SYS_MALLOC_F_LEN to set the size.
 +              In most cases driver model will only allocate a few uclasses
 +              and devices in SPL, so 1KB should be enable. See
 +              CONFIG_SYS_MALLOC_F_LEN for more details on how to enable
 +              it.
 +
 +              CONFIG_DM_SERIAL
 +
 +              Enable driver model for serial. This replaces
 +              drivers/serial/serial.c with the serial uclass, which
 +              implements serial_putc() etc. The uclass interface is
 +              defined in include/serial.h.
 +
 +              CONFIG_DM_GPIO
 +
 +              Enable driver model for GPIO access. The standard GPIO
 +              interface (gpio_get_value(), etc.) is then implemented by
 +              the GPIO uclass. Drivers provide methods to query the
 +              particular GPIOs that they provide. The uclass interface
 +              is defined in include/asm-generic/gpio.h.
 +
 +              CONFIG_DM_SPI
 +
 +              Enable driver model for SPI. The SPI slave interface
 +              (spi_setup_slave(), spi_xfer(), etc.) is then implemented by
 +              the SPI uclass. Drivers provide methods to access the SPI
 +              buses that they control. The uclass interface is defined in
 +              include/spi.h. The existing spi_slave structure is attached
 +              as 'parent data' to every slave on each bus. Slaves
 +              typically use driver-private data instead of extending the
 +              spi_slave structure.
 +
 +              CONFIG_DM_SPI_FLASH
 +
 +              Enable driver model for SPI flash. This SPI flash interface
 +              (spi_flash_probe(), spi_flash_write(), etc.) is then
 +              implemented by the SPI flash uclass. There is one standard
 +              SPI flash driver which knows how to probe most chips
 +              supported by U-Boot. The uclass interface is defined in
 +              include/spi_flash.h, but is currently fully compatible
 +              with the old interface to avoid confusion and duplication
 +              during the transition parent. SPI and SPI flash must be
 +              enabled together (it is not possible to use driver model
 +              for one and not the other).
 +
 +              CONFIG_DM_CROS_EC
 +
 +              Enable driver model for the Chrome OS EC interface. This
 +              allows the cros_ec SPI driver to operate with CONFIG_DM_SPI
 +              but otherwise makes few changes. Since cros_ec also supports
 +              I2C and LPC (which don't support driver model yet), a full
 +              conversion is not yet possible.
 +
 +
 +              ** Code size options: The following options are enabled by
 +              default except in SPL. Enable them explicitly to get these
 +              features in SPL.
 +
 +              CONFIG_DM_WARN
 +
 +              Enable the dm_warn() function. This can use up quite a bit
 +              of space for its strings.
 +
 +              CONFIG_DM_STDIO
 +
 +              Enable registering a serial device with the stdio library.
 +
 +              CONFIG_DM_DEVICE_REMOVE
 +
 +              Enable removing of devices.
 +
 +
  - Linux Kernel Interface:
                CONFIG_CLOCKS_IN_MHZ
  
                Board code has addition modification that it wants to make
                to the flat device tree before handing it off to the kernel
  
+               CONFIG_OF_SYSTEM_SETUP
+               Other code has addition modification that it wants to make
+               to the flat device tree before handing it off to the kernel.
+               This causes ft_system_setup() to be called before booting
+               the kernel.
                CONFIG_OF_BOOT_CPU
  
                This define fills in the correct boot CPU in the boot
                CONFIG_CMD_EXT4         * ext4 command support
                CONFIG_CMD_FS_GENERIC   * filesystem commands (e.g. load, ls)
                                          that work for multiple fs types
 +              CONFIG_CMD_FS_UUID      * Look up a filesystem UUID
                CONFIG_CMD_SAVEENV        saveenv
                CONFIG_CMD_FDC          * Floppy Disk Support
                CONFIG_CMD_FAT          * FAT command support
@@@ -2949,6 -2841,18 +2956,6 @@@ CBFS (Coreboot Filesystem) suppor
  
                Enable auto completion of commands using TAB.
  
 -              CONFIG_SYS_HUSH_PARSER
 -
 -              Define this variable to enable the "hush" shell (from
 -              Busybox) as command line interpreter, thus enabling
 -              powerful command line syntax like
 -              if...then...else...fi conditionals or `&&' and '||'
 -              constructs ("shell scripts").
 -
 -              If undefined, you get the old, much simpler behaviour
 -              with a somewhat smaller memory footprint.
 -
 -
                CONFIG_SYS_PROMPT_HUSH_PS2
  
                This defines the secondary prompt string, which is
@@@ -3510,7 -3414,7 +3517,7 @@@ FIT uImage format
                to 128 or 256, although it does not have to be power of 2).
  
                default: 4096
-               
                CONFIG_MTD_UBI_BEB_LIMIT
                This option specifies the maximum bad physical eraseblocks UBI
                expects on the MTD device (per 1024 eraseblocks). If the
@@@ -3984,11 -3888,6 +3991,11 @@@ Configuration Settings
                Pre-relocation malloc() is only supported on ARM and sandbox
                at present but is fairly easy to enable for other archs.
  
 +- CONFIG_SYS_MALLOC_SIMPLE
 +              Provides a simple and small malloc() and calloc() for those
 +              boards which do not use the full malloc in SPL (which is
 +              enabled with CONFIG_SYS_SPL_MALLOC_START).
 +
  - CONFIG_SYS_BOOTM_LEN:
                Normally compressed uImages are limited to an
                uncompressed size of 8 MBytes. If this is not enough,
index 09e285b74db81b34e4e32790cd06887f786fb7dd,180e7779d7c3aaa6b40050e18d4971094508836b..84e36439fa18ddf10040043f63abd2fba478562f
@@@ -98,6 -98,9 +98,6 @@@ int sata_initialize(void
        /* Make sure this gpio has logical 0 value */
        gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0);
        udelay(100);
 -
 -      cm_fx6_sata_power(0);
 -      mdelay(250);
        cm_fx6_sata_power(1);
  
        for (i = 0; i < CM_FX6_SATA_INIT_RETRIES; i++) {
  
        return err;
  }
 +
 +int sata_stop(void)
 +{
 +      __sata_stop();
 +      cm_fx6_sata_power(0);
 +      mdelay(250);
 +
 +      return 0;
 +}
  #else
  static int cm_fx6_setup_issd(void) { return 0; }
  #endif
@@@ -458,7 -452,7 +458,7 @@@ int cm_fx6_setup_ecspi(void) { return 0
  #endif
  
  #ifdef CONFIG_OF_BOARD_SETUP
void ft_board_setup(void *blob, bd_t *bd)
int ft_board_setup(void *blob, bd_t *bd)
  {
        uint8_t enetaddr[6];
  
                fdt_find_and_setprop(blob, "/fec", "local-mac-address",
                                     enetaddr, 6, 1);
        }
+       return 0;
  }
  #endif
  
diff --combined board/tqc/tqma6/tqma6.c
index e480d57e7dbe9c7f54929743f14e7d89003ef1f7,7b7abc64662ab8bd9fd874ea7b757807e61fe694..c9e163e7d5e8e492a5a4e3e04d948031f6808e3e
@@@ -17,7 -17,6 +17,7 @@@
  #include <asm/gpio.h>
  #include <asm/io.h>
  #include <asm/imx-common/mxc_i2c.h>
 +#include <asm/imx-common/spi.h>
  #include <common.h>
  #include <fsl_esdhc.h>
  #include <libfdt.h>
@@@ -51,7 -50,7 +51,7 @@@ DECLARE_GLOBAL_DATA_PTR
  
  int dram_init(void)
  {
 -      gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
 +      gd->ram_size = imx_ddr_size();
  
        return 0;
  }
@@@ -181,14 -180,8 +181,14 @@@ static struct i2c_pads_info tqma6_i2c3_
  
  static void tqma6_setup_i2c(void)
  {
 -      /* use logical index for bus, e.g. I2C1 -> 0 */
 -      setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &tqma6_i2c3_pads);
 +      int ret;
 +      /*
 +       * use logical index for bus, e.g. I2C1 -> 0
 +       * warn on error
 +       */
 +      ret = setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &tqma6_i2c3_pads);
 +      if (ret)
 +              printf("setup I2C3 failed: %d\n", ret);
  }
  
  int board_early_init_f(void)
@@@ -266,12 -259,14 +266,14 @@@ int checkboard(void
   * Device Tree Support
   */
  #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
void ft_board_setup(void *blob, bd_t *bd)
int ft_board_setup(void *blob, bd_t *bd)
  {
        /* bring in eMMC dsr settings */
        do_fixup_by_path_u32(blob,
                             "/soc/aips-bus@02100000/usdhc@02198000",
                             "dsr", tqma6_emmc_dsr, 2);
        tqma6_bb_ft_board_setup(blob, bd);
+       return 0;
  }
  #endif /* defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) */
diff --combined common/fdt_support.c
index 2d3c3870b19a3d42f0edb0e4f1f9c88272072b1e,a405cb8039b0a753afe0a8747f8257edd3f5f9c2..ce32fe73aff2c7d42d683ee71bf4f4eedfcf6a81
  #include <fdt_support.h>
  #include <exports.h>
  
- /*
-  * Get cells len in bytes
-  *     if #NNNN-cells property is 2 then len is 8
-  *     otherwise len is 4
-  */
- static int get_cells_len(const void *fdt, const char *nr_cells_name)
- {
-       const fdt32_t *cell;
-       cell = fdt_getprop(fdt, 0, nr_cells_name, NULL);
-       if (cell && fdt32_to_cpu(*cell) == 2)
-               return 8;
-       return 4;
- }
  /**
   * fdt_getprop_u32_default_node - Return a node's property or a default
   *
@@@ -113,7 -97,8 +97,8 @@@ int fdt_find_and_setprop(void *fdt, con
  }
  
  /**
-  * fdt_find_or_add_subnode - find or possibly add a subnode of a given node
+  * fdt_find_or_add_subnode() - find or possibly add a subnode of a given node
+  *
   * @fdt: pointer to the device tree blob
   * @parentoffset: structure block offset of a node
   * @name: name of the subnode to locate
   * fdt_subnode_offset() finds a subnode of the node with a given name.
   * If the subnode does not exist, it will be created.
   */
- static int fdt_find_or_add_subnode(void *fdt, int parentoffset,
-                                  const char *name)
+ int fdt_find_or_add_subnode(void *fdt, int parentoffset, const char *name)
  {
        int offset;
  
@@@ -246,7 -230,7 +230,7 @@@ int fdt_initrd(void *fdt, ulong initrd_
                return err;
        }
  
-       is_u64 = (get_cells_len(fdt, "#address-cells") == 8);
+       is_u64 = (fdt_address_cells(fdt, 0) == 2);
  
        err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-start",
                              (uint64_t)initrd_start, is_u64);
@@@ -382,22 -366,22 +366,22 @@@ void do_fixup_by_compat_u32(void *fdt, 
  /*
   * 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)
+ static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size,
+                       int n)
  {
        int i;
-       int address_len = get_cells_len(fdt, "#address-cells");
-       int size_len = get_cells_len(fdt, "#size-cells");
+       int address_len = fdt_address_cells(fdt, 0);
+       int size_len = fdt_size_cells(fdt, 0);
        char *p = buf;
  
        for (i = 0; i < n; i++) {
-               if (address_len == 8)
+               if (address_len == 2)
                        *(fdt64_t *)p = cpu_to_fdt64(address[i]);
                else
                        *(fdt32_t *)p = cpu_to_fdt32(address[i]);
                p += address_len;
  
-               if (size_len == 8)
+               if (size_len == 2)
                        *(fdt64_t *)p = cpu_to_fdt64(size[i]);
                else
                        *(fdt32_t *)p = cpu_to_fdt32(size[i]);
@@@ -968,13 -952,8 +952,8 @@@ void of_bus_default_count_cells(void *b
  {
        const fdt32_t *prop;
  
-       if (addrc) {
-               prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL);
-               if (prop)
-                       *addrc = be32_to_cpup(prop);
-               else
-                       *addrc = 2;
-       }
+       if (addrc)
+               *addrc = fdt_address_cells(blob, parentoffset);
  
        if (sizec) {
                prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL);
@@@ -1199,8 -1178,7 +1178,8 @@@ int fdt_node_offset_by_compat_reg(void 
   */
  int fdt_alloc_phandle(void *blob)
  {
 -      int offset, phandle = 0;
 +      int offset;
 +      uint32_t phandle = 0;
  
        for (offset = fdt_next_node(blob, -1, NULL); offset >= 0;
             offset = fdt_next_node(blob, offset, NULL)) {
@@@ -1420,11 -1398,7 +1399,7 @@@ u64 fdt_get_base_address(void *fdt, in
        u32 naddr;
        const fdt32_t *prop;
  
-       prop = fdt_getprop(fdt, node, "#address-cells", &size);
-       if (prop && size == 4)
-               naddr = be32_to_cpup(prop);
-       else
-               naddr = 2;
+       naddr = fdt_address_cells(fdt, node);
  
        prop = fdt_getprop(fdt, node, "ranges", &size);
  
diff --combined include/fdtdec.h
index abfd678424b5521d7cf941f1542b4dacef163cbd,a7655dc19391378864485af4124890f1e94eb9c2..3da9fab95ce8c10280a363e0590ec9e8135d5d3d
@@@ -118,8 -118,6 +118,8 @@@ enum fdt_compat_id 
        COMPAT_SAMSUNG_EXYNOS_SYSMMU,   /* Exynos sysmmu */
        COMPAT_PARADE_PS8625,           /* Parade PS8622 EDP->LVDS bridge */
        COMPAT_INTEL_LPC,               /* Intel Low Pin Count I/F */
 +      COMPAT_INTEL_MICROCODE,         /* Intel microcode update */
 +      COMPAT_MEMORY_SPD,              /* Memory SPD information */
  
        COMPAT_COUNT,
  };
@@@ -446,22 -444,6 +446,22 @@@ int fdtdec_lookup_phandle(const void *b
  int fdtdec_get_int_array(const void *blob, int node, const char *prop_name,
                u32 *array, int count);
  
 +/**
 + * Look up a property in a node and return its contents in an integer
 + * array of given length. The property must exist but may have less data that
 + * expected (4*count bytes). It may have more, but this will be ignored.
 + *
 + * @param blob                FDT blob
 + * @param node                node to examine
 + * @param prop_name   name of property to find
 + * @param array               array to fill with data
 + * @param count               number of array elements
 + * @return number of array elements if ok, or -FDT_ERR_NOTFOUND if the
 + *            property is not found
 + */
 +int fdtdec_get_int_array_count(const void *blob, int node,
 +                             const char *prop_name, u32 *array, int count);
 +
  /**
   * Look up a property in a node and return a pointer to its contents as a
   * unsigned int array of given length. The property must have at least enough
@@@ -613,17 -595,33 +613,33 @@@ const u8 *fdtdec_locate_byte_array(cons
   * @param blob                FDT blob
   * @param node                node to examine
   * @param prop_name   name of property to find
-  * @param ptrp                returns pointer to region, or NULL if no address
-  * @param size                returns size of region
-  * @return 0 if ok, -1 on error (propery not found)
+  * @param basep               Returns base address of region
+  * @param size                Returns size of region
+  * @return 0 if ok, -1 on error (property not found)
   */
- int fdtdec_decode_region(const void *blob, int node,
-               const char *prop_name, void **ptrp, size_t *size);
+ int fdtdec_decode_region(const void *blob, int node, const char *prop_name,
+                        fdt_addr_t *basep, fdt_size_t *sizep);
+ enum fmap_compress_t {
+       FMAP_COMPRESS_NONE,
+       FMAP_COMPRESS_LZO,
+ };
+ enum fmap_hash_t {
+       FMAP_HASH_NONE,
+       FMAP_HASH_SHA1,
+       FMAP_HASH_SHA256,
+ };
  
  /* A flash map entry, containing an offset and length */
  struct fmap_entry {
        uint32_t offset;
        uint32_t length;
+       uint32_t used;                  /* Number of bytes used in region */
+       enum fmap_compress_t compress_algo;     /* Compression type */
+       enum fmap_hash_t hash_algo;             /* Hash algorithm */
+       const uint8_t *hash;                    /* Hash value */
+       int hash_size;                          /* Hash size */
  };
  
  /**
@@@ -679,4 -677,31 +695,31 @@@ int fdt_get_named_resource(const void *
   */
  int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf);
  
+ /**
+  * Decode a named region within a memory bank of a given type.
+  *
+  * This function handles selection of a memory region. The region is
+  * specified as an offset/size within a particular type of memory.
+  *
+  * The properties used are:
+  *
+  *    <mem_type>-memory<suffix> for the name of the memory bank
+  *    <mem_type>-offset<suffix> for the offset in that bank
+  *
+  * The property value must have an offset and a size. The function checks
+  * that the region is entirely within the memory bank.5
+  *
+  * @param blob                FDT blob
+  * @param node                Node containing the properties (-1 for /config)
+  * @param mem_type    Type of memory to use, which is a name, such as
+  *                    "u-boot" or "kernel".
+  * @param suffix      String to append to the memory/offset
+  *                    property names
+  * @param basep               Returns base of region
+  * @param sizep               Returns size of region
+  * @return 0 if OK, -ive on error
+  */
+ int fdtdec_decode_memory_region(const void *blob, int node,
+                               const char *mem_type, const char *suffix,
+                               fdt_addr_t *basep, fdt_size_t *sizep);
  #endif
diff --combined lib/fdtdec.c
index e8775df5d00b135972799040d03cc76932af759d,9c332ad903ee63608f7ffd97e97bdb2240f97b44..7c7e673aeb79e975f0a725967eb298da4212d99d
@@@ -73,8 -73,6 +73,8 @@@ static const char * const compat_names[
        COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
        COMPAT(PARADE_PS8625, "parade,ps8625"),
        COMPAT(COMPAT_INTEL_LPC, "intel,lpc"),
 +      COMPAT(INTEL_MICROCODE, "intel,microcode"),
 +      COMPAT(MEMORY_SPD, "memory-spd"),
  };
  
  const char *fdtdec_get_compatible(enum fdt_compat_id id)
@@@ -357,9 -355,9 +357,9 @@@ int fdtdec_get_alias_seq(const void *bl
                slash = strrchr(prop, '/');
                if (strcmp(slash + 1, find_name))
                        continue;
 -              for (p = name; *p; p++) {
 -                      if (isdigit(*p)) {
 -                              *seqp = simple_strtoul(p, NULL, 10);
 +              for (p = name + strlen(name) - 1; p > name; p--) {
 +                      if (!isdigit(*p)) {
 +                              *seqp = simple_strtoul(p + 1, NULL, 10);
                                debug("Found seq %d\n", *seqp);
                                return 0;
                        }
@@@ -487,26 -485,6 +487,26 @@@ int fdtdec_get_int_array(const void *bl
        return err;
  }
  
 +int fdtdec_get_int_array_count(const void *blob, int node,
 +                             const char *prop_name, u32 *array, int count)
 +{
 +      const u32 *cell;
 +      int len, elems;
 +      int i;
 +
 +      debug("%s: %s\n", __func__, prop_name);
 +      cell = fdt_getprop(blob, node, prop_name, &len);
 +      if (!cell)
 +              return -FDT_ERR_NOTFOUND;
 +      elems = len / sizeof(u32);
 +      if (count > elems)
 +              count = elems;
 +      for (i = 0; i < count; i++)
 +              array[i] = fdt32_to_cpu(cell[i]);
 +
 +      return count;
 +}
 +
  const u32 *fdtdec_locate_array(const void *blob, int node,
                               const char *prop_name, int count)
  {
@@@ -691,20 -669,25 +691,25 @@@ char *fdtdec_get_config_string(const vo
        return (char *)nodep;
  }
  
- int fdtdec_decode_region(const void *blob, int node,
-               const char *prop_name, void **ptrp, size_t *size)
+ int fdtdec_decode_region(const void *blob, int node, const char *prop_name,
+                        fdt_addr_t *basep, fdt_size_t *sizep)
  {
        const fdt_addr_t *cell;
        int len;
  
-       debug("%s: %s\n", __func__, prop_name);
+       debug("%s: %s: %s\n", __func__, fdt_get_name(blob, node, NULL),
+             prop_name);
        cell = fdt_getprop(blob, node, prop_name, &len);
-       if (!cell || (len != sizeof(fdt_addr_t) * 2))
+       if (!cell || (len < sizeof(fdt_addr_t) * 2)) {
+               debug("cell=%p, len=%d\n", cell, len);
                return -1;
+       }
+       *basep = fdt_addr_to_cpu(*cell);
+       *sizep = fdt_size_to_cpu(cell[1]);
+       debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep,
+             (ulong)*sizep);
  
-       *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;
  }
  
  int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
                           struct fmap_entry *entry)
  {
+       const char *prop;
        u32 reg[2];
  
        if (fdtdec_get_int_array(blob, node, "reg", reg, 2)) {
        }
        entry->offset = reg[0];
        entry->length = reg[1];
+       entry->used = fdtdec_get_int(blob, node, "used", entry->length);
+       prop = fdt_getprop(blob, node, "compress", NULL);
+       entry->compress_algo = prop && !strcmp(prop, "lzo") ?
+               FMAP_COMPRESS_LZO : FMAP_COMPRESS_NONE;
+       prop = fdt_getprop(blob, node, "hash", &entry->hash_size);
+       entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE;
+       entry->hash = (uint8_t *)prop;
  
        return 0;
  }
@@@ -802,4 -793,65 +815,65 @@@ int fdtdec_pci_get_bdf(const void *fdt
  
        return 0;
  }
+ int fdtdec_decode_memory_region(const void *blob, int config_node,
+                               const char *mem_type, const char *suffix,
+                               fdt_addr_t *basep, fdt_size_t *sizep)
+ {
+       char prop_name[50];
+       const char *mem;
+       fdt_size_t size, offset_size;
+       fdt_addr_t base, offset;
+       int node;
+       if (config_node == -1) {
+               config_node = fdt_path_offset(blob, "/config");
+               if (config_node < 0) {
+                       debug("%s: Cannot find /config node\n", __func__);
+                       return -ENOENT;
+               }
+       }
+       if (!suffix)
+               suffix = "";
+       snprintf(prop_name, sizeof(prop_name), "%s-memory%s", mem_type,
+                suffix);
+       mem = fdt_getprop(blob, config_node, prop_name, NULL);
+       if (!mem) {
+               debug("%s: No memory type for '%s', using /memory\n", __func__,
+                     prop_name);
+               mem = "/memory";
+       }
+       node = fdt_path_offset(blob, mem);
+       if (node < 0) {
+               debug("%s: Failed to find node '%s': %s\n", __func__, mem,
+                     fdt_strerror(node));
+               return -ENOENT;
+       }
+       /*
+        * Not strictly correct - the memory may have multiple banks. We just
+        * use the first
+        */
+       if (fdtdec_decode_region(blob, node, "reg", &base, &size)) {
+               debug("%s: Failed to decode memory region %s\n", __func__,
+                     mem);
+               return -EINVAL;
+       }
+       snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type,
+                suffix);
+       if (fdtdec_decode_region(blob, config_node, prop_name, &offset,
+                                &offset_size)) {
+               debug("%s: Failed to decode memory region '%s'\n", __func__,
+                     prop_name);
+               return -EINVAL;
+       }
+       *basep = base + offset;
+       *sizep = offset_size;
+       return 0;
+ }
  #endif