]> git.sur5r.net Git - u-boot/commitdiff
Merge git://git.denx.de/u-boot-dm
authorTom Rini <trini@konsulko.com>
Thu, 14 Dec 2017 20:46:07 +0000 (15:46 -0500)
committerTom Rini <trini@konsulko.com>
Thu, 14 Dec 2017 20:46:07 +0000 (15:46 -0500)
61 files changed:
Makefile
arch/arm/config.mk
arch/arm/cpu/u-boot-spl.lds
arch/arm/dts/tegra-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/tegra114-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/tegra124-nyan-big-u-boot.dtsi
arch/arm/dts/tegra124-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/tegra20-u-boot.dtsi
arch/arm/dts/tegra210-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/tegra30-u-boot.dtsi [new file with mode: 0644]
arch/arm/mach-tegra/Kconfig
arch/sandbox/dts/sandbox_pmic.dtsi
common/spl/spl.c
common/spl/spl_ram.c
doc/device-tree-bindings/regulator/regulator.txt
drivers/block/blk-uclass.c
drivers/power/pmic/Kconfig
drivers/power/pmic/Makefile
drivers/power/pmic/pmic-uclass.c
drivers/power/pmic/pmic_tps65910_dm.c [new file with mode: 0644]
drivers/power/regulator/Kconfig
drivers/power/regulator/Makefile
drivers/power/regulator/tps65910_regulator.c [new file with mode: 0644]
drivers/sysreset/sysreset-uclass.c
include/binman_sym.h [new file with mode: 0644]
include/power/sandbox_pmic.h
include/power/tps65910_pmic.h [new file with mode: 0644]
include/spl.h
test/dm/regulator.c
tools/binman/README
tools/binman/binman.py
tools/binman/control.py
tools/binman/elf.py [new file with mode: 0644]
tools/binman/elf_test.py [new file with mode: 0644]
tools/binman/etype/entry.py
tools/binman/etype/u_boot_spl.py
tools/binman/etype/u_boot_spl_bss_pad.py
tools/binman/etype/u_boot_spl_dtb.py [new file with mode: 0644]
tools/binman/etype/u_boot_spl_nodtb.py [new file with mode: 0644]
tools/binman/etype/u_boot_with_ucode_ptr.py
tools/binman/ftest.py
tools/binman/image.py
tools/binman/image_test.py [new file with mode: 0644]
tools/binman/test/21_image_pad.dts
tools/binman/test/24_sorted.dts
tools/binman/test/28_pack_4gb_outside.dts
tools/binman/test/29_x86-rom.dts
tools/binman/test/51_u_boot_spl_dtb.dts [new file with mode: 0644]
tools/binman/test/52_u_boot_spl_nodtb.dts [new file with mode: 0644]
tools/binman/test/53_symbols.dts [new file with mode: 0644]
tools/binman/test/Makefile
tools/binman/test/bss_data.c
tools/binman/test/u_boot_binman_syms [new file with mode: 0755]
tools/binman/test/u_boot_binman_syms.c [new file with mode: 0644]
tools/binman/test/u_boot_binman_syms.lds [new file with mode: 0644]
tools/binman/test/u_boot_binman_syms_bad [new file with mode: 0755]
tools/binman/test/u_boot_binman_syms_bad.c [new symlink]
tools/binman/test/u_boot_binman_syms_bad.lds [new file with mode: 0644]
tools/binman/test/u_boot_binman_syms_size [new file with mode: 0755]
tools/binman/test/u_boot_binman_syms_size.c [new file with mode: 0644]
tools/binman/test/u_boot_ucode_ptr.c

index e6d309afe42c5a1fbcb137055aa0a96dfa63bad1..9800d79c8598060269d6dc65fa491b3f6a2c19ec 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1149,6 +1149,11 @@ u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.img u-boot.dtb FORCE
 endif
 
 ifneq ($(CONFIG_TEGRA),)
+ifneq ($(CONFIG_BINMAN),)
+u-boot-dtb-tegra.bin u-boot-tegra.bin u-boot-nodtb-tegra.bin: \
+               spl/u-boot-spl u-boot.bin FORCE
+       $(call if_changed,binman)
+else
 OBJCOPYFLAGS_u-boot-nodtb-tegra.bin = -O binary --pad-to=$(CONFIG_SYS_TEXT_BASE)
 u-boot-nodtb-tegra.bin: spl/u-boot-spl u-boot-nodtb.bin FORCE
        $(call if_changed,pad_cat)
@@ -1159,6 +1164,7 @@ u-boot-tegra.bin: spl/u-boot-spl u-boot.bin FORCE
 
 u-boot-dtb-tegra.bin: u-boot-tegra.bin FORCE
        $(call if_changed,copy)
+endif  # binman
 endif
 
 OBJCOPYFLAGS_u-boot-app.efi := $(OBJCOPYFLAGS_EFI)
index 02f61fcc3cba247fce802f55b9398d1af6496ae4..9c213b897cd5fd7981a6f0103ec605718075c26a 100644 (file)
@@ -136,10 +136,12 @@ endif
 # limit ourselves to the sections we want in the .bin.
 ifdef CONFIG_ARM64
 OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .data \
-               -j .u_boot_list -j .rela.dyn -j .got -j .got.plt
+               -j .u_boot_list -j .rela.dyn -j .got -j .got.plt \
+               -j .binman_sym_table
 else
 OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .hash \
-               -j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn
+               -j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn \
+               -j .binman_sym_table
 endif
 
 # if a dtb section exists we always have to include it
index 068163b73a65986dbd3ac48fc325be1370c2748e..65f7b68861e28b201d47f8565815c283a3279f7b 100644 (file)
@@ -36,6 +36,13 @@ SECTIONS
                KEEP(*(SORT(.u_boot_list*)));
        }
 
+       . = ALIGN(4);
+       .binman_sym_table : {
+               __binman_sym_start = .;
+               KEEP(*(SORT(.binman_sym*)));
+               __binman_sym_end = .;
+       }
+
        . = ALIGN(4);
 
        __image_copy_end = .;
diff --git a/arch/arm/dts/tegra-u-boot.dtsi b/arch/arm/dts/tegra-u-boot.dtsi
new file mode 100644 (file)
index 0000000..cde591c
--- /dev/null
@@ -0,0 +1,40 @@
+#include <config.h>
+
+/ {
+       binman {
+               multiple-images;
+               image1 {
+                       filename = "u-boot-tegra.bin";
+                       pad-byte = <0xff>;
+                       u-boot-spl {
+                       };
+                       u-boot {
+                               pos = <(CONFIG_SYS_TEXT_BASE -
+                                       CONFIG_SPL_TEXT_BASE)>;
+                       };
+               };
+
+               /* Same as image1 - some tools still expect the -dtb suffix */
+               image2 {
+                       filename = "u-boot-dtb-tegra.bin";
+                       pad-byte = <0xff>;
+                       u-boot-spl {
+                       };
+                       u-boot {
+                               pos = <(CONFIG_SYS_TEXT_BASE -
+                                       CONFIG_SPL_TEXT_BASE)>;
+                       };
+               };
+
+               image3 {
+                       filename = "u-boot-nodtb-tegra.bin";
+                       pad-byte = <0xff>;
+                       u-boot-spl {
+                       };
+                       u-boot-nodtb {
+                               pos = <(CONFIG_SYS_TEXT_BASE -
+                                       CONFIG_SPL_TEXT_BASE)>;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/dts/tegra114-u-boot.dtsi b/arch/arm/dts/tegra114-u-boot.dtsi
new file mode 100644 (file)
index 0000000..7c11972
--- /dev/null
@@ -0,0 +1,3 @@
+#include <config.h>
+
+#include "tegra-u-boot.dtsi"
index 65c3851affac2ab4fe58a739e4310cb2b0f1c59a..44e64998c5f0dfdbdbbce8b45500c2f712da2f33 100644 (file)
@@ -5,6 +5,8 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
+#include "tegra-u-boot.dtsi"
+
 / {
        host1x@50000000 {
                u-boot,dm-pre-reloc;
diff --git a/arch/arm/dts/tegra124-u-boot.dtsi b/arch/arm/dts/tegra124-u-boot.dtsi
new file mode 100644 (file)
index 0000000..7c11972
--- /dev/null
@@ -0,0 +1,3 @@
+#include <config.h>
+
+#include "tegra-u-boot.dtsi"
index 9b9835da7e96976c5349b63a5c0907551570e8b1..7c1197255284d9ba8abb53fa14dff6f4f24f173b 100644 (file)
@@ -1,8 +1,3 @@
-/ {
-       host1x@50000000 {
-               u-boot,dm-pre-reloc;
-               dc@54200000 {
-                       u-boot,dm-pre-reloc;
-               };
-       };
-};
+#include <config.h>
+
+#include "tegra-u-boot.dtsi"
diff --git a/arch/arm/dts/tegra210-u-boot.dtsi b/arch/arm/dts/tegra210-u-boot.dtsi
new file mode 100644 (file)
index 0000000..7c11972
--- /dev/null
@@ -0,0 +1,3 @@
+#include <config.h>
+
+#include "tegra-u-boot.dtsi"
diff --git a/arch/arm/dts/tegra30-u-boot.dtsi b/arch/arm/dts/tegra30-u-boot.dtsi
new file mode 100644 (file)
index 0000000..7c11972
--- /dev/null
@@ -0,0 +1,3 @@
+#include <config.h>
+
+#include "tegra-u-boot.dtsi"
index 51e50907d27a25177ebc9e6bbbcd9306e0a346c0..51d143687b064b097a8f936b50649cd1288fed43 100644 (file)
@@ -38,6 +38,7 @@ config TEGRA_COMMON
        select OF_CONTROL
        select VIDCONSOLE_AS_LCD if DM_VIDEO
        select BOARD_EARLY_INIT_F
+       select BINMAN
        imply CRC32_VERIFY
 
 config TEGRA_NO_BPMP
index ce261b930e13abe4f8b7903e22319b09c3a39d2d..acb479939645913f6df90f59a70e5cd8097176b8 100644 (file)
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
        };
+
+       no_match_by_nodename {
+               regulator-name = "buck_SUPPLY_1.5V";
+               regulator-min-microvolt = <1500000>;
+               regulator-max-microvolt = <1500000>;
+       };
 };
index 3bb20c7822f80af362ec1e16bff665d7e4be55a7..76c1963611c49c8e6cb572d8b451f4c392262b00 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <common.h>
+#include <binman_sym.h>
 #include <dm.h>
 #include <spl.h>
 #include <asm/u-boot.h>
@@ -32,6 +33,9 @@ DECLARE_GLOBAL_DATA_PTR;
 
 u32 *boot_params_ptr = NULL;
 
+/* See spl.h for information about this */
+binman_sym_declare(ulong, u_boot_any, pos);
+
 /* Define board data structure */
 static bd_t bdata __attribute__ ((section(".data")));
 
@@ -120,9 +124,17 @@ __weak void spl_board_prepare_for_boot(void)
 
 void spl_set_header_raw_uboot(struct spl_image_info *spl_image)
 {
+       ulong u_boot_pos = binman_sym(ulong, u_boot_any, pos);
+
        spl_image->size = CONFIG_SYS_MONITOR_LEN;
-       spl_image->entry_point = CONFIG_SYS_UBOOT_START;
-       spl_image->load_addr = CONFIG_SYS_TEXT_BASE;
+       if (u_boot_pos != BINMAN_SYM_MISSING) {
+               /* biman does not support separate entry addresses at present */
+               spl_image->entry_point = u_boot_pos;
+               spl_image->load_addr = u_boot_pos;
+       } else {
+               spl_image->entry_point = CONFIG_SYS_UBOOT_START;
+               spl_image->load_addr = CONFIG_SYS_TEXT_BASE;
+       }
        spl_image->os = IH_OS_U_BOOT;
        spl_image->name = "U-Boot";
 }
index b2645a194806c8ad9b43afaa5239316da3d8bc83..fa8c768773afeca085ba3a85d8dce4fefd676bbe 100644 (file)
@@ -11,6 +11,8 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <binman_sym.h>
+#include <mapmem.h>
 #include <spl.h>
 #include <libfdt.h>
 
@@ -48,15 +50,24 @@ static int spl_ram_load_image(struct spl_image_info *spl_image,
                load.read = spl_ram_load_read;
                spl_load_simple_fit(spl_image, &load, 0, header);
        } else {
+               ulong u_boot_pos = binman_sym(ulong, u_boot_any, pos);
+
                debug("Legacy image\n");
                /*
                 * Get the header.  It will point to an address defined by
                 * handoff which will tell where the image located inside
-                * the flash. For now, it will temporary fixed to address
-                * pointed by U-Boot.
+                * the flash.
                 */
-               header = (struct image_header *)
-                       (CONFIG_SYS_TEXT_BASE - sizeof(struct image_header));
+               debug("u_boot_pos = %lx\n", u_boot_pos);
+               if (u_boot_pos == BINMAN_SYM_MISSING) {
+                       /*
+                        * No binman support or no information. For now, fix it
+                        * to the address pointed to by U-Boot.
+                        */
+                       u_boot_pos = CONFIG_SYS_TEXT_BASE -
+                                       sizeof(struct image_header);
+               }
+               header = (struct image_header *)map_sysmem(u_boot_pos, 0);
 
                spl_parse_image_header(spl_image, header);
        }
index 918711eb4d86881f49abbf12f5872e227ad971c1..65b69c427899e582568538a942c2eb71a61b60bd 100644 (file)
@@ -2,7 +2,8 @@ Voltage/Current regulator
 
 Binding:
 The regulator devices don't use the "compatible" property. The binding is done
-by the prefix of regulator node's name. Usually the pmic I/O driver will provide
+by the prefix of regulator node's name, or, if this fails, by the prefix of the
+regulator's "regulator-name" property. Usually the pmic I/O driver will provide
 the array of 'struct pmic_child_info' with the prefixes and compatible drivers.
 The bind is done by calling function: pmic_bind_childs().
 Example drivers:
@@ -15,8 +16,19 @@ For the node name e.g.: "prefix[:alpha:]num { ... }":
 
 Example the prefix "ldo" will pass for: "ldo1", "ldo@1", "ldoreg@1, ...
 
+Binding by means of the node's name is preferred. However if the node names
+would produce ambiguous prefixes (like "regulator@1" and "regualtor@11") and you
+can't or do not want to change them then binding against the "regulator-name"
+property is possible. The syntax for the prefix of the "regulator-name" property
+is the same as the one for the regulator's node name.
+Use case: a regulator named "regulator@1" to be bound to a driver named
+"LDO_DRV" and a regulator named "regualator@11" to be bound to an other driver
+named "BOOST_DRV". Using prefix "regualtor@1" for driver matching would load
+the same driver for both regulators, hence the prefix is ambiguous.
+
 Optional properties:
-- regulator-name: a string, required by the regulator uclass
+- regulator-name: a string, required by the regulator uclass, used for driver
+                  binding if binding by node's name prefix fails
 - regulator-min-microvolt: a minimum allowed Voltage value
 - regulator-max-microvolt: a maximum allowed Voltage value
 - regulator-min-microamp: a minimum allowed Current value
index 537cf5f0bbcb0d6122c247dcf09c326ee701add9..010ed32d3add35c434c0d9f819edd31fcb527fa0 100644 (file)
@@ -10,6 +10,7 @@
 #include <dm.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
+#include <dm/uclass-internal.h>
 
 static const char *if_typename_str[IF_TYPE_COUNT] = {
        [IF_TYPE_IDE]           = "ide",
@@ -331,7 +332,7 @@ int blk_first_device(int if_type, struct udevice **devp)
        struct blk_desc *desc;
        int ret;
 
-       ret = uclass_first_device(UCLASS_BLK, devp);
+       ret = uclass_find_first_device(UCLASS_BLK, devp);
        if (ret)
                return ret;
        if (!*devp)
@@ -340,7 +341,7 @@ int blk_first_device(int if_type, struct udevice **devp)
                desc = dev_get_uclass_platdata(*devp);
                if (desc->if_type == if_type)
                        return 0;
-               ret = uclass_next_device(devp);
+               ret = uclass_find_next_device(devp);
                if (ret)
                        return ret;
        } while (*devp);
@@ -356,7 +357,7 @@ int blk_next_device(struct udevice **devp)
        desc = dev_get_uclass_platdata(*devp);
        if_type = desc->if_type;
        do {
-               ret = uclass_next_device(devp);
+               ret = uclass_find_next_device(devp);
                if (ret)
                        return ret;
                if (!*devp)
index e3f9e4dfc0deedf1cc243b5813c97717337fad24..5d49c93f32a2915b897512aeb8308391bdf4946f 100644 (file)
@@ -201,3 +201,11 @@ config POWER_MC34VR500
        The MC34VR500 is used in conjunction with the FSL T1 and LS1 series
        SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is accessed
        via an I2C interface.
+
+config DM_PMIC_TPS65910
+       bool "Enable driver for Texas Instruments TPS65910 PMIC"
+       depends on DM_PMIC
+       ---help---
+       The TPS65910 is a PMIC containing 3 buck DC-DC converters, one boost
+       DC-DC converter, 8 LDOs and a RTC. This driver binds the SMPS and LDO
+       pmic children.
index f7bdfa560963db7fb5e737a42d27a1ed5f8d7843..7d6c583d347c51b762cfc819862f7f2d2f8d5611 100644 (file)
@@ -19,6 +19,7 @@ obj-$(CONFIG_PMIC_RK8XX) += rk8xx.o
 obj-$(CONFIG_PMIC_RN5T567) += rn5t567.o
 obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
 obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o
+obj-$(CONFIG_DM_PMIC_TPS65910) += pmic_tps65910_dm.o
 obj-$(CONFIG_$(SPL_)PMIC_PALMAS) += palmas.o
 obj-$(CONFIG_$(SPL_)PMIC_LP873X) += lp873x.o
 obj-$(CONFIG_$(SPL_)PMIC_LP87565) += lp87565.o
index 64964e4e963ddb6291499f272d907331a88cc5c1..9347b4068897e8fca645f8974dc70f7a1b39b7f2 100644 (file)
@@ -26,6 +26,7 @@ int pmic_bind_children(struct udevice *pmic, ofnode parent,
        struct driver *drv;
        struct udevice *child;
        const char *node_name;
+       const char *reg_name;
        int bind_count = 0;
        ofnode node;
        int prefix_len;
@@ -44,8 +45,14 @@ int pmic_bind_children(struct udevice *pmic, ofnode parent,
                        debug("  - compatible prefix: '%s'\n", info->prefix);
 
                        prefix_len = strlen(info->prefix);
-                       if (strncmp(info->prefix, node_name, prefix_len))
-                               continue;
+                       if (strncmp(info->prefix, node_name, prefix_len)) {
+                               reg_name = ofnode_read_string(node,
+                                                             "regulator-name");
+                               if (!reg_name)
+                                       continue;
+                               if (strncmp(info->prefix, reg_name, prefix_len))
+                                       continue;
+                       }
 
                        drv = lists_driver_lookup_name(info->driver);
                        if (!drv) {
diff --git a/drivers/power/pmic/pmic_tps65910_dm.c b/drivers/power/pmic/pmic_tps65910_dm.c
new file mode 100644 (file)
index 0000000..0127ce3
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/tps65910_pmic.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+       { .prefix = "ldo_", .driver = TPS65910_LDO_DRIVER },
+       { .prefix = "buck_", .driver = TPS65910_BUCK_DRIVER },
+       { .prefix = "boost_", .driver = TPS65910_BOOST_DRIVER },
+       { },
+};
+
+static int pmic_tps65910_reg_count(struct udevice *dev)
+{
+       return TPS65910_NUM_REGS;
+}
+
+static int pmic_tps65910_write(struct udevice *dev, uint reg, const u8 *buffer,
+                              int len)
+{
+       int ret;
+
+       ret = dm_i2c_write(dev, reg, buffer, len);
+       if (ret)
+               error("%s write error on register %02x\n", dev->name, reg);
+
+       return ret;
+}
+
+static int pmic_tps65910_read(struct udevice *dev, uint reg, u8 *buffer,
+                             int len)
+{
+       int ret;
+
+       ret = dm_i2c_read(dev, reg, buffer, len);
+       if (ret)
+               error("%s read error on register %02x\n", dev->name, reg);
+
+       return ret;
+}
+
+static int pmic_tps65910_bind(struct udevice *dev)
+{
+       ofnode regulators_node;
+       int children;
+
+       regulators_node = dev_read_subnode(dev, "regulators");
+       if (!ofnode_valid(regulators_node)) {
+               debug("%s regulators subnode not found\n", dev->name);
+               return -EINVAL;
+       }
+
+       children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+       if (!children)
+               debug("%s has no children (regulators)\n", dev->name);
+
+       return 0;
+}
+
+static int pmic_tps65910_probe(struct udevice *dev)
+{
+       /* use I2C control interface instead of I2C smartreflex interface to
+        * access smartrefelex registers VDD1_OP_REG, VDD1_SR_REG, VDD2_OP_REG
+        * and VDD2_SR_REG
+        */
+       return pmic_clrsetbits(dev, TPS65910_REG_DEVICE_CTRL, 0,
+                              TPS65910_I2C_SEL_MASK);
+}
+
+static struct dm_pmic_ops pmic_tps65910_ops = {
+       .reg_count = pmic_tps65910_reg_count,
+       .read = pmic_tps65910_read,
+       .write = pmic_tps65910_write,
+};
+
+static const struct udevice_id pmic_tps65910_match[] = {
+       { .compatible = "ti,tps65910" },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(pmic_tps65910) = {
+       .name = "pmic_tps65910",
+       .id = UCLASS_PMIC,
+       .of_match = pmic_tps65910_match,
+       .bind = pmic_tps65910_bind,
+       .probe = pmic_tps65910_probe,
+       .ops = &pmic_tps65910_ops,
+};
index 8892fa14e0226868d1b1b88aec92d1258fbce76f..26fb9368ea9e1c233189860753990af2f72d0bc9 100644 (file)
@@ -188,3 +188,11 @@ config DM_REGULATOR_LP87565
        LP87565 series of PMICs have 4 single phase BUCKs that can also
        be configured in multi phase modes. The driver implements
        get/set api for value and enable.
+
+config DM_REGULATOR_TPS65910
+       bool "Enable driver for TPS65910 PMIC regulators"
+       depends on DM_PMIC_TPS65910
+       ---help---
+       The TPS65910 PMIC provides 4 SMPSs and 8 LDOs. This driver supports all
+       regulator types of the TPS65910 (BUCK, BOOST and LDO). It implements
+       the get/set api for value and enable.
index 6c149a9263473726578f461a9e4070d793e2c3a4..7a2e76dc8293b8609ac19d8eb15036bca4cb8fe0 100644 (file)
@@ -21,3 +21,4 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR_PALMAS) += palmas_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_PBIAS) += pbias_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP873X) += lp873x_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o
+obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o
diff --git a/drivers/power/regulator/tps65910_regulator.c b/drivers/power/regulator/tps65910_regulator.c
new file mode 100644 (file)
index 0000000..5e2ec8f
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/tps65910_pmic.h>
+
+#define VOUT_CHOICE_COUNT 4
+
+/*
+ * struct regulator_props - Properties of a LDO and VIO SMPS regulator
+ *
+ * All of these regulators allow setting one out of four output voltages.
+ * These output voltages are only achievable when supplying the regulator
+ * with a minimum input voltage.
+ *
+ * @vin_min[]: minimum supply input voltage in uV required to achieve the
+ *             corresponding vout[] voltage
+ * @vout[]:    regulator output voltage in uV
+ * @reg:       I2C register used to set regulator voltage
+ */
+struct regulator_props {
+       int vin_min[VOUT_CHOICE_COUNT];
+       int vout[VOUT_CHOICE_COUNT];
+       int reg;
+};
+
+static const struct regulator_props ldo_props_vdig1 = {
+       .vin_min = { 1700000, 2100000, 2700000, 3200000 },
+       .vout = { 1200000, 1500000, 1800000, 2700000 },
+       .reg = TPS65910_REG_VDIG1
+};
+
+static const struct regulator_props ldo_props_vdig2 = {
+       .vin_min = { 1700000, 1700000, 1700000, 2700000 },
+       .vout = { 1000000, 1100000, 1200000, 1800000 },
+       .reg = TPS65910_REG_VDIG2
+};
+
+static const struct regulator_props ldo_props_vpll = {
+       .vin_min = { 2700000, 2700000, 2700000, 3000000 },
+       .vout = { 1000000, 1100000, 1800000, 2500000 },
+       .reg = TPS65910_REG_VPLL
+};
+
+static const struct regulator_props ldo_props_vdac = {
+       .vin_min = { 2700000, 3000000, 3200000, 3200000 },
+       .vout = { 1800000, 2600000, 2800000, 2850000 },
+       .reg = TPS65910_REG_VDAC
+};
+
+static const struct regulator_props ldo_props_vaux1 = {
+       .vin_min = { 2700000, 3200000, 3200000, 3200000 },
+       .vout = { 1800000, 2500000, 2800000, 2850000 },
+       .reg = TPS65910_REG_VAUX1
+};
+
+static const struct regulator_props ldo_props_vaux2 = {
+       .vin_min = { 2700000, 3200000, 3200000, 3600000 },
+       .vout = { 1800000, 2800000, 2900000, 3300000 },
+       .reg = TPS65910_REG_VAUX2
+};
+
+static const struct regulator_props ldo_props_vaux33 = {
+       .vin_min = { 2700000, 2700000, 3200000, 3600000 },
+       .vout = { 1800000, 2000000, 2800000, 3300000 },
+       .reg = TPS65910_REG_VAUX33
+};
+
+static const struct regulator_props ldo_props_vmmc = {
+       .vin_min = { 2700000, 3200000, 3200000, 3600000 },
+       .vout = { 1800000, 2800000, 3000000, 3300000 },
+       .reg = TPS65910_REG_VMMC
+};
+
+static const struct regulator_props smps_props_vio = {
+       .vin_min = { 3200000, 3200000, 4000000, 4400000 },
+       .vout = { 1500000, 1800000, 2500000, 3300000 },
+       .reg = TPS65910_REG_VIO
+};
+
+/* lookup table of control registers indexed by regulator unit number */
+static const int ctrl_regs[] = {
+       TPS65910_REG_VRTC,
+       TPS65910_REG_VIO,
+       TPS65910_REG_VDD1,
+       TPS65910_REG_VDD2,
+       TPS65910_REG_VDD3,
+       TPS65910_REG_VDIG1,
+       TPS65910_REG_VDIG2,
+       TPS65910_REG_VPLL,
+       TPS65910_REG_VDAC,
+       TPS65910_REG_VAUX1,
+       TPS65910_REG_VAUX2,
+       TPS65910_REG_VAUX33,
+       TPS65910_REG_VMMC
+};
+
+/* supply names as used in DT */
+static const char * const supply_names[] = {
+       "vccio-supply",
+       "vcc1-supply",
+       "vcc2-supply",
+       "vcc3-supply",
+       "vcc4-supply",
+       "vcc5-supply",
+       "vcc6-supply",
+       "vcc7-supply"
+};
+
+/* lookup table of regulator supplies indexed by regulator unit number */
+static const int regulator_supplies[] = {
+       TPS65910_SUPPLY_VCC7,
+       TPS65910_SUPPLY_VCCIO,
+       TPS65910_SUPPLY_VCC1,
+       TPS65910_SUPPLY_VCC2,
+       TPS65910_SUPPLY_VCC7,
+       TPS65910_SUPPLY_VCC6,
+       TPS65910_SUPPLY_VCC6,
+       TPS65910_SUPPLY_VCC5,
+       TPS65910_SUPPLY_VCC5,
+       TPS65910_SUPPLY_VCC4,
+       TPS65910_SUPPLY_VCC4,
+       TPS65910_SUPPLY_VCC3,
+       TPS65910_SUPPLY_VCC3
+};
+
+static int get_ctrl_reg_from_unit_addr(const uint unit_addr)
+{
+       if (unit_addr < ARRAY_SIZE(ctrl_regs))
+               return ctrl_regs[unit_addr];
+       return -ENXIO;
+}
+
+static int tps65910_regulator_get_value(struct udevice *dev,
+                                       const struct regulator_props *rgp)
+{
+       int sel, val, vout;
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+       int vin = pdata->supply;
+
+       val = pmic_reg_read(dev->parent, rgp->reg);
+       if (val < 0)
+               return val;
+       sel = (val & TPS65910_SEL_MASK) >> 2;
+       vout = (vin >= *(rgp->vin_min + sel)) ? *(rgp->vout + sel) : 0;
+       vout = ((val & TPS65910_SUPPLY_STATE_MASK) == 1) ? vout : 0;
+
+       return vout;
+}
+
+static int tps65910_ldo_get_value(struct udevice *dev)
+{
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+       int vin;
+
+       if (!pdata)
+               return 0;
+       vin = pdata->supply;
+
+       switch (pdata->unit) {
+       case TPS65910_UNIT_VRTC:
+               /* VRTC is fixed and can't be turned off */
+               return (vin >= 2500000) ? 1830000 : 0;
+       case TPS65910_UNIT_VDIG1:
+               return tps65910_regulator_get_value(dev, &ldo_props_vdig1);
+       case TPS65910_UNIT_VDIG2:
+               return tps65910_regulator_get_value(dev, &ldo_props_vdig2);
+       case TPS65910_UNIT_VPLL:
+               return tps65910_regulator_get_value(dev, &ldo_props_vpll);
+       case TPS65910_UNIT_VDAC:
+               return tps65910_regulator_get_value(dev, &ldo_props_vdac);
+       case TPS65910_UNIT_VAUX1:
+               return tps65910_regulator_get_value(dev, &ldo_props_vaux1);
+       case TPS65910_UNIT_VAUX2:
+               return tps65910_regulator_get_value(dev, &ldo_props_vaux2);
+       case TPS65910_UNIT_VAUX33:
+               return tps65910_regulator_get_value(dev, &ldo_props_vaux33);
+       case TPS65910_UNIT_VMMC:
+               return tps65910_regulator_get_value(dev, &ldo_props_vmmc);
+       default:
+               return 0;
+       }
+}
+
+static int tps65910_regulator_set_value(struct udevice *dev,
+                                       const struct regulator_props *ldo,
+                                       int uV)
+{
+       int val;
+       int sel = 0;
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+
+       do {
+               /* we only allow exact voltage matches */
+               if (uV == *(ldo->vout + sel))
+                       break;
+       } while (++sel < VOUT_CHOICE_COUNT);
+       if (sel == VOUT_CHOICE_COUNT)
+               return -EINVAL;
+       if (pdata->supply < *(ldo->vin_min + sel))
+               return -EINVAL;
+
+       val = pmic_reg_read(dev->parent, ldo->reg);
+       if (val < 0)
+               return val;
+       val &= ~TPS65910_SEL_MASK;
+       val |= sel << 2;
+       return pmic_reg_write(dev->parent, ldo->reg, val);
+}
+
+static int tps65910_ldo_set_value(struct udevice *dev, int uV)
+{
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+       int vin = pdata->supply;
+
+       switch (pdata->unit) {
+       case TPS65910_UNIT_VRTC:
+               /* VRTC is fixed to 1.83V and can't be turned off */
+               if (vin < 2500000)
+                       return -EINVAL;
+               return 0;
+       case TPS65910_UNIT_VDIG1:
+               return tps65910_regulator_set_value(dev, &ldo_props_vdig1, uV);
+       case TPS65910_UNIT_VDIG2:
+               return tps65910_regulator_set_value(dev, &ldo_props_vdig2, uV);
+       case TPS65910_UNIT_VPLL:
+               return tps65910_regulator_set_value(dev, &ldo_props_vpll, uV);
+       case TPS65910_UNIT_VDAC:
+               return tps65910_regulator_set_value(dev, &ldo_props_vdac, uV);
+       case TPS65910_UNIT_VAUX1:
+               return tps65910_regulator_set_value(dev, &ldo_props_vaux1, uV);
+       case TPS65910_UNIT_VAUX2:
+               return tps65910_regulator_set_value(dev, &ldo_props_vaux2, uV);
+       case TPS65910_UNIT_VAUX33:
+               return tps65910_regulator_set_value(dev, &ldo_props_vaux33, uV);
+       case TPS65910_UNIT_VMMC:
+               return tps65910_regulator_set_value(dev, &ldo_props_vmmc, uV);
+       default:
+               return 0;
+       }
+}
+
+static int tps65910_get_enable(struct udevice *dev)
+{
+       int reg, val;
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+
+       reg = get_ctrl_reg_from_unit_addr(pdata->unit);
+       if (reg < 0)
+               return reg;
+
+       val = pmic_reg_read(dev->parent, reg);
+       if (val < 0)
+               return val;
+
+       /* bits 1:0 of regulator control register define state */
+       return ((val & TPS65910_SUPPLY_STATE_MASK) == 1);
+}
+
+static int tps65910_set_enable(struct udevice *dev, bool enable)
+{
+       int reg;
+       uint clr, set;
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+
+       reg = get_ctrl_reg_from_unit_addr(pdata->unit);
+       if (reg < 0)
+               return reg;
+
+       if (enable) {
+               clr = TPS65910_SUPPLY_STATE_MASK & ~TPS65910_SUPPLY_STATE_ON;
+               set = TPS65910_SUPPLY_STATE_MASK & TPS65910_SUPPLY_STATE_ON;
+       } else {
+               clr = TPS65910_SUPPLY_STATE_MASK & ~TPS65910_SUPPLY_STATE_OFF;
+               set = TPS65910_SUPPLY_STATE_MASK & TPS65910_SUPPLY_STATE_OFF;
+       }
+       return pmic_clrsetbits(dev->parent, reg, clr, set);
+}
+
+static int buck_get_vdd1_vdd2_value(struct udevice *dev, int reg_vdd)
+{
+       int gain;
+       int val = pmic_reg_read(dev, reg_vdd);
+
+       if (val < 0)
+               return val;
+       gain = (val & TPS65910_GAIN_SEL_MASK) >> 6;
+       gain = (gain == 0) ? 1 : gain;
+       val = pmic_reg_read(dev, reg_vdd + 1);
+       if (val < 0)
+               return val;
+       if (val & TPS65910_VDD_SR_MASK)
+               /* use smart reflex value instead */
+               val = pmic_reg_read(dev, reg_vdd + 2);
+       if (val < 0)
+               return val;
+       return (562500 + (val & TPS65910_VDD_SEL_MASK) * 12500) * gain;
+}
+
+static int tps65910_buck_get_value(struct udevice *dev)
+{
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+
+       switch (pdata->unit) {
+       case TPS65910_UNIT_VIO:
+               return tps65910_regulator_get_value(dev, &smps_props_vio);
+       case TPS65910_UNIT_VDD1:
+               return buck_get_vdd1_vdd2_value(dev->parent, TPS65910_REG_VDD1);
+       case TPS65910_UNIT_VDD2:
+               return buck_get_vdd1_vdd2_value(dev->parent, TPS65910_REG_VDD2);
+       default:
+               return 0;
+       }
+}
+
+static int buck_set_vdd1_vdd2_value(struct udevice *dev, int uV)
+{
+       int ret, reg_vdd, gain;
+       int val;
+       struct dm_regulator_uclass_platdata *uc_pdata;
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+
+       switch (pdata->unit) {
+       case TPS65910_UNIT_VDD1:
+               reg_vdd = TPS65910_REG_VDD1;
+               break;
+       case TPS65910_UNIT_VDD2:
+               reg_vdd = TPS65910_REG_VDD2;
+               break;
+       default:
+               return -EINVAL;
+       }
+       uc_pdata = dev_get_uclass_platdata(dev);
+
+       /* check setpoint is within limits */
+       if (uV < uc_pdata->min_uV) {
+               error("voltage %duV for %s too low\n", uV, dev->name);
+               return -EINVAL;
+       }
+       if (uV > uc_pdata->max_uV) {
+               error("voltage %duV for %s too high\n", uV, dev->name);
+               return -EINVAL;
+       }
+
+       val = pmic_reg_read(dev->parent, reg_vdd);
+       if (val < 0)
+               return val;
+       gain = (val & TPS65910_GAIN_SEL_MASK) >> 6;
+       gain = (gain == 0) ? 1 : gain;
+       val = ((uV / gain) - 562500) / 12500;
+       if (val < TPS65910_VDD_SEL_MIN || val > TPS65910_VDD_SEL_MAX)
+               /*
+                * Neither do we change the gain, nor do we allow shutdown or
+                * any approximate value (for now)
+                */
+               return -EPERM;
+       val &= TPS65910_VDD_SEL_MASK;
+       ret = pmic_reg_write(dev->parent, reg_vdd + 1, val);
+       if (ret)
+               return ret;
+       return 0;
+}
+
+static int tps65910_buck_set_value(struct udevice *dev, int uV)
+{
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+
+       if (pdata->unit == TPS65910_UNIT_VIO)
+               return tps65910_regulator_set_value(dev, &smps_props_vio, uV);
+
+       return buck_set_vdd1_vdd2_value(dev, uV);
+}
+
+static int tps65910_boost_get_value(struct udevice *dev)
+{
+       int vout;
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+
+       vout = (pdata->supply >= 3000000) ? 5000000 : 0;
+       return vout;
+}
+
+static int tps65910_regulator_ofdata_to_platdata(struct udevice *dev)
+{
+       struct udevice *supply;
+       int ret;
+       const char *supply_name;
+       struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
+
+       pdata->unit = dev_get_driver_data(dev);
+       if (pdata->unit > TPS65910_UNIT_VMMC)
+               return -EINVAL;
+       supply_name = supply_names[regulator_supplies[pdata->unit]];
+
+       debug("Looking up supply power %s\n", supply_name);
+       ret = device_get_supply_regulator(dev->parent, supply_name, &supply);
+       if (ret) {
+               debug("  missing supply power %s\n", supply_name);
+               return ret;
+       }
+       pdata->supply = regulator_get_value(supply);
+       if (pdata->supply < 0) {
+               debug("  invalid supply voltage for regulator %s\n",
+                     supply->name);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct dm_regulator_ops tps65910_boost_ops = {
+       .get_value  = tps65910_boost_get_value,
+       .get_enable = tps65910_get_enable,
+       .set_enable = tps65910_set_enable,
+};
+
+U_BOOT_DRIVER(tps65910_boost) = {
+       .name = TPS65910_BOOST_DRIVER,
+       .id = UCLASS_REGULATOR,
+       .ops = &tps65910_boost_ops,
+       .platdata_auto_alloc_size = sizeof(struct tps65910_regulator_pdata),
+       .ofdata_to_platdata = tps65910_regulator_ofdata_to_platdata,
+};
+
+static const struct dm_regulator_ops tps65910_buck_ops = {
+       .get_value  = tps65910_buck_get_value,
+       .set_value  = tps65910_buck_set_value,
+       .get_enable = tps65910_get_enable,
+       .set_enable = tps65910_set_enable,
+};
+
+U_BOOT_DRIVER(tps65910_buck) = {
+       .name = TPS65910_BUCK_DRIVER,
+       .id = UCLASS_REGULATOR,
+       .ops = &tps65910_buck_ops,
+       .platdata_auto_alloc_size = sizeof(struct tps65910_regulator_pdata),
+       .ofdata_to_platdata = tps65910_regulator_ofdata_to_platdata,
+};
+
+static const struct dm_regulator_ops tps65910_ldo_ops = {
+       .get_value  = tps65910_ldo_get_value,
+       .set_value  = tps65910_ldo_set_value,
+       .get_enable = tps65910_get_enable,
+       .set_enable = tps65910_set_enable,
+};
+
+U_BOOT_DRIVER(tps65910_ldo) = {
+       .name = TPS65910_LDO_DRIVER,
+       .id = UCLASS_REGULATOR,
+       .ops = &tps65910_ldo_ops,
+       .platdata_auto_alloc_size = sizeof(struct tps65910_regulator_pdata),
+       .ofdata_to_platdata = tps65910_regulator_ofdata_to_platdata,
+};
index 3566d17fb1b79b3396415bbb8c8fe583f40804f2..0747c52b607794fef9b4e2de4bc2e0d33dd319c2 100644 (file)
@@ -70,7 +70,7 @@ void reset_cpu(ulong addr)
 
 int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       sysreset_walk_halt(SYSRESET_WARM);
+       sysreset_walk_halt(SYSRESET_COLD);
 
        return 0;
 }
diff --git a/include/binman_sym.h b/include/binman_sym.h
new file mode 100644 (file)
index 0000000..87d03d5
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Symbol access for symbols set up by binman as part of the build.
+ *
+ * This allows C code to access the position of a particular part of the image
+ * assembled by binman.
+ *
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __BINMAN_SYM_H
+#define __BINMAN_SYM_H
+
+#define BINMAN_SYM_MISSING     (-1UL)
+
+#ifdef CONFIG_BINMAN
+
+/**
+ * binman_symname() - Internal fnuction to get a binman symbol name
+ *
+ * @entry_name: Name of the entry to look for (e.g. 'u_boot_spl')
+ * @_prop_name: Property value to get from that entry (e.g. 'pos')
+ * @returns name of the symbol for that entry and property
+ */
+#define binman_symname(_entry_name, _prop_name) \
+       _binman_ ## _entry_name ## _prop_ ## _prop_name
+
+/**
+ * binman_sym_declare() - Declare a symbol that will be used at run-time
+ *
+ * @_type: Type f the symbol (e.g. unsigned long)
+ * @entry_name: Name of the entry to look for (e.g. 'u_boot_spl')
+ * @_prop_name: Property value to get from that entry (e.g. 'pos')
+ */
+#define binman_sym_declare(_type, _entry_name, _prop_name) \
+       _type binman_symname(_entry_name, _prop_name) \
+               __attribute__((aligned(4), unused, section(".binman_sym")))
+
+/**
+ * binman_sym_extern() - Declare a extern symbol that will be used at run-time
+ *
+ * @_type: Type f the symbol (e.g. unsigned long)
+ * @entry_name: Name of the entry to look for (e.g. 'u_boot_spl')
+ * @_prop_name: Property value to get from that entry (e.g. 'pos')
+ */
+#define binman_sym_extern(_type, _entry_name, _prop_name) \
+       extern _type binman_symname(_entry_name, _prop_name) \
+               __attribute__((aligned(4), unused, section(".binman_sym")))
+
+/**
+ * binman_sym_declare_optional() - Declare an optional symbol
+ *
+ * If this symbol cannot be provided by binman, an error will not be generated.
+ * Instead the image will be assigned the value BINMAN_SYM_MISSING.
+ *
+ * @_type: Type f the symbol (e.g. unsigned long)
+ * @entry_name: Name of the entry to look for (e.g. 'u_boot_spl')
+ * @_prop_name: Property value to get from that entry (e.g. 'pos')
+ */
+#define binman_sym_declare_optional(_type, _entry_name, _prop_name) \
+       _type binman_symname(_entry_name, _prop_name) \
+               __attribute__((aligned(4), weak, unused, \
+               section(".binman_sym")))
+
+/**
+ * binman_sym() - Access a previously declared symbol
+ *
+ * This is used to get the value of a symbol. E.g.:
+ *
+ *    ulong address = binman_sym(ulong, u_boot_spl, pos);
+ *
+ * @_type: Type f the symbol (e.g. unsigned long)
+ * @entry_name: Name of the entry to look for (e.g. 'u_boot_spl')
+ * @_prop_name: Property value to get from that entry (e.g. 'pos')
+ * @returns value of that property (filled in by binman)
+ */
+#define binman_sym(_type, _entry_name, _prop_name) \
+       (*(_type *)&binman_symname(_entry_name, _prop_name))
+
+#else /* !BINMAN */
+
+#define binman_sym_declare(_type, _entry_name, _prop_name)
+
+#define binman_sym_declare_optional(_type, _entry_name, _prop_name)
+
+#define binman_sym_extern(_type, _entry_name, _prop_name)
+
+#define binman_sym(_type, _entry_name, _prop_name) BINMAN_SYM_MISSING
+
+#endif /* BINMAN */
+
+#endif
index 7fdbfb9fc6f978ac9e58f26824b42044f6a42bf5..c5e6fda2ea0f9c509c7148b08fe66490870b996d 100644 (file)
@@ -13,7 +13,7 @@
 #define SANDBOX_BUCK_DRIVER            "sandbox_buck"
 #define SANDBOX_OF_BUCK_PREFIX         "buck"
 
-#define SANDBOX_BUCK_COUNT     2
+#define SANDBOX_BUCK_COUNT     3
 #define SANDBOX_LDO_COUNT      2
 /*
  * Sandbox PMIC registers:
@@ -109,6 +109,9 @@ enum {
 #define SANDBOX_BUCK1_PLATNAME "SUPPLY_1.2V"
 #define SANDBOX_BUCK2_DEVNAME  "buck2"
 #define SANDBOX_BUCK2_PLATNAME "SUPPLY_3.3V"
+/* BUCK3: for testing fallback regulator prefix matching during bind */
+#define SANDBOX_BUCK3_DEVNAME  "no_match_by_nodename"
+#define SANDBOX_BUCK3_PLATNAME "buck_SUPPLY_1.5V"
 /* LDO names */
 #define SANDBOX_LDO1_DEVNAME   "ldo1"
 #define SANDBOX_LDO1_PLATNAME  "VDD_EMMC_1.8V"
diff --git a/include/power/tps65910_pmic.h b/include/power/tps65910_pmic.h
new file mode 100644 (file)
index 0000000..e8d9ffa
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __TPS65910_PMIC_H_
+#define __TPS65910_PMIC_H_
+
+#define TPS65910_I2C_SEL_MASK          (0x1 << 4)
+#define TPS65910_VDD_SR_MASK           (0x1 << 7)
+#define TPS65910_GAIN_SEL_MASK         (0x3 << 6)
+#define TPS65910_VDD_SEL_MASK          0x7f
+#define TPS65910_VDD_SEL_MIN           3
+#define TPS65910_VDD_SEL_MAX           75
+#define TPS65910_SEL_MASK              (0x3 << 2)
+#define TPS65910_SUPPLY_STATE_MASK     0x3
+#define TPS65910_SUPPLY_STATE_OFF      0x0
+#define TPS65910_SUPPLY_STATE_ON       0x1
+
+/* i2c registers */
+enum {
+       TPS65910_REG_RTC_SEC                    = 0x00,
+       TPS65910_REG_RTC_MIN,
+       TPS65910_REG_RTC_HOUR,
+       TPS65910_REG_RTC_DAY,
+       TPS65910_REG_RTC_MONTH,
+       TPS65910_REG_RTC_YEAR,
+       TPS65910_REG_RTC_WEEK,
+       TPS65910_REG_RTC_ALARM_SEC              = 0x08,
+       TPS65910_REG_RTC_ALARM_MIN,
+       TPS65910_REG_RTC_ALARM_HOUR,
+       TPS65910_REG_RTC_ALARM_DAY,
+       TPS65910_REG_RTC_ALARM_MONTH,
+       TPS65910_REG_RTC_ALARM_YEAR,
+       TPS65910_REG_RTC_CTRL                   = 0x10,
+       TPS65910_REG_RTC_STAT,
+       TPS65910_REG_RTC_INT,
+       TPS65910_REG_RTC_COMP_LSB,
+       TPS65910_REG_RTC_COMP_MSB,
+       TPS65910_REG_RTC_RESISTOR_PRG,
+       TPS65910_REG_RTC_RESET_STAT,
+       TPS65910_REG_BACKUP1,
+       TPS65910_REG_BACKUP2,
+       TPS65910_REG_BACKUP3,
+       TPS65910_REG_BACKUP4,
+       TPS65910_REG_BACKUP5,
+       TPS65910_REG_PUADEN,
+       TPS65910_REG_REF,
+       TPS65910_REG_VRTC,
+       TPS65910_REG_VIO                        = 0x20,
+       TPS65910_REG_VDD1,
+       TPS65910_REG_VDD1_VAL,
+       TPS65910_REG_VDD1_VAL_SR,
+       TPS65910_REG_VDD2,
+       TPS65910_REG_VDD2_VAL,
+       TPS65910_REG_VDD2_VAL_SR,
+       TPS65910_REG_VDD3,
+       TPS65910_REG_VDIG1                      = 0x30,
+       TPS65910_REG_VDIG2,
+       TPS65910_REG_VAUX1,
+       TPS65910_REG_VAUX2,
+       TPS65910_REG_VAUX33,
+       TPS65910_REG_VMMC,
+       TPS65910_REG_VPLL,
+       TPS65910_REG_VDAC,
+       TPS65910_REG_THERM,
+       TPS65910_REG_BATTERY_BACKUP_CHARGE,
+       TPS65910_REG_DCDC_CTRL                  = 0x3e,
+       TPS65910_REG_DEVICE_CTRL,
+       TPS65910_REG_DEVICE_CTRL2,
+       TPS65910_REG_SLEEP_KEEP_LDO_ON,
+       TPS65910_REG_SLEEP_KEEP_RES_ON,
+       TPS65910_REG_SLEEP_SET_LDO_OFF,
+       TPS65910_REG_SLEEP_SET_RES_OFF,
+       TPS65910_REG_EN1_LDO_ASS,
+       TPS65910_REG_EM1_SMPS_ASS,
+       TPS65910_REG_EN2_LDO_ASS,
+       TPS65910_REG_EM2_SMPS_ASS,
+       TPS65910_REG_INT_STAT                   = 0x50,
+       TPS65910_REG_INT_MASK,
+       TPS65910_REG_INT_STAT2,
+       TPS65910_REG_INT_MASK2,
+       TPS65910_REG_GPIO                       = 0x60,
+       TPS65910_REG_JTAGREVNUM                 = 0x80,
+       TPS65910_NUM_REGS
+};
+
+/* chip supplies */
+enum {
+       TPS65910_SUPPLY_VCCIO   = 0x00,
+       TPS65910_SUPPLY_VCC1,
+       TPS65910_SUPPLY_VCC2,
+       TPS65910_SUPPLY_VCC3,
+       TPS65910_SUPPLY_VCC4,
+       TPS65910_SUPPLY_VCC5,
+       TPS65910_SUPPLY_VCC6,
+       TPS65910_SUPPLY_VCC7,
+       TPS65910_NUM_SUPPLIES
+};
+
+/* regulator unit numbers */
+enum {
+       TPS65910_UNIT_VRTC = 0x00,
+       TPS65910_UNIT_VIO,
+       TPS65910_UNIT_VDD1,
+       TPS65910_UNIT_VDD2,
+       TPS65910_UNIT_VDD3,
+       TPS65910_UNIT_VDIG1,
+       TPS65910_UNIT_VDIG2,
+       TPS65910_UNIT_VPLL,
+       TPS65910_UNIT_VDAC,
+       TPS65910_UNIT_VAUX1,
+       TPS65910_UNIT_VAUX2,
+       TPS65910_UNIT_VAUX33,
+       TPS65910_UNIT_VMMC,
+};
+
+/* platform data */
+struct tps65910_regulator_pdata {
+       u32 supply;     /* regulator supply voltage in uV */
+       uint unit;      /* unit-address according to DT */
+};
+
+/* driver names */
+#define TPS65910_BUCK_DRIVER   "tps65910_buck"
+#define TPS65910_BOOST_DRIVER  "tps65910_boost"
+#define TPS65910_LDO_DRIVER    "tps65910_ldo"
+
+#endif /* __TPS65910_PMIC_H_ */
index 308ce7b563bf94ad11e4e4dcc3b1752d063a8dd6..c14448b8fc98a85c78b231647f948fb584c40ec2 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef        _SPL_H_
 #define        _SPL_H_
 
+#include <binman_sym.h>
+
 /* Platform-specific defines */
 #include <linux/compiler.h>
 #include <asm/spl.h>
@@ -51,6 +53,15 @@ struct spl_load_info {
                      void *buf);
 };
 
+/*
+ * We need to know the position of U-Boot in memory so we can jump to it. We
+ * allow any U-Boot binary to be used (u-boot.bin, u-boot-nodtb.bin,
+ * u-boot.img), hence the '_any'. These is no checking here that the correct
+ * image is found. For * example if u-boot.img is used we don't check that
+ * spl_parse_image_header() can parse a valid header.
+ */
+binman_sym_extern(ulong, u_boot_any, pos);
+
 /**
  * spl_load_simple_fit() - Loads a fit image from a device.
  * @spl_image: Image description to set up
index 3d0056f2dc7bf13049d4d2c13e711bedf9aa8f77..395381d4bd2f2b0902766ac47c7fd425d13b6e35 100644 (file)
@@ -27,6 +27,7 @@ DECLARE_GLOBAL_DATA_PTR;
 enum {
        BUCK1,
        BUCK2,
+       BUCK3,
        LDO1,
        LDO2,
        OUTPUT_COUNT,
@@ -42,6 +43,7 @@ static const char *regulator_names[OUTPUT_COUNT][OUTPUT_NAME_COUNT] = {
        /* devname, platname */
        { SANDBOX_BUCK1_DEVNAME, SANDBOX_BUCK1_PLATNAME },
        { SANDBOX_BUCK2_DEVNAME, SANDBOX_BUCK2_PLATNAME },
+       { SANDBOX_BUCK3_DEVNAME, SANDBOX_BUCK3_PLATNAME },
        { SANDBOX_LDO1_DEVNAME, SANDBOX_LDO1_PLATNAME},
        { SANDBOX_LDO2_DEVNAME, SANDBOX_LDO2_PLATNAME},
 };
index 4ef76c8f08977b6a8f7d068ae024987679c7439d..08c3e56bdef8d3ee47ac2ec86411465a78dbf567 100644 (file)
@@ -439,6 +439,8 @@ contents of an entry in some way. For example, it would be possible to create
 an entry containing a hash of the contents of some other entries. At this
 stage the position and size of entries should not be adjusted.
 
+6. WriteEntryInfo()
+
 7. BuildImage() - builds the image and writes it to a file. This is the final
 step.
 
@@ -471,6 +473,33 @@ the 'warning' line in scripts/Makefile.lib to see what it has found:
    # u_boot_dtsi_options_debug = $(u_boot_dtsi_options_raw)
 
 
+Access to binman entry positions at run time
+--------------------------------------------
+
+Binman assembles images and determines where each entry is placed in the image.
+This information may be useful to U-Boot at run time. For example, in SPL it
+is useful to be able to find the location of U-Boot so that it can be executed
+when SPL is finished.
+
+Binman allows you to declare symbols in the SPL image which are filled in
+with their correct values during the build. For example:
+
+    binman_sym_declare(ulong, u_boot_any, pos);
+
+declares a ulong value which will be assigned to the position of any U-Boot
+image (u-boot.bin, u-boot.img, u-boot-nodtb.bin) that is present in the image.
+You can access this value with something like:
+
+    ulong u_boot_pos = binman_sym(ulong, u_boot_any, pos);
+
+Thus u_boot_pos will be set to the position of U-Boot in memory, assuming that
+the whole image has been loaded, or is available in flash. You can then jump to
+that address to start U-Boot.
+
+At present this feature is only supported in SPL. In principle it is possible
+to fill in such symbols in U-Boot proper, as well.
+
+
 Code coverage
 -------------
 
@@ -543,7 +572,8 @@ To do
 
 Some ideas:
 - Fill out the device tree to include the final position and size of each
-  entry (since the input file may not always specify these)
+  entry (since the input file may not always specify these). See also
+  'Access to binman entry positions at run time' above
 - Use of-platdata to make the information available to code that is unable
   to use device tree (such as a very small SPL image)
 - Write an image map to a text file
index 3ccf25f1f884249ca98733b6b88423539c353516..1c8e8dbff65a04dc7b07828a3dc579bb97bdc758 100755 (executable)
@@ -31,11 +31,13 @@ import cmdline
 import command
 import control
 
-def RunTests():
+def RunTests(debug):
     """Run the functional tests and any embedded doctests"""
+    import elf_test
     import entry_test
     import fdt_test
     import ftest
+    import image_test
     import test
     import doctest
 
@@ -45,12 +47,15 @@ def RunTests():
         suite.run(result)
 
     sys.argv = [sys.argv[0]]
+    if debug:
+        sys.argv.append('-D')
 
     # Run the entry tests first ,since these need to be the first to import the
     # 'entry' module.
     suite = unittest.TestLoader().loadTestsFromTestCase(entry_test.TestEntry)
     suite.run(result)
-    for module in (ftest.TestFunctional, fdt_test.TestFdt):
+    for module in (ftest.TestFunctional, fdt_test.TestFdt, elf_test.TestElf,
+                   image_test.TestImage):
         suite = unittest.TestLoader().loadTestsFromTestCase(module)
         suite.run(result)
 
@@ -110,7 +115,7 @@ def RunBinman(options, args):
         sys.tracebacklimit = 0
 
     if options.test:
-        ret_code = RunTests()
+        ret_code = RunTests(options.debug)
 
     elif options.test_coverage:
         RunTestCoverage()
index e9d48df03014cde346fd9175c5d32fb8b6d75e9a..ffa2bbd80f69a2a11870f215d56dc466016c5117 100644 (file)
@@ -12,6 +12,7 @@ import sys
 import tools
 
 import command
+import elf
 import fdt
 import fdt_util
 from image import Image
@@ -89,6 +90,7 @@ def Binman(options, args):
 
     try:
         tout.Init(options.verbosity)
+        elf.debug = options.debug
         try:
             tools.SetInputDirs(options.indir)
             tools.PrepareOutputDir(options.outdir, options.preserve)
@@ -109,6 +111,7 @@ def Binman(options, args):
                 image.CheckSize()
                 image.CheckEntries()
                 image.ProcessEntryContents()
+                image.WriteSymbols()
                 image.BuildImage()
         finally:
             tools.FinaliseOutputDir()
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
new file mode 100644 (file)
index 0000000..80ff225
--- /dev/null
@@ -0,0 +1,129 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+# Handle various things related to ELF images
+#
+
+from collections import namedtuple, OrderedDict
+import command
+import os
+import re
+import struct
+
+import tools
+
+# This is enabled from control.py
+debug = False
+
+Symbol = namedtuple('Symbol', ['section', 'address', 'size', 'weak'])
+
+
+def GetSymbols(fname, patterns):
+    """Get the symbols from an ELF file
+
+    Args:
+        fname: Filename of the ELF file to read
+        patterns: List of regex patterns to search for, each a string
+
+    Returns:
+        None, if the file does not exist, or Dict:
+          key: Name of symbol
+          value: Hex value of symbol
+    """
+    stdout = command.Output('objdump', '-t', fname, raise_on_error=False)
+    lines = stdout.splitlines()
+    if patterns:
+        re_syms = re.compile('|'.join(patterns))
+    else:
+        re_syms = None
+    syms = {}
+    syms_started = False
+    for line in lines:
+        if not line or not syms_started:
+            if 'SYMBOL TABLE' in line:
+                syms_started = True
+            line = None  # Otherwise code coverage complains about 'continue'
+            continue
+        if re_syms and not re_syms.search(line):
+            continue
+
+        space_pos = line.find(' ')
+        value, rest = line[:space_pos], line[space_pos + 1:]
+        flags = rest[:7]
+        parts = rest[7:].split()
+        section, size =  parts[:2]
+        if len(parts) > 2:
+            name = parts[2]
+            syms[name] = Symbol(section, int(value, 16), int(size,16),
+                                flags[1] == 'w')
+    return syms
+
+def GetSymbolAddress(fname, sym_name):
+    """Get a value of a symbol from an ELF file
+
+    Args:
+        fname: Filename of the ELF file to read
+        patterns: List of regex patterns to search for, each a string
+
+    Returns:
+        Symbol value (as an integer) or None if not found
+    """
+    syms = GetSymbols(fname, [sym_name])
+    sym = syms.get(sym_name)
+    if not sym:
+        return None
+    return sym.address
+
+def LookupAndWriteSymbols(elf_fname, entry, image):
+    """Replace all symbols in an entry with their correct values
+
+    The entry contents is updated so that values for referenced symbols will be
+    visible at run time. This is done by finding out the symbols positions in
+    the entry (using the ELF file) and replacing them with values from binman's
+    data structures.
+
+    Args:
+        elf_fname: Filename of ELF image containing the symbol information for
+            entry
+        entry: Entry to process
+        image: Image which can be used to lookup symbol values
+    """
+    fname = tools.GetInputFilename(elf_fname)
+    syms = GetSymbols(fname, ['image', 'binman'])
+    if not syms:
+        return
+    base = syms.get('__image_copy_start')
+    if not base:
+        return
+    for name, sym in syms.iteritems():
+        if name.startswith('_binman'):
+            msg = ("Image '%s': Symbol '%s'\n   in entry '%s'" %
+                   (image.GetPath(), name, entry.GetPath()))
+            offset = sym.address - base.address
+            if offset < 0 or offset + sym.size > entry.contents_size:
+                raise ValueError('%s has offset %x (size %x) but the contents '
+                                 'size is %x' % (entry.GetPath(), offset,
+                                                 sym.size, entry.contents_size))
+            if sym.size == 4:
+                pack_string = '<I'
+            elif sym.size == 8:
+                pack_string = '<Q'
+            else:
+                raise ValueError('%s has size %d: only 4 and 8 are supported' %
+                                 (msg, sym.size))
+
+            # Look up the symbol in our entry tables.
+            value = image.LookupSymbol(name, sym.weak, msg)
+            if value is not None:
+                value += base.address
+            else:
+                value = -1
+                pack_string = pack_string.lower()
+            value_bytes = struct.pack(pack_string, value)
+            if debug:
+                print('%s:\n   insert %s, offset %x, value %x, length %d' %
+                      (msg, name, offset, value, len(value_bytes)))
+            entry.data = (entry.data[:offset] + value_bytes +
+                        entry.data[offset + sym.size:])
diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py
new file mode 100644 (file)
index 0000000..e5fc282
--- /dev/null
@@ -0,0 +1,122 @@
+#
+# Copyright (c) 2017 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+# Test for the elf module
+
+from contextlib import contextmanager
+import os
+import sys
+import unittest
+
+try:
+  from StringIO import StringIO
+except ImportError:
+  from io import StringIO
+
+import elf
+
+binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
+
+# Use this to suppress stdout/stderr output:
+# with capture_sys_output() as (stdout, stderr)
+#   ...do something...
+@contextmanager
+def capture_sys_output():
+  capture_out, capture_err = StringIO(), StringIO()
+  old_out, old_err = sys.stdout, sys.stderr
+  try:
+    sys.stdout, sys.stderr = capture_out, capture_err
+    yield capture_out, capture_err
+  finally:
+    sys.stdout, sys.stderr = old_out, old_err
+
+
+class FakeEntry:
+    def __init__(self, contents_size):
+        self.contents_size = contents_size
+        self.data = 'a' * contents_size
+
+    def GetPath(self):
+        return 'entry_path'
+
+class FakeImage:
+    def __init__(self, sym_value=1):
+        self.sym_value = sym_value
+
+    def GetPath(self):
+        return 'image_path'
+
+    def LookupSymbol(self, name, weak, msg):
+        return self.sym_value
+
+class TestElf(unittest.TestCase):
+    def testAllSymbols(self):
+        fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
+        syms = elf.GetSymbols(fname, [])
+        self.assertIn('.ucode', syms)
+
+    def testRegexSymbols(self):
+        fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
+        syms = elf.GetSymbols(fname, ['ucode'])
+        self.assertIn('.ucode', syms)
+        syms = elf.GetSymbols(fname, ['missing'])
+        self.assertNotIn('.ucode', syms)
+        syms = elf.GetSymbols(fname, ['missing', 'ucode'])
+        self.assertIn('.ucode', syms)
+
+    def testMissingFile(self):
+        entry = FakeEntry(10)
+        image = FakeImage()
+        with self.assertRaises(ValueError) as e:
+            syms = elf.LookupAndWriteSymbols('missing-file', entry, image)
+        self.assertIn("Filename 'missing-file' not found in input path",
+                      str(e.exception))
+
+    def testOutsideFile(self):
+        entry = FakeEntry(10)
+        image = FakeImage()
+        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
+        with self.assertRaises(ValueError) as e:
+            syms = elf.LookupAndWriteSymbols(elf_fname, entry, image)
+        self.assertIn('entry_path has offset 4 (size 8) but the contents size '
+                      'is a', str(e.exception))
+
+    def testMissingImageStart(self):
+        entry = FakeEntry(10)
+        image = FakeImage()
+        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_bad')
+        self.assertEqual(elf.LookupAndWriteSymbols(elf_fname, entry, image),
+                         None)
+
+    def testBadSymbolSize(self):
+        entry = FakeEntry(10)
+        image = FakeImage()
+        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_size')
+        with self.assertRaises(ValueError) as e:
+            syms = elf.LookupAndWriteSymbols(elf_fname, entry, image)
+        self.assertIn('has size 1: only 4 and 8 are supported',
+                      str(e.exception))
+
+    def testNoValue(self):
+        entry = FakeEntry(20)
+        image = FakeImage(sym_value=None)
+        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
+        syms = elf.LookupAndWriteSymbols(elf_fname, entry, image)
+        self.assertEqual(chr(255) * 16 + 'a' * 4, entry.data)
+
+    def testDebug(self):
+        elf.debug = True
+        entry = FakeEntry(20)
+        image = FakeImage()
+        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
+        with capture_sys_output() as (stdout, stderr):
+            syms = elf.LookupAndWriteSymbols(elf_fname, entry, image)
+        elf.debug = False
+        self.assertTrue(len(stdout.getvalue()) > 0)
+
+
+if __name__ == '__main__':
+    unittest.main()
index 67c57341ca21d6ee79c08ee350b8e25a40479e99..5541887d475cfb55222fa48d9d1adc422a1e2a26 100644 (file)
@@ -198,3 +198,11 @@ class Entry(object):
 
     def ProcessContents(self):
         pass
+
+    def WriteSymbols(self, image):
+        """Write symbol values into binary files for access at run time
+
+        Args:
+          image: Image containing the entry
+        """
+        pass
index 68b0148427dcfb3d6395b3ee3395d9f7bc104824..3720b47fef6365257dc08c5a3f5786b6c56f7617 100644 (file)
@@ -6,12 +6,18 @@
 # Entry-type module for spl/u-boot-spl.bin
 #
 
+import elf
+
 from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_spl(Entry_blob):
     def __init__(self, image, etype, node):
         Entry_blob.__init__(self, image, etype, node)
+        self.elf_fname = 'spl/u-boot-spl'
 
     def GetDefaultFilename(self):
         return 'spl/u-boot-spl.bin'
+
+    def WriteSymbols(self, image):
+        elf.LookupAndWriteSymbols(self.elf_fname, self, image)
index c005f28191fef199e110cada3bb0083f4ee99962..c37f61db23553de720f2659714c3409f4dd1798f 100644 (file)
@@ -9,6 +9,7 @@
 #
 
 import command
+import elf
 from entry import Entry
 from blob import Entry_blob
 import tools
@@ -19,8 +20,8 @@ class Entry_u_boot_spl_bss_pad(Entry_blob):
 
     def ObtainContents(self):
         fname = tools.GetInputFilename('spl/u-boot-spl')
-        args = [['nm', fname], ['grep', '__bss_size']]
-        out = command.RunPipe(args, capture=True).stdout.splitlines()
-        bss_size = int(out[0].split()[0], 16)
+        bss_size = elf.GetSymbolAddress(fname, '__bss_size')
+        if not bss_size:
+            self.Raise('Expected __bss_size symbol in spl/u-boot-spl')
         self.data = chr(0) * bss_size
         self.contents_size = bss_size
diff --git a/tools/binman/etype/u_boot_spl_dtb.py b/tools/binman/etype/u_boot_spl_dtb.py
new file mode 100644 (file)
index 0000000..6c5ce1e
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+# Entry-type module for U-Boot device tree
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_spl_dtb(Entry_blob):
+    def __init__(self, image, etype, node):
+        Entry_blob.__init__(self, image, etype, node)
+
+    def GetDefaultFilename(self):
+        return 'spl/u-boot-spl.dtb'
diff --git a/tools/binman/etype/u_boot_spl_nodtb.py b/tools/binman/etype/u_boot_spl_nodtb.py
new file mode 100644 (file)
index 0000000..880e0c7
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+# Entry-type module for 'u-boot-nodtb.bin'
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_spl_nodtb(Entry_blob):
+    def __init__(self, image, etype, node):
+        Entry_blob.__init__(self, image, etype, node)
+
+    def GetDefaultFilename(self):
+        return 'spl/u-boot-spl-nodtb.bin'
index 6f01adb9701892cb7277f6c115bad929e7e81939..99b437130dbbffc4b8df99b9a1ce76431b7c8232 100644 (file)
@@ -9,6 +9,7 @@
 import struct
 
 import command
+import elf
 from entry import Entry
 from blob import Entry_blob
 import fdt_util
@@ -31,11 +32,9 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob):
     def ObtainContents(self):
         # Figure out where to put the microcode pointer
         fname = tools.GetInputFilename(self.elf_fname)
-        args = [['nm', fname], ['grep', '-w', '_dt_ucode_base_size']]
-        out = (command.RunPipe(args, capture=True, raise_on_error=False).
-               stdout.splitlines())
-        if len(out) == 1:
-            self.target_pos = int(out[0].split()[0], 16)
+        sym = elf.GetSymbolAddress(fname, '_dt_ucode_base_size')
+        if sym:
+           self.target_pos = sym
         elif not fdt_util.GetBool(self._node, 'optional-ucode'):
             self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot')
 
index 9083143894f0c784f8a74cfc4de4e96644748b70..5812ab397cf35d10487c698d43fa1bb1d209a800 100644 (file)
@@ -20,6 +20,7 @@ import binman
 import cmdline
 import command
 import control
+import elf
 import fdt
 import fdt_util
 import tools
@@ -28,11 +29,12 @@ import tout
 # Contents of test files, corresponding to different entry types
 U_BOOT_DATA           = '1234'
 U_BOOT_IMG_DATA       = 'img'
-U_BOOT_SPL_DATA       = '567'
+U_BOOT_SPL_DATA       = '56780123456789abcde'
 BLOB_DATA             = '89'
 ME_DATA               = '0abcd'
 VGA_DATA              = 'vga'
 U_BOOT_DTB_DATA       = 'udtb'
+U_BOOT_SPL_DTB_DATA   = 'spldtb'
 X86_START16_DATA      = 'start16'
 X86_START16_SPL_DATA  = 'start16spl'
 U_BOOT_NODTB_DATA     = 'nodtb with microcode pointer somewhere in here'
@@ -76,6 +78,7 @@ class TestFunctional(unittest.TestCase):
         TestFunctional._MakeInputFile('me.bin', ME_DATA)
         TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
         TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
+        TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
         TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
         TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
                                       X86_START16_SPL_DATA)
@@ -134,7 +137,10 @@ class TestFunctional(unittest.TestCase):
         Returns:
             Return value (0 for success)
         """
-        (options, args) = cmdline.ParseArgs(list(args))
+        args = list(args)
+        if '-D' in sys.argv:
+            args = args + ['-D']
+        (options, args) = cmdline.ParseArgs(args)
         options.pager = 'binman-invalid-pager'
         options.build_dir = self._indir
 
@@ -142,14 +148,16 @@ class TestFunctional(unittest.TestCase):
         # options.verbosity = tout.DEBUG
         return control.Binman(options, args)
 
-    def _DoTestFile(self, fname):
+    def _DoTestFile(self, fname, debug=False):
         """Run binman with a given test file
 
         Args:
             fname: Device tree source filename to use (e.g. 05_simple.dts)
         """
-        return self._DoBinman('-p', '-I', self._indir,
-                              '-d', self.TestFile(fname))
+        args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
+        if debug:
+            args.append('-D')
+        return self._DoBinman(*args)
 
     def _SetupDtb(self, fname, outfile='u-boot.dtb'):
         """Set up a new test device-tree file
@@ -302,7 +310,6 @@ class TestFunctional(unittest.TestCase):
         self.assertEqual(0, len(result.stderr))
         self.assertEqual(0, result.return_code)
 
-    # Not yet available.
     def testBoard(self):
         """Test that we can run it with a specific board"""
         self._SetupDtb('05_simple.dts', 'sandbox/u-boot.dtb')
@@ -362,6 +369,10 @@ class TestFunctional(unittest.TestCase):
         data = self._DoReadFile('05_simple.dts')
         self.assertEqual(U_BOOT_DATA, data)
 
+    def testSimpleDebug(self):
+        """Test a simple binman run with debugging enabled"""
+        data = self._DoTestFile('05_simple.dts', debug=True)
+
     def testDual(self):
         """Test that we can handle creating two images
 
@@ -563,8 +574,10 @@ class TestFunctional(unittest.TestCase):
 
     def testImagePadByte(self):
         """Test that the image pad byte can be specified"""
+        with open(self.TestFile('bss_data')) as fd:
+            TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
         data = self._DoReadFile('21_image_pad.dts')
-        self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 9) + U_BOOT_DATA, data)
+        self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data)
 
     def testImageName(self):
         """Test that image files can be named"""
@@ -586,7 +599,7 @@ class TestFunctional(unittest.TestCase):
     def testPackSorted(self):
         """Test that entries can be sorted"""
         data = self._DoReadFile('24_sorted.dts')
-        self.assertEqual(chr(0) * 5 + U_BOOT_SPL_DATA + chr(0) * 2 +
+        self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
                          U_BOOT_DATA, data)
 
     def testPackZeroPosition(self):
@@ -614,14 +627,14 @@ class TestFunctional(unittest.TestCase):
         with self.assertRaises(ValueError) as e:
             self._DoTestFile('28_pack_4gb_outside.dts')
         self.assertIn("Node '/binman/u-boot': Position 0x0 (0) is outside "
-                      "the image starting at 0xfffffff0 (4294967280)",
+                      "the image starting at 0xffffffe0 (4294967264)",
                       str(e.exception))
 
     def testPackX86Rom(self):
         """Test that a basic x86 ROM can be created"""
         data = self._DoReadFile('29_x86-rom.dts')
-        self.assertEqual(U_BOOT_DATA + chr(0) * 3 + U_BOOT_SPL_DATA +
-                         chr(0) * 6, data)
+        self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA +
+                         chr(0) * 2, data)
 
     def testPackX86RomMeNoDesc(self):
         """Test that an invalid Intel descriptor entry is detected"""
@@ -835,6 +848,13 @@ class TestFunctional(unittest.TestCase):
         data = self._DoReadFile('47_spl_bss_pad.dts')
         self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data)
 
+        with open(self.TestFile('u_boot_ucode_ptr')) as fd:
+            TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
+        with self.assertRaises(ValueError) as e:
+            data = self._DoReadFile('47_spl_bss_pad.dts')
+        self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
+                      str(e.exception))
+
     def testPackStart16Spl(self):
         """Test that an image with an x86 start16 region can be created"""
         data = self._DoReadFile('48_x86-start16-spl.dts')
@@ -862,6 +882,32 @@ class TestFunctional(unittest.TestCase):
         data = self._DoReadFile('50_intel_mrc.dts')
         self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
 
+    def testSplDtb(self):
+        """Test that an image with spl/u-boot-spl.dtb can be created"""
+        data = self._DoReadFile('51_u_boot_spl_dtb.dts')
+        self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
+
+    def testSplNoDtb(self):
+        """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
+        data = self._DoReadFile('52_u_boot_spl_nodtb.dts')
+        self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
+
+    def testSymbols(self):
+        """Test binman can assign symbols embedded in U-Boot"""
+        elf_fname = self.TestFile('u_boot_binman_syms')
+        syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
+        addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
+        self.assertEqual(syms['_binman_u_boot_spl_prop_pos'].address, addr)
+
+        with open(self.TestFile('u_boot_binman_syms')) as fd:
+            TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
+        data = self._DoReadFile('53_symbols.dts')
+        sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
+        expected = (sym_values + U_BOOT_SPL_DATA[16:] + chr(0xff) +
+                    U_BOOT_DATA +
+                    sym_values + U_BOOT_SPL_DATA[16:])
+        self.assertEqual(expected, data)
+
 
 if __name__ == "__main__":
     unittest.main()
index 24c4f6f578a6a61ee59041f6bae86b834c1662ad..741630f0912afc1ec9cfe5ca835c01ceb7ed226c 100644 (file)
@@ -6,8 +6,12 @@
 # Class for an image, the output of binman
 #
 
+from __future__ import print_function
+
 from collections import OrderedDict
 from operator import attrgetter
+import re
+import sys
 
 import fdt_util
 import tools
@@ -45,7 +49,7 @@ class Image:
              address.
         _entries: OrderedDict() of entries
     """
-    def __init__(self, name, node):
+    def __init__(self, name, node, test=False):
         global entry
         global Entry
         import entry
@@ -64,8 +68,9 @@ class Image:
         self._end_4gb = False
         self._entries = OrderedDict()
 
-        self._ReadNode()
-        self._ReadEntries()
+        if not test:
+            self._ReadNode()
+            self._ReadEntries()
 
     def _ReadNode(self):
         """Read properties from the image node"""
@@ -119,6 +124,14 @@ class Image:
         """
         raise ValueError("Image '%s': %s" % (self._node.path, msg))
 
+    def GetPath(self):
+        """Get the path of an image (in the FDT)
+
+        Returns:
+            Full path of the node for this image
+        """
+        return self._node.path
+
     def _ReadEntries(self):
         for node in self._node.subnodes:
             self._entries[node.name] = Entry.Create(self, node)
@@ -220,6 +233,11 @@ class Image:
         for entry in self._entries.values():
             entry.ProcessContents()
 
+    def WriteSymbols(self):
+        """Write symbol values into binary files for access at run time"""
+        for entry in self._entries.values():
+            entry.WriteSymbols(self)
+
     def BuildImage(self):
         """Write the image to a file"""
         fname = tools.GetOutputFilename(self._filename)
@@ -230,3 +248,58 @@ class Image:
                 data = entry.GetData()
                 fd.seek(self._pad_before + entry.pos - self._skip_at_start)
                 fd.write(data)
+
+    def LookupSymbol(self, sym_name, optional, msg):
+        """Look up a symbol in an ELF file
+
+        Looks up a symbol in an ELF file. Only entry types which come from an
+        ELF image can be used by this function.
+
+        At present the only entry property supported is pos.
+
+        Args:
+            sym_name: Symbol name in the ELF file to look up in the format
+                _binman_<entry>_prop_<property> where <entry> is the name of
+                the entry and <property> is the property to find (e.g.
+                _binman_u_boot_prop_pos). As a special case, you can append
+                _any to <entry> to have it search for any matching entry. E.g.
+                _binman_u_boot_any_prop_pos will match entries called u-boot,
+                u-boot-img and u-boot-nodtb)
+            optional: True if the symbol is optional. If False this function
+                will raise if the symbol is not found
+            msg: Message to display if an error occurs
+
+        Returns:
+            Value that should be assigned to that symbol, or None if it was
+                optional and not found
+
+        Raises:
+            ValueError if the symbol is invalid or not found, or references a
+                property which is not supported
+        """
+        m = re.match(r'^_binman_(\w+)_prop_(\w+)$', sym_name)
+        if not m:
+            raise ValueError("%s: Symbol '%s' has invalid format" %
+                             (msg, sym_name))
+        entry_name, prop_name = m.groups()
+        entry_name = entry_name.replace('_', '-')
+        entry = self._entries.get(entry_name)
+        if not entry:
+            if entry_name.endswith('-any'):
+                root = entry_name[:-4]
+                for name in self._entries:
+                    if name.startswith(root):
+                        rest = name[len(root):]
+                        if rest in ['', '-img', '-nodtb']:
+                            entry = self._entries[name]
+        if not entry:
+            err = ("%s: Entry '%s' not found in list (%s)" %
+                   (msg, entry_name, ','.join(self._entries.keys())))
+            if optional:
+                print('Warning: %s' % err, file=sys.stderr)
+                return None
+            raise ValueError(err)
+        if prop_name == 'pos':
+            return entry.pos
+        else:
+            raise ValueError("%s: No such property '%s'" % (msg, prop_name))
diff --git a/tools/binman/image_test.py b/tools/binman/image_test.py
new file mode 100644 (file)
index 0000000..1b50dda
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2017 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+# Test for the image module
+
+import unittest
+
+from image import Image
+from elf_test import capture_sys_output
+
+class TestImage(unittest.TestCase):
+    def testInvalidFormat(self):
+        image = Image('name', 'node', test=True)
+        with self.assertRaises(ValueError) as e:
+            image.LookupSymbol('_binman_something_prop_', False, 'msg')
+        self.assertIn(
+            "msg: Symbol '_binman_something_prop_' has invalid format",
+            str(e.exception))
+
+    def testMissingSymbol(self):
+        image = Image('name', 'node', test=True)
+        image._entries = {}
+        with self.assertRaises(ValueError) as e:
+            image.LookupSymbol('_binman_type_prop_pname', False, 'msg')
+        self.assertIn("msg: Entry 'type' not found in list ()",
+                      str(e.exception))
+
+    def testMissingSymbolOptional(self):
+        image = Image('name', 'node', test=True)
+        image._entries = {}
+        with capture_sys_output() as (stdout, stderr):
+            val = image.LookupSymbol('_binman_type_prop_pname', True, 'msg')
+        self.assertEqual(val, None)
+        self.assertEqual("Warning: msg: Entry 'type' not found in list ()\n",
+                         stderr.getvalue())
+        self.assertEqual('', stdout.getvalue())
+
+    def testBadProperty(self):
+        image = Image('name', 'node', test=True)
+        image._entries = {'u-boot': 1}
+        with self.assertRaises(ValueError) as e:
+            image.LookupSymbol('_binman_u_boot_prop_bad', False, 'msg')
+        self.assertIn("msg: No such property 'bad", str(e.exception))
index daf8385f6d55867582e3a704975887652dfa8d0b..bf39dc1b6f717397cac2ac98efb6f5375c1a2cec 100644 (file)
@@ -10,7 +10,7 @@
                };
 
                u-boot {
-                       pos = <12>;
+                       pos = <20>;
                };
        };
 };
index 9f4151c932b0fb1ea154386d3c6368066e5a60ce..43a7831341ca79e44d15ca040c0d3dccc49e0ee5 100644 (file)
@@ -7,11 +7,11 @@
        binman {
                sort-by-pos;
                u-boot {
-                       pos = <10>;
+                       pos = <22>;
                };
 
                u-boot-spl {
-                       pos = <5>;
+                       pos = <1>;
                };
        };
 };
index ff468c7d41d031aab7bc4a4ce7e0729cdfd2bc54..18d6bb5b8af5fc513828e633672f5c3578538239 100644 (file)
@@ -7,13 +7,13 @@
        binman {
                sort-by-pos;
                end-at-4gb;
-               size = <16>;
+               size = <32>;
                u-boot {
                        pos = <0>;
                };
 
                u-boot-spl {
-                       pos = <0xfffffff7>;
+                       pos = <0xffffffeb>;
                };
        };
 };
index 075ede36ab32e6c8b07a99b2bf0561cd5263861d..d49078e19e2dfa83de87fc23b82f42718aa55e06 100644 (file)
@@ -7,13 +7,13 @@
        binman {
                sort-by-pos;
                end-at-4gb;
-               size = <16>;
+               size = <32>;
                u-boot {
-                       pos = <0xfffffff0>;
+                       pos = <0xffffffe0>;
                };
 
                u-boot-spl {
-                       pos = <0xfffffff7>;
+                       pos = <0xffffffeb>;
                };
        };
 };
diff --git a/tools/binman/test/51_u_boot_spl_dtb.dts b/tools/binman/test/51_u_boot_spl_dtb.dts
new file mode 100644 (file)
index 0000000..3912f86
--- /dev/null
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               size = <16>;
+
+               u-boot-spl-dtb {
+               };
+       };
+};
diff --git a/tools/binman/test/52_u_boot_spl_nodtb.dts b/tools/binman/test/52_u_boot_spl_nodtb.dts
new file mode 100644 (file)
index 0000000..7f4e277
--- /dev/null
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u-boot-spl-nodtb {
+               };
+       };
+};
diff --git a/tools/binman/test/53_symbols.dts b/tools/binman/test/53_symbols.dts
new file mode 100644 (file)
index 0000000..980b066
--- /dev/null
@@ -0,0 +1,20 @@
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               pad-byte = <0xff>;
+               u-boot-spl {
+               };
+
+               u-boot {
+                       pos = <20>;
+               };
+
+               u-boot-spl2 {
+                       type = "u-boot-spl";
+               };
+       };
+};
index 217d13c666f1bbe24f71e5afb937519ef7f62b92..e58fc807757b3528acf7bfaef14266ed982d585d 100644 (file)
 CFLAGS := -march=i386 -m32 -nostdlib -I ../../../include
 
 LDS_UCODE := -T u_boot_ucode_ptr.lds
+LDS_BINMAN := -T u_boot_binman_syms.lds
+LDS_BINMAN_BAD := -T u_boot_binman_syms_bad.lds
 
-TARGETS = u_boot_ucode_ptr u_boot_no_ucode_ptr bss_data
+TARGETS = u_boot_ucode_ptr u_boot_no_ucode_ptr bss_data \
+       u_boot_binman_syms u_boot_binman_syms.bin u_boot_binman_syms_bad \
+       u_boot_binman_syms_size
 
 all: $(TARGETS)
 
@@ -24,6 +28,18 @@ u_boot_ucode_ptr: u_boot_ucode_ptr.c
 bss_data: CFLAGS += bss_data.lds
 bss_data: bss_data.c
 
+u_boot_binman_syms.bin: u_boot_binman_syms
+       objcopy -O binary $< -R .note.gnu.build-id $@
+
+u_boot_binman_syms: CFLAGS += $(LDS_BINMAN)
+u_boot_binman_syms: u_boot_binman_syms.c
+
+u_boot_binman_syms_bad: CFLAGS += $(LDS_BINMAN_BAD)
+u_boot_binman_syms_bad: u_boot_binman_syms_bad.c
+
+u_boot_binman_syms_size: CFLAGS += $(LDS_BINMAN)
+u_boot_binman_syms_size: u_boot_binman_syms_size.c
+
 clean:
        rm -f $(TARGETS)
 
index f865a9d9f6732e7a6dbb272fd9d649edf4fe3ab1..e0305c382c35665a0fd2f61702a5f8da240018c5 100644 (file)
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier:     GPL-2.0+
  *
  * Simple program to create a _dt_ucode_base_size symbol which can be read
- * by 'nm'. This is used by binman tests.
+ * by binutils. This is used by binman tests.
  */
 
 int bss_data[10];
diff --git a/tools/binman/test/u_boot_binman_syms b/tools/binman/test/u_boot_binman_syms
new file mode 100755 (executable)
index 0000000..2e02dc0
Binary files /dev/null and b/tools/binman/test/u_boot_binman_syms differ
diff --git a/tools/binman/test/u_boot_binman_syms.c b/tools/binman/test/u_boot_binman_syms.c
new file mode 100644 (file)
index 0000000..a975476
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * Simple program to create some binman symbols. This is used by binman tests.
+ */
+
+#define CONFIG_BINMAN
+#include <binman_sym.h>
+
+binman_sym_declare(unsigned long, u_boot_spl, pos);
+binman_sym_declare(unsigned long long, u_boot_spl2, pos);
+binman_sym_declare(unsigned long, u_boot_any, pos);
diff --git a/tools/binman/test/u_boot_binman_syms.lds b/tools/binman/test/u_boot_binman_syms.lds
new file mode 100644 (file)
index 0000000..d3130cd
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+       . = 0x00000000;
+       _start = .;
+
+       . = ALIGN(4);
+       .text :
+       {
+               __image_copy_start = .;
+               *(.text*)
+       }
+
+       . = ALIGN(4);
+       .binman_sym_table : {
+               __binman_sym_start = .;
+               KEEP(*(SORT(.binman_sym*)));
+               __binman_sym_end = .;
+       }
+
+}
diff --git a/tools/binman/test/u_boot_binman_syms_bad b/tools/binman/test/u_boot_binman_syms_bad
new file mode 100755 (executable)
index 0000000..8da3d9d
Binary files /dev/null and b/tools/binman/test/u_boot_binman_syms_bad differ
diff --git a/tools/binman/test/u_boot_binman_syms_bad.c b/tools/binman/test/u_boot_binman_syms_bad.c
new file mode 120000 (symlink)
index 0000000..939b2e9
--- /dev/null
@@ -0,0 +1 @@
+u_boot_binman_syms.c
\ No newline at end of file
diff --git a/tools/binman/test/u_boot_binman_syms_bad.lds b/tools/binman/test/u_boot_binman_syms_bad.lds
new file mode 100644 (file)
index 0000000..0b474b5
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+       . = 0x00000000;
+       _start = .;
+
+       . = ALIGN(4);
+       .text :
+       {
+               *(.text*)
+       }
+
+       . = ALIGN(4);
+       .binman_sym_table : {
+               __binman_sym_start = .;
+               KEEP(*(SORT(.binman_sym*)));
+               __binman_sym_end = .;
+       }
+
+}
diff --git a/tools/binman/test/u_boot_binman_syms_size b/tools/binman/test/u_boot_binman_syms_size
new file mode 100755 (executable)
index 0000000..d691e89
Binary files /dev/null and b/tools/binman/test/u_boot_binman_syms_size differ
diff --git a/tools/binman/test/u_boot_binman_syms_size.c b/tools/binman/test/u_boot_binman_syms_size.c
new file mode 100644 (file)
index 0000000..ee4c048
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * Simple program to create some binman symbols. This is used by binman tests.
+ */
+
+#define CONFIG_BINMAN
+#include <binman_sym.h>
+
+binman_sym_declare(char, u_boot_spl, pos);
index 24f349fb9e424c84ea3188b385e07bb8a833b60d..734d54f0d419576bb32739d2041d3e268c2c1f78 100644 (file)
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier:     GPL-2.0+
  *
  * Simple program to create a _dt_ucode_base_size symbol which can be read
- * by 'nm'. This is used by binman tests.
+ * by binutils. This is used by binman tests.
  */
 
 static unsigned long _dt_ucode_base_size[2]