Merge branch 'master' of git://git.denx.de/u-boot-spi
authorTom Rini <trini@konsulko.com>
Sat, 4 Aug 2018 23:41:43 +0000 (19:41 -0400)
committerTom Rini <trini@konsulko.com>
Sat, 4 Aug 2018 23:41:43 +0000 (19:41 -0400)
180 files changed:
.mailmap
Kconfig
arch/arm/cpu/armv8/Kconfig
arch/arm/cpu/armv8/Makefile
arch/arm/cpu/armv8/exceptions.S
arch/arm/cpu/armv8/start.S
arch/arm/dts/Makefile
arch/arm/dts/stm32429i-eval.dts
arch/arm/dts/sun50i-h6-orangepi-one-plus.dts [new file with mode: 0644]
arch/arm/dts/sun50i-h6-pine-h64.dts [new file with mode: 0644]
arch/arm/dts/sun50i-h6.dtsi [new file with mode: 0644]
arch/arm/dts/sunxi-u-boot.dtsi
arch/arm/dts/tegra-u-boot.dtsi
arch/arm/include/asm/arch-sunxi/boot0.h
arch/arm/include/asm/arch-sunxi/clock.h
arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h [new file with mode: 0644]
arch/arm/include/asm/arch-sunxi/cpu.h
arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h [new file with mode: 0644]
arch/arm/include/asm/arch-sunxi/dram.h
arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h [new file with mode: 0644]
arch/arm/include/asm/arch-sunxi/gpio.h
arch/arm/include/asm/arch-sunxi/mmc.h
arch/arm/include/asm/arch-sunxi/spl.h
arch/arm/include/asm/arch-sunxi/timer.h
arch/arm/mach-sunxi/Kconfig
arch/arm/mach-sunxi/Makefile
arch/arm/mach-sunxi/board.c
arch/arm/mach-sunxi/clock_sun50i_h6.c [new file with mode: 0644]
arch/arm/mach-sunxi/cpu_info.c
arch/arm/mach-sunxi/dram_sun50i_h6.c [new file with mode: 0644]
arch/arm/mach-sunxi/rmr_switch.S
arch/sandbox/include/asm/clk.h
arch/x86/dts/u-boot.dtsi
board/sunxi/MAINTAINERS
board/sunxi/board.c
board/sunxi/mksunxi_fit_atf.sh
board/ti/am335x/board.c
board/ti/am335x/board.h
board/ti/am335x/mux.c
common/spl/Kconfig
common/spl/spl.c
common/spl/spl_ram.c
configs/bananapi_m2_berry_defconfig
configs/orangepi_one_plus_defconfig [new file with mode: 0644]
configs/pine_h64_defconfig [new file with mode: 0644]
configs/stm32f429-evaluation_defconfig
configs/stm32f469-discovery_defconfig
configs/stm32f746-disco_defconfig
configs/stm32mp15_basic_defconfig
doc/device-tree-bindings/adc/st,stm32-adc.txt [new file with mode: 0644]
drivers/adc/Kconfig
drivers/adc/Makefile
drivers/adc/adc-uclass.c
drivers/adc/stm32-adc-core.c [new file with mode: 0644]
drivers/adc/stm32-adc-core.h [new file with mode: 0644]
drivers/adc/stm32-adc.c [new file with mode: 0644]
drivers/bootcount/bootcount.c
drivers/clk/clk-uclass.c
drivers/clk/clk_sandbox_test.c
drivers/mmc/arm_pl180_mmci.c
drivers/mmc/arm_pl180_mmci.h
drivers/mmc/sunxi_mmc.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/sunxi_nand.c
drivers/phy/allwinner/phy-sun4i-usb.c
drivers/video/sunxi/sunxi_de2.c
include/clk.h
include/configs/am335x_evm.h
include/configs/omap3_cairo.h
include/configs/omap3_logic.h
include/configs/sun4i.h
include/configs/sun50i.h
include/configs/sun5i.h
include/configs/sun6i.h
include/configs/sun7i.h
include/configs/sun8i.h
include/configs/sunxi-common.h
include/configs/ti_omap3_common.h
include/dt-bindings/clock/sun50i-h6-ccu.h [new file with mode: 0644]
include/dt-bindings/clock/sun50i-h6-r-ccu.h [new file with mode: 0644]
include/dt-bindings/reset/sun50i-h6-ccu.h [new file with mode: 0644]
include/dt-bindings/reset/sun50i-h6-r-ccu.h [new file with mode: 0644]
include/spl.h
scripts/.gitignore
scripts/Makefile
scripts/config_whitelist.txt
scripts/docproc.c [deleted file]
test/dm/clk.c
tools/binman/README
tools/binman/README.entries [new file with mode: 0644]
tools/binman/binman.py
tools/binman/bsection.py
tools/binman/cmdline.py
tools/binman/control.py
tools/binman/elf.py
tools/binman/elf_test.py
tools/binman/entry.py
tools/binman/etype/_testing.py
tools/binman/etype/blob.py
tools/binman/etype/blob_named_by_arg.py [new file with mode: 0644]
tools/binman/etype/cros_ec_rw.py [new file with mode: 0644]
tools/binman/etype/fill.py [new file with mode: 0644]
tools/binman/etype/fmap.py [new file with mode: 0644]
tools/binman/etype/gbb.py [new file with mode: 0644]
tools/binman/etype/intel_cmc.py
tools/binman/etype/intel_descriptor.py
tools/binman/etype/intel_fsp.py
tools/binman/etype/intel_me.py
tools/binman/etype/intel_mrc.py
tools/binman/etype/intel_vbt.py
tools/binman/etype/intel_vga.py
tools/binman/etype/section.py
tools/binman/etype/text.py [new file with mode: 0644]
tools/binman/etype/u_boot.py
tools/binman/etype/u_boot_dtb.py
tools/binman/etype/u_boot_dtb_with_ucode.py
tools/binman/etype/u_boot_img.py
tools/binman/etype/u_boot_nodtb.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
tools/binman/etype/u_boot_spl_nodtb.py
tools/binman/etype/u_boot_tpl.py [new file with mode: 0644]
tools/binman/etype/u_boot_tpl_dtb.py [new file with mode: 0644]
tools/binman/etype/u_boot_ucode.py
tools/binman/etype/u_boot_with_ucode_ptr.py
tools/binman/etype/vblock.py [new file with mode: 0644]
tools/binman/etype/x86_start16.py
tools/binman/etype/x86_start16_spl.py
tools/binman/fmap_util.py [new file with mode: 0644]
tools/binman/ftest.py
tools/binman/image.py
tools/binman/test/08_pack.dts
tools/binman/test/12_pack_inv_align.dts
tools/binman/test/14_pack_overlap.dts
tools/binman/test/21_image_pad.dts
tools/binman/test/24_sorted.dts
tools/binman/test/25_pack_zero_size.dts
tools/binman/test/27_pack_4gb_no_size.dts
tools/binman/test/28_pack_4gb_outside.dts
tools/binman/test/29_x86-rom.dts
tools/binman/test/30_x86-rom-me-no-desc.dts
tools/binman/test/31_x86-rom-me.dts
tools/binman/test/34_x86_ucode.dts
tools/binman/test/35_x86_single_ucode.dts
tools/binman/test/37_x86_no_ucode.dts
tools/binman/test/38_x86_ucode_missing_node.dts
tools/binman/test/39_x86_ucode_missing_node2.dts
tools/binman/test/40_x86_ucode_not_in_image.dts
tools/binman/test/44_x86_optional_ucode.dts
tools/binman/test/45_prop_test.dts
tools/binman/test/49_x86_ucode_spl.dts
tools/binman/test/53_symbols.dts
tools/binman/test/55_sections.dts
tools/binman/test/58_x86_ucode_spl_needs_retry.dts
tools/binman/test/62_entry_args.dts [new file with mode: 0644]
tools/binman/test/63_entry_args_missing.dts [new file with mode: 0644]
tools/binman/test/64_entry_args_required.dts [new file with mode: 0644]
tools/binman/test/65_entry_args_unknown_datatype.dts [new file with mode: 0644]
tools/binman/test/66_text.dts [new file with mode: 0644]
tools/binman/test/67_fmap.dts [new file with mode: 0644]
tools/binman/test/68_blob_named_by_arg.dts [new file with mode: 0644]
tools/binman/test/69_fill.dts [new file with mode: 0644]
tools/binman/test/70_fill_no_size.dts [new file with mode: 0644]
tools/binman/test/71_gbb.dts [new file with mode: 0644]
tools/binman/test/72_gbb_too_small.dts [new file with mode: 0644]
tools/binman/test/73_gbb_no_size.dts [new file with mode: 0644]
tools/binman/test/74_vblock.dts [new file with mode: 0644]
tools/binman/test/75_vblock_no_content.dts [new file with mode: 0644]
tools/binman/test/76_vblock_bad_phandle.dts [new file with mode: 0644]
tools/binman/test/77_vblock_bad_entry.dts [new file with mode: 0644]
tools/binman/test/78_u_boot_tpl.dts [new file with mode: 0644]
tools/binman/test/79_uses_pos.dts [new file with mode: 0644]
tools/binman/test/u_boot_binman_syms
tools/binman/test/u_boot_binman_syms.c
tools/dtoc/fdt.py
tools/dtoc/fdt_util.py
tools/dtoc/test_fdt.py
tools/patman/command.py
tools/patman/tools.py

index d29703058dbefe92afd65a2bdda4813dc97a5414..1bee048d1349268e51f5c915ae56425cbc013bdc 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -34,4 +34,5 @@ Wolfgang Denk <wdenk>
 York Sun <yorksun@freescale.com>
 York Sun <york.sun@nxp.com>
 Łukasz Majewski <l.majewski@samsung.com>
+Lukasz Majewski <lukma@denx.de>
 Mirza <Taimoor_Mirza@mentor.com>
diff --git a/Kconfig b/Kconfig
index 62235cae96cf852d5cabfcbc054c3a5fbed71ceb..7dc7798df4e104025a653b549b5d7ee996cedd18 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -137,24 +137,24 @@ config SYS_MALLOC_F_LEN
          initial serial device and any others that are needed.
 
 config SPL_SYS_MALLOC_F_LEN
-        hex "Size of malloc() pool in SPL before relocation"
-        depends on SYS_MALLOC_F
-        default SYS_MALLOC_F_LEN
-        help
-          Before relocation, memory is very limited on many platforms. Still,
-          we can provide a small malloc() pool if needed. Driver model in
-          particular needs this to operate, so that it can allocate the
-          initial serial device and any others that are needed.
+       hex "Size of malloc() pool in SPL before relocation"
+       depends on SYS_MALLOC_F
+       default SYS_MALLOC_F_LEN
+       help
+         Before relocation, memory is very limited on many platforms. Still,
+         we can provide a small malloc() pool if needed. Driver model in
+         particular needs this to operate, so that it can allocate the
+         initial serial device and any others that are needed.
 
 config TPL_SYS_MALLOC_F_LEN
-        hex "Size of malloc() pool in TPL before relocation"
-        depends on SYS_MALLOC_F
-        default SYS_MALLOC_F_LEN
-        help
-          Before relocation, memory is very limited on many platforms. Still,
-          we can provide a small malloc() pool if needed. Driver model in
-          particular needs this to operate, so that it can allocate the
-          initial serial device and any others that are needed.
+       hex "Size of malloc() pool in TPL before relocation"
+       depends on SYS_MALLOC_F
+       default SYS_MALLOC_F_LEN
+       help
+         Before relocation, memory is very limited on many platforms. Still,
+         we can provide a small malloc() pool if needed. Driver model in
+         particular needs this to operate, so that it can allocate the
+         initial serial device and any others that are needed.
 
 menuconfig EXPERT
        bool "Configure standard U-Boot features (expert users)"
index 741e15c773786eaef6b639c7d587ca262ddb6bea..c8bebabdf6f44f00258c5da8095d6df16d50d999 100644 (file)
@@ -1,5 +1,16 @@
 if ARM64
 
+config ARMV8_SPL_EXCEPTION_VECTORS
+       bool "Install crash dump exception vectors"
+       depends on SPL
+       default y
+       help
+         The default exception vector table is only used for the crash
+         dump, but still takes quite a lot of space in the image size.
+
+         Say N here if you are running out of code space in the image
+         and want to save some space at the cost of less debugging info.
+
 config ARMV8_MULTIENTRY
         bool "Enable multiple CPUs to enter into U-Boot"
 
index d1d4ffecfd22955dc5de3fbb4bd7f0e431788bb1..52c8daa049621f53c4a05f503f21235e6d2b8b22 100644 (file)
@@ -10,7 +10,11 @@ ifndef CONFIG_$(SPL_TPL_)TIMER
 obj-$(CONFIG_SYS_ARCH_TIMER) += generic_timer.o
 endif
 obj-y  += cache_v8.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) += exceptions.o
+else
 obj-y  += exceptions.o
+endif
 obj-y  += cache.o
 obj-y  += tlb.o
 obj-y  += transition.o
index 1a78a5d1dcc7e577fe23edccc926d6878fbe9fe2..a15af72e023ad1decd6936210d474a197e27738c 100644 (file)
 #include <linux/linkage.h>
 
 /*
- * Exception vectors.
+ * AArch64 exception vectors:
+ * We have four types of exceptions:
+ * - synchronous: traps, data aborts, undefined instructions, ...
+ * - IRQ: group 1 (normal) interrupts
+ * - FIQ: group 0 or secure interrupts
+ * - SError: fatal system errors
+ * There are entries for all four of those for different contexts:
+ * - from same exception level, when using the SP_EL0 stack pointer
+ * - from same exception level, when using the SP_ELx stack pointer
+ * - from lower exception level, when this is AArch64
+ * - from lower exception level, when this is AArch32
+ * Each of those 16 entries have space for 32 instructions, each entry must
+ * be 128 byte aligned, the whole table must be 2K aligned.
+ * The 32 instructions are not enough to save and restore all registers and
+ * to branch to the actual handler, so we split this up:
+ * Each entry saves the LR, branches to the save routine, then to the actual
+ * handler, then to the restore routine. The save and restore routines are
+ * each split in half and stuffed in the unused gap between the entries.
+ * Also as we do not run anything in a lower exception level, we just provide
+ * the first 8 entries for exceptions from the same EL.
  */
        .align  11
        .globl  vectors
@@ -22,52 +41,9 @@ vectors:
        bl      do_bad_sync
        b       exception_exit
 
-       .align  7               /* Current EL IRQ Thread */
-       stp     x29, x30, [sp, #-16]!
-       bl      _exception_entry
-       bl      do_bad_irq
-       b       exception_exit
-
-       .align  7               /* Current EL FIQ Thread */
-       stp     x29, x30, [sp, #-16]!
-       bl      _exception_entry
-       bl      do_bad_fiq
-       b       exception_exit
-
-       .align  7               /* Current EL Error Thread */
-       stp     x29, x30, [sp, #-16]!
-       bl      _exception_entry
-       bl      do_bad_error
-       b       exception_exit
-
-       .align  7                /* Current EL Synchronous Handler */
-       stp     x29, x30, [sp, #-16]!
-       bl      _exception_entry
-       bl      do_sync
-       b       exception_exit
-
-       .align  7                /* Current EL IRQ Handler */
-       stp     x29, x30, [sp, #-16]!
-       bl      _exception_entry
-       bl      do_irq
-       b       exception_exit
-
-       .align  7                /* Current EL FIQ Handler */
-       stp     x29, x30, [sp, #-16]!
-       bl      _exception_entry
-       bl      do_fiq
-       b       exception_exit
-
-       .align  7                /* Current EL Error Handler */
-       stp     x29, x30, [sp, #-16]!
-       bl      _exception_entry
-       bl      do_error
-       b       exception_exit
-
 /*
- * Enter Exception.
- * This will save the processor state that is ELR/X0~X30
- * to the stack frame.
+ * Save (most of) the GP registers to the stack frame.
+ * This is the first part of the shared routine called into from all entries.
  */
 _exception_entry:
        stp     x27, x28, [sp, #-16]!
@@ -84,7 +60,19 @@ _exception_entry:
        stp     x5, x6, [sp, #-16]!
        stp     x3, x4, [sp, #-16]!
        stp     x1, x2, [sp, #-16]!
+       b       _save_el_regs                   /* jump to the second part */
 
+       .align  7               /* Current EL IRQ Thread */
+       stp     x29, x30, [sp, #-16]!
+       bl      _exception_entry
+       bl      do_bad_irq
+       b       exception_exit
+
+/*
+ * Save exception specific context: ESR and ELR, for all exception levels.
+ * This is the second part of the shared routine called into from all entries.
+ */
+_save_el_regs:
        /* Could be running at EL3/EL2/EL1 */
        switch_el x11, 3f, 2f, 1f
 3:     mrs     x1, esr_el3
@@ -100,16 +88,36 @@ _exception_entry:
        mov     x0, sp
        ret
 
-
+       .align  7               /* Current EL FIQ Thread */
+       stp     x29, x30, [sp, #-16]!
+       bl      _exception_entry
+       bl      do_bad_fiq
+                               /* falling through to _exception_exit */
+/*
+ * Restore the exception return address, for all exception levels.
+ * This is the first part of the shared routine called into from all entries.
+ */
 exception_exit:
        ldp     x2, x0, [sp],#16
        switch_el x11, 3f, 2f, 1f
 3:     msr     elr_el3, x2
-       b       0f
+       b       _restore_regs
 2:     msr     elr_el2, x2
-       b       0f
+       b       _restore_regs
 1:     msr     elr_el1, x2
-0:
+       b       _restore_regs           /* jump to the second part */
+
+       .align  7               /* Current EL Error Thread */
+       stp     x29, x30, [sp, #-16]!
+       bl      _exception_entry
+       bl      do_bad_error
+       b       exception_exit
+
+/*
+ * Restore the general purpose registers from the exception stack, then return.
+ * This is the second part of the shared routine called into from all entries.
+ */
+_restore_regs:
        ldp     x1, x2, [sp],#16
        ldp     x3, x4, [sp],#16
        ldp     x5, x6, [sp],#16
@@ -126,3 +134,27 @@ exception_exit:
        ldp     x27, x28, [sp],#16
        ldp     x29, x30, [sp],#16
        eret
+
+       .align  7                /* Current EL (SP_ELx) Synchronous Handler */
+       stp     x29, x30, [sp, #-16]!
+       bl      _exception_entry
+       bl      do_sync
+       b       exception_exit
+
+       .align  7                /* Current EL (SP_ELx) IRQ Handler */
+       stp     x29, x30, [sp, #-16]!
+       bl      _exception_entry
+       bl      do_irq
+       b       exception_exit
+
+       .align  7                /* Current EL (SP_ELx) FIQ Handler */
+       stp     x29, x30, [sp, #-16]!
+       bl      _exception_entry
+       bl      do_fiq
+       b       exception_exit
+
+       .align  7                /* Current EL (SP_ELx) Error Handler */
+       stp     x29, x30, [sp, #-16]!
+       bl      _exception_entry
+       bl      do_error
+       b       exception_exit
index d4db4d044f6414cd8bae121a75fffce4a3b880fc..12a78ee38b41e629a2af5b5aac8cf3351f9a2fbb 100644 (file)
@@ -86,14 +86,23 @@ pie_fixup_done:
 
 #ifdef CONFIG_SYS_RESET_SCTRL
        bl reset_sctrl
+#endif
+
+#if defined(CONFIG_ARMV8__SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
+.macro set_vbar, regname, reg
+       msr     \regname, \reg
+.endm
+       adr     x0, vectors
+#else
+.macro set_vbar, regname, reg
+.endm
 #endif
        /*
         * Could be EL3/EL2/EL1, Initial State:
         * Little Endian, MMU Disabled, i/dCache Disabled
         */
-       adr     x0, vectors
        switch_el x1, 3f, 2f, 1f
-3:     msr     vbar_el3, x0
+3:     set_vbar vbar_el3, x0
        mrs     x0, scr_el3
        orr     x0, x0, #0xf                    /* SCR_EL3.NS|IRQ|FIQ|EA */
        msr     scr_el3, x0
@@ -103,11 +112,11 @@ pie_fixup_done:
        msr     cntfrq_el0, x0                  /* Initialize CNTFRQ */
 #endif
        b       0f
-2:     msr     vbar_el2, x0
+2:     set_vbar        vbar_el2, x0
        mov     x0, #0x33ff
        msr     cptr_el2, x0                    /* Enable FP/SIMD */
        b       0f
-1:     msr     vbar_el1, x0
+1:     set_vbar        vbar_el1, x0
        mov     x0, #3 << 20
        msr     cpacr_el1, x0                   /* Enable FP/SIMD */
 0:
@@ -345,6 +354,7 @@ ENDPROC(smp_kick_all_cpus)
 /*-----------------------------------------------------------------------*/
 
 ENTRY(c_runtime_cpu_setup)
+#if defined(CONFIG_ARMV8__SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
        /* Relocate vBAR */
        adr     x0, vectors
        switch_el x1, 3f, 2f, 1f
@@ -354,6 +364,7 @@ ENTRY(c_runtime_cpu_setup)
        b       0f
 1:     msr     vbar_el1, x0
 0:
+#endif
 
        ret
 ENDPROC(c_runtime_cpu_setup)
index 09adf5eab1da8d687e4cb0a8252ed2b13c15b3c8..89032bb5450222a83a16bae94ac044f83ad111c8 100644 (file)
@@ -390,6 +390,9 @@ dtb-$(CONFIG_MACH_SUN50I_H5) += \
        sun50i-h5-orangepi-pc2.dtb \
        sun50i-h5-orangepi-prime.dtb \
        sun50i-h5-orangepi-zero-plus2.dtb
+dtb-$(CONFIG_MACH_SUN50I_H6) += \
+       sun50i-h6-orangepi-one-plus.dtb \
+       sun50i-h6-pine-h64.dtb
 dtb-$(CONFIG_MACH_SUN50I) += \
        sun50i-a64-amarula-relic.dtb \
        sun50i-a64-bananapi-m64.dtb \
index c16594b7e43371182c1bd40187806ae0b841f736..f6753a4d1a1cb67266a44650238d9ef70dbe9c72 100644 (file)
 &sdio {
        status = "okay";
        vmmc-supply = <&mmc_vcard>;
-       cd-gpios = <&stmpegpio 15 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&stmpegpio 15 GPIO_ACTIVE_LOW>;
        pinctrl-names = "default", "opendrain";
        pinctrl-0 = <&sdio_pins>;
        pinctrl-1 = <&sdio_pins_od>;
diff --git a/arch/arm/dts/sun50i-h6-orangepi-one-plus.dts b/arch/arm/dts/sun50i-h6-orangepi-one-plus.dts
new file mode 100644 (file)
index 0000000..0612c19
--- /dev/null
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-h6.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "OrangePi One Plus";
+       compatible = "xunlong,orangepi-one-plus", "allwinner,sun50i-h6";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+};
+
+&mmc0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc0_pins>;
+       vmmc-supply = <&reg_cldo1>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&r_i2c {
+       status = "okay";
+
+       axp805: pmic@36 {
+               compatible = "x-powers,axp805", "x-powers,axp806";
+               reg = <0x36>;
+               interrupt-parent = <&r_intc>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               x-powers,self-working-mode;
+
+               regulators {
+                       reg_aldo1: aldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-pl";
+                       };
+
+                       reg_aldo2: aldo2 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-ac200";
+                       };
+
+                       reg_aldo3: aldo3 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc25-dram";
+                       };
+
+                       reg_bldo1: bldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-bias-pll";
+                       };
+
+                       reg_bldo2: bldo2 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-efuse-pcie-hdmi-io";
+                       };
+
+                       reg_bldo3: bldo3 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-dcxoio";
+                       };
+
+                       bldo4 {
+                               /* unused */
+                       };
+
+                       reg_cldo1: cldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-3v3";
+                       };
+
+                       reg_cldo2: cldo2 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-wifi-1";
+                       };
+
+                       reg_cldo3: cldo3 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-wifi-2";
+                       };
+
+                       reg_dcdca: dcdca {
+                               regulator-always-on;
+                               regulator-min-microvolt = <810000>;
+                               regulator-max-microvolt = <1080000>;
+                               regulator-name = "vdd-cpu";
+                       };
+
+                       reg_dcdcc: dcdcc {
+                               regulator-min-microvolt = <810000>;
+                               regulator-max-microvolt = <1080000>;
+                               regulator-name = "vdd-gpu";
+                       };
+
+                       reg_dcdcd: dcdcd {
+                               regulator-always-on;
+                               regulator-min-microvolt = <960000>;
+                               regulator-max-microvolt = <960000>;
+                               regulator-name = "vdd-sys";
+                       };
+
+                       reg_dcdce: dcdce {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-name = "vcc-dram";
+                       };
+
+                       sw {
+                               /* unused */
+                       };
+               };
+       };
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_ph_pins>;
+       status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-h6-pine-h64.dts b/arch/arm/dts/sun50i-h6-pine-h64.dts
new file mode 100644 (file)
index 0000000..ceffc40
--- /dev/null
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+/dts-v1/;
+
+#include "sun50i-h6.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "Pine H64";
+       compatible = "pine64,pine-h64", "allwinner,sun50i-h6";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               heartbeat {
+                       label = "pine-h64:green:heartbeat";
+                       gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */
+               };
+
+               link {
+                       label = "pine-h64:white:link";
+                       gpios = <&r_pio 0 3 GPIO_ACTIVE_HIGH>; /* PL3 */
+               };
+
+               status {
+                       label = "pine-h64:blue:status";
+                       gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
+               };
+       };
+};
+
+&mmc0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc0_pins>;
+       vmmc-supply = <&reg_cldo1>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&reg_cldo1>;
+       vqmmc-supply = <&reg_bldo2>;
+       non-removable;
+       cap-mmc-hw-reset;
+       status = "okay";
+};
+
+&r_i2c {
+       status = "okay";
+
+       axp805: pmic@36 {
+               compatible = "x-powers,axp805", "x-powers,axp806";
+               reg = <0x36>;
+               interrupt-parent = <&r_intc>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               x-powers,self-working-mode;
+
+               regulators {
+                       reg_aldo1: aldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-pl";
+                       };
+
+                       reg_aldo2: aldo2 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-ac200";
+                       };
+
+                       reg_aldo3: aldo3 {
+                               /* This regulator is connected with CLDO1 */
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-3v3-1";
+                       };
+
+                       reg_bldo1: bldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-bias-pll";
+                       };
+
+                       reg_bldo2: bldo2 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-efuse-pcie-hdmi-io";
+                       };
+
+                       reg_bldo3: bldo3 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-dcxoio";
+                       };
+
+                       bldo4 {
+                               /* unused */
+                       };
+
+                       reg_cldo1: cldo1 {
+                               /* This regulator is connected with ALDO3 */
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-3v3-2";
+                       };
+
+                       reg_cldo2: cldo2 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-wifi-1";
+                       };
+
+                       reg_cldo3: cldo3 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-wifi-2";
+                       };
+
+                       reg_dcdca: dcdca {
+                               regulator-always-on;
+                               regulator-min-microvolt = <810000>;
+                               regulator-max-microvolt = <1080000>;
+                               regulator-name = "vdd-cpu";
+                       };
+
+                       reg_dcdcc: dcdcc {
+                               regulator-min-microvolt = <810000>;
+                               regulator-max-microvolt = <1080000>;
+                               regulator-name = "vdd-gpu";
+                       };
+
+                       reg_dcdcd: dcdcd {
+                               regulator-always-on;
+                               regulator-min-microvolt = <960000>;
+                               regulator-max-microvolt = <960000>;
+                               regulator-name = "vdd-sys";
+                       };
+
+                       reg_dcdce: dcdce {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-name = "vcc-dram";
+                       };
+
+                       sw {
+                               /* unused */
+                       };
+               };
+       };
+
+       pcf8563: rtc@51 {
+               compatible = "nxp,pcf8563";
+               reg = <0x51>;
+               #clock-cells = <0>;
+       };
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_ph_pins>;
+       status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-h6.dtsi b/arch/arm/dts/sun50i-h6.dtsi
new file mode 100644 (file)
index 0000000..cfa5fff
--- /dev/null
@@ -0,0 +1,288 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun50i-h6-ccu.h>
+#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
+
+/ {
+       interrupt-parent = <&gic>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <0>;
+                       enable-method = "psci";
+               };
+
+               cpu1: cpu@1 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <1>;
+                       enable-method = "psci";
+               };
+
+               cpu2: cpu@2 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <2>;
+                       enable-method = "psci";
+               };
+
+               cpu3: cpu@3 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <3>;
+                       enable-method = "psci";
+               };
+       };
+
+       iosc: internal-osc-clk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <16000000>;
+               clock-accuracy = <300000000>;
+               clock-output-names = "iosc";
+       };
+
+       osc24M: osc24M_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <24000000>;
+               clock-output-names = "osc24M";
+       };
+
+       osc32k: osc32k_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+               clock-output-names = "osc32k";
+       };
+
+       psci {
+               compatible = "arm,psci-0.2";
+               method = "smc";
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13
+                       (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 14
+                       (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 11
+                       (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 10
+                       (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               ccu: clock@3001000 {
+                       compatible = "allwinner,sun50i-h6-ccu";
+                       reg = <0x03001000 0x1000>;
+                       clocks = <&osc24M>, <&osc32k>, <&iosc>;
+                       clock-names = "hosc", "losc", "iosc";
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
+               gic: interrupt-controller@3021000 {
+                       compatible = "arm,gic-400";
+                       reg = <0x03021000 0x1000>,
+                             <0x03022000 0x2000>,
+                             <0x03024000 0x2000>,
+                             <0x03026000 0x2000>;
+                       interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+               };
+
+               pio: pinctrl@300b000 {
+                       compatible = "allwinner,sun50i-h6-pinctrl";
+                       reg = <0x0300b000 0x400>;
+                       interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_APB1>, <&osc24M>, <&osc32k>;
+                       clock-names = "apb", "hosc", "losc";
+                       gpio-controller;
+                       #gpio-cells = <3>;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+
+                       mmc0_pins: mmc0-pins {
+                               pins = "PF0", "PF1", "PF2", "PF3",
+                                      "PF4", "PF5";
+                               function = "mmc0";
+                               drive-strength = <30>;
+                               bias-pull-up;
+                       };
+
+                       mmc2_pins: mmc2-pins {
+                               pins = "PC1", "PC4", "PC5", "PC6",
+                                      "PC7", "PC8", "PC9", "PC10",
+                                      "PC11", "PC12", "PC13", "PC14";
+                               function = "mmc2";
+                               drive-strength = <30>;
+                               bias-pull-up;
+                       };
+
+                       uart0_ph_pins: uart0-ph {
+                               pins = "PH0", "PH1";
+                               function = "uart0";
+                       };
+               };
+
+               mmc0: mmc@4020000 {
+                       compatible = "allwinner,sun50i-h6-mmc",
+                                    "allwinner,sun50i-a64-mmc";
+                       reg = <0x04020000 0x1000>;
+                       clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+                       clock-names = "ahb", "mmc";
+                       resets = <&ccu RST_BUS_MMC0>;
+                       reset-names = "ahb";
+                       interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               mmc1: mmc@4021000 {
+                       compatible = "allwinner,sun50i-h6-mmc",
+                                    "allwinner,sun50i-a64-mmc";
+                       reg = <0x04021000 0x1000>;
+                       clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+                       clock-names = "ahb", "mmc";
+                       resets = <&ccu RST_BUS_MMC1>;
+                       reset-names = "ahb";
+                       interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               mmc2: mmc@4022000 {
+                       compatible = "allwinner,sun50i-h6-emmc",
+                                    "allwinner,sun50i-a64-emmc";
+                       reg = <0x04022000 0x1000>;
+                       clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+                       clock-names = "ahb", "mmc";
+                       resets = <&ccu RST_BUS_MMC2>;
+                       reset-names = "ahb";
+                       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               uart0: serial@5000000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x05000000 0x400>;
+                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART0>;
+                       resets = <&ccu RST_BUS_UART0>;
+                       status = "disabled";
+               };
+
+               uart1: serial@5000400 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x05000400 0x400>;
+                       interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART1>;
+                       resets = <&ccu RST_BUS_UART1>;
+                       status = "disabled";
+               };
+
+               uart2: serial@5000800 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x05000800 0x400>;
+                       interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART2>;
+                       resets = <&ccu RST_BUS_UART2>;
+                       status = "disabled";
+               };
+
+               uart3: serial@5000c00 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x05000c00 0x400>;
+                       interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART3>;
+                       resets = <&ccu RST_BUS_UART3>;
+                       status = "disabled";
+               };
+
+               r_ccu: clock@7010000 {
+                       compatible = "allwinner,sun50i-h6-r-ccu";
+                       reg = <0x07010000 0x400>;
+                       clocks = <&osc24M>, <&osc32k>, <&iosc>,
+                                <&ccu CLK_PLL_PERIPH0>;
+                       clock-names = "hosc", "losc", "iosc", "pll-periph";
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
+               r_intc: interrupt-controller@7021000 {
+                       compatible = "allwinner,sun50i-h6-r-intc",
+                                    "allwinner,sun6i-a31-r-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       reg = <0x07021000 0x400>;
+                       interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               r_pio: pinctrl@7022000 {
+                       compatible = "allwinner,sun50i-h6-r-pinctrl";
+                       reg = <0x07022000 0x400>;
+                       interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&osc32k>;
+                       clock-names = "apb", "hosc", "losc";
+                       gpio-controller;
+                       #gpio-cells = <3>;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+
+                       r_i2c_pins: r-i2c {
+                               pins = "PL0", "PL1";
+                               function = "s_i2c";
+                       };
+               };
+
+               r_i2c: i2c@7081400 {
+                       compatible = "allwinner,sun6i-a31-i2c";
+                       reg = <0x07081400 0x400>;
+                       interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&r_ccu CLK_R_APB2_I2C>;
+                       resets = <&r_ccu RST_R_APB2_I2C>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&r_i2c_pins>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+       };
+};
index 5adfd9bca2ec1ffa8ff8360f02d51071948009a3..8a9f2a6417daae05b7e192be39801db3151de0b6 100644 (file)
@@ -8,7 +8,7 @@
                        filename = "spl/sunxi-spl.bin";
                };
                u-boot-img {
-                       pos = <CONFIG_SPL_PAD_TO>;
+                       offset = <CONFIG_SPL_PAD_TO>;
                };
        };
 };
index 4f692ee975729295ec638b7751e4ca2b2d573b4c..fe19619919ec54446cacea103afb8b7c6aa4ace8 100644 (file)
@@ -15,7 +15,7 @@
                        u-boot-spl {
                        };
                        u-boot {
-                               pos = <(U_BOOT_OFFSET)>;
+                               offset = <(U_BOOT_OFFSET)>;
                        };
                };
 
@@ -26,7 +26,7 @@
                        u-boot-spl {
                        };
                        u-boot {
-                               pos = <(U_BOOT_OFFSET)>;
+                               offset = <(U_BOOT_OFFSET)>;
                        };
                };
 
@@ -36,7 +36,7 @@
                        u-boot-spl {
                        };
                        u-boot-nodtb {
-                               pos = <(U_BOOT_OFFSET)>;
+                               offset = <(U_BOOT_OFFSET)>;
                        };
                };
        };
index c826fec415239c69b2e972ad041b26e1d33bc7da..54c144afd8cb60af035fb8998859b151db3ade84 100644 (file)
        .word   0xf57ff06f      // isb     sy
        .word   0xe320f003      // wfi
        .word   0xeafffffd      // b       @wfi
+#ifndef CONFIG_MACH_SUN50I_H6
        .word   0x017000a0      // writeable RVBAR mapping address
+#else
+       .word   0x09010040      // writeable RVBAR mapping address
+#endif
 #ifdef CONFIG_SPL_BUILD
        .word   CONFIG_SPL_TEXT_BASE
 #else
index 46c3eed377fcf519e4cbb697cd7ddf04a4bb9467..5994130e6b543cf92615eae63e70916cb9915774 100644 (file)
@@ -16,6 +16,8 @@
 /* clock control module regs definition */
 #if defined(CONFIG_MACH_SUN8I_A83T)
 #include <asm/arch/clock_sun8i_a83t.h>
+#elif defined(CONFIG_MACH_SUN50I_H6)
+#include <asm/arch/clock_sun50i_h6.h>
 #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
       defined(CONFIG_MACH_SUN50I)
 #include <asm/arch/clock_sun6i.h>
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
new file mode 100644 (file)
index 0000000..e369370
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Allwinner H6 clock register definitions
+ *
+ * (C) Copyright 2017 Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _SUNXI_CLOCK_SUN50I_H6_H
+#define _SUNXI_CLOCK_SUN50I_H6_H
+
+struct sunxi_ccm_reg {
+       u32 pll1_cfg;           /* 0x000 pll1 (cpux) control */
+       u8 reserved_0x004[12];
+       u32 pll5_cfg;           /* 0x010 pll5 (ddr) control */
+       u8 reserved_0x014[12];
+       u32 pll6_cfg;           /* 0x020 pll6 (periph0) control */
+       u8 reserved_0x020[4];
+       u32 pll_periph1_cfg;    /* 0x028 pll periph1 control */
+       u8 reserved_0x028[4];
+       u32 pll7_cfg;           /* 0x030 pll7 (gpu) control */
+       u8 reserved_0x034[12];
+       u32 pll3_cfg;           /* 0x040 pll3 (video0) control */
+       u8 reserved_0x044[4];
+       u32 pll_video1_cfg;     /* 0x048 pll video1 control */
+       u8 reserved_0x04c[12];
+       u32 pll4_cfg;           /* 0x058 pll4 (ve) control */
+       u8 reserved_0x05c[4];
+       u32 pll10_cfg;          /* 0x060 pll10 (de) control */
+       u8 reserved_0x064[12];
+       u32 pll9_cfg;           /* 0x070 pll9 (hsic) control */
+       u8 reserved_0x074[4];
+       u32 pll2_cfg;           /* 0x078 pll2 (audio) control */
+       u8 reserved_0x07c[148];
+       u32 pll5_pat;           /* 0x110 pll5 (ddr) pattern */
+       u8 reserved_0x114[20];
+       u32 pll_periph1_pat0;   /* 0x128 pll periph1 pattern0 */
+       u32 pll_periph1_pat1;   /* 0x12c pll periph1 pattern1 */
+       u32 pll7_pat0;          /* 0x130 pll7 (gpu) pattern0 */
+       u32 pll7_pat1;          /* 0x134 pll7 (gpu) pattern1 */
+       u8 reserved_0x138[8];
+       u32 pll3_pat0;          /* 0x140 pll3 (video0) pattern0 */
+       u32 pll3_pat1;          /* 0x144 pll3 (video0) pattern1 */
+       u32 pll_video1_pat0;    /* 0x148 pll video1 pattern0 */
+       u32 pll_video1_pat1;    /* 0x14c pll video1 pattern1 */
+       u8 reserved_0x150[8];
+       u32 pll4_pat0;          /* 0x158 pll4 (ve) pattern0 */
+       u32 pll4_pat1;          /* 0x15c pll4 (ve) pattern1 */
+       u32 pll10_pat0;         /* 0x160 pll10 (de) pattern0 */
+       u32 pll10_pat1;         /* 0x164 pll10 (de) pattern1 */
+       u8 reserved_0x168[8];
+       u32 pll9_pat0;          /* 0x170 pll9 (hsic) pattern0 */
+       u32 pll9_pat1;          /* 0x174 pll9 (hsic) pattern1 */
+       u32 pll2_pat0;          /* 0x178 pll2 (audio) pattern0 */
+       u32 pll2_pat1;          /* 0x17c pll2 (audio) pattern1 */
+       u8 reserved_0x180[384];
+       u32 pll1_bias;          /* 0x300 pll1 (cpux) bias */
+       u8 reserved_0x304[12];
+       u32 pll5_bias;          /* 0x310 pll5 (ddr) bias */
+       u8 reserved_0x314[12];
+       u32 pll6_bias;          /* 0x320 pll6 (periph0) bias */
+       u8 reserved_0x324[4];
+       u32 pll_periph1_bias;   /* 0x328 pll periph1 bias */
+       u8 reserved_0x32c[4];
+       u32 pll7_bias;          /* 0x330 pll7 (gpu) bias */
+       u8 reserved_0x334[12];
+       u32 pll3_bias;          /* 0x340 pll3 (video0) bias */
+       u8 reserved_0x344[4];
+       u32 pll_video1_bias;    /* 0x348 pll video1 bias */
+       u8 reserved_0x34c[12];
+       u32 pll4_bias;          /* 0x358 pll4 (ve) bias */
+       u8 reserved_0x35c[4];
+       u32 pll10_bias;         /* 0x360 pll10 (de) bias */
+       u8 reserved_0x364[12];
+       u32 pll9_bias;          /* 0x370 pll9 (hsic) bias */
+       u8 reserved_0x374[4];
+       u32 pll2_bias;          /* 0x378 pll2 (audio) bias */
+       u8 reserved_0x37c[132];
+       u32 pll1_tun;           /* 0x400 pll1 (cpux) tunning */
+       u8 reserved_0x404[252];
+       u32 cpu_axi_cfg;        /* 0x500 CPUX/AXI clock control*/
+       u8 reserved_0x504[12];
+       u32 psi_ahb1_ahb2_cfg;  /* 0x510 PSI/AHB1/AHB2 clock control */
+       u8 reserved_0x514[8];
+       u32 ahb3_cfg;           /* 0x51c AHB3 clock control */
+       u32 apb1_cfg;           /* 0x520 APB1 clock control */
+       u32 apb2_cfg;           /* 0x524 APB2 clock control */
+       u8 reserved_0x528[24];
+       u32 mbus_cfg;           /* 0x540 MBUS clock control */
+       u8 reserved_0x544[188];
+       u32 de_clk_cfg;         /* 0x600 DE clock control */
+       u8 reserved_0x604[8];
+       u32 de_gate_reset;      /* 0x60c DE gate/reset control */
+       u8 reserved_0x610[16];
+       u32 di_clk_cfg;         /* 0x620 DI clock control */
+       u8 reserved_0x024[8];
+       u32 di_gate_reset;      /* 0x62c DI gate/reset control */
+       u8 reserved_0x630[64];
+       u32 gpu_clk_cfg;        /* 0x670 GPU clock control */
+       u8 reserved_0x674[8];
+       u32 gpu_gate_reset;     /* 0x67c GPU gate/reset control */
+       u32 ce_clk_cfg;         /* 0x680 CE clock control */
+       u8 reserved_0x684[8];
+       u32 ce_gate_reset;      /* 0x68c CE gate/reset control */
+       u32 ve_clk_cfg;         /* 0x690 VE clock control */
+       u8 reserved_0x694[8];
+       u32 ve_gate_reset;      /* 0x69c VE gate/reset control */
+       u8 reserved_0x6a0[16];
+       u32 emce_clk_cfg;       /* 0x6b0 EMCE clock control */
+       u8 reserved_0x6b4[8];
+       u32 emce_gate_reset;    /* 0x6bc EMCE gate/reset control */
+       u32 vp9_clk_cfg;        /* 0x6c0 VP9 clock control */
+       u8 reserved_0x6c4[8];
+       u32 vp9_gate_reset;     /* 0x6cc VP9 gate/reset control */
+       u8 reserved_0x6d0[60];
+       u32 dma_gate_reset;     /* 0x70c DMA gate/reset control */
+       u8 reserved_0x710[12];
+       u32 msgbox_gate_reset;  /* 0x71c Message Box gate/reset control */
+       u8 reserved_0x720[12];
+       u32 spinlock_gate_reset;/* 0x72c Spinlock gate/reset control */
+       u8 reserved_0x730[12];
+       u32 hstimer_gate_reset; /* 0x73c HS Timer gate/reset control */
+       u32 avs_gate_reset;     /* 0x740 AVS gate/reset control */
+       u8 reserved_0x744[72];
+       u32 dbgsys_gate_reset;  /* 0x78c Debugging system gate/reset control */
+       u8 reserved_0x790[12];
+       u32 psi_gate_reset;     /* 0x79c PSI gate/reset control */
+       u8 reserved_0x7a0[12];
+       u32 pwm_gate_reset;     /* 0x7ac PWM gate/reset control */
+       u8 reserved_0x7b0[12];
+       u32 iommu_gate_reset;   /* 0x7bc IOMMU gate/reset control */
+       u8 reserved_0x7c0[64];
+       u32 dram_clk_cfg;               /* 0x800 DRAM clock control */
+       u32 mbus_gate;          /* 0x804 MBUS gate control */
+       u8 reserved_0x808[4];
+       u32 dram_gate_reset;    /* 0x80c DRAM gate/reset control */
+       u32 nand0_clk_cfg;      /* 0x810 NAND0 clock control */
+       u32 nand1_clk_cfg;      /* 0x814 NAND1 clock control */
+       u8 reserved_0x818[20];
+       u32 nand_gate_reset;    /* 0x82c NAND gate/reset control */
+       u32 sd0_clk_cfg;        /* 0x830 MMC0 clock control */
+       u32 sd1_clk_cfg;        /* 0x834 MMC1 clock control */
+       u32 sd2_clk_cfg;        /* 0x838 MMC2 clock control */
+       u8 reserved_0x83c[16];
+       u32 sd_gate_reset;      /* 0x84c MMC gate/reset control */
+       u8 reserved_0x850[188];
+       u32 uart_gate_reset;    /* 0x90c UART gate/reset control */
+       u8 reserved_0x910[12];
+       u32 twi_gate_reset;     /* 0x91c I2C gate/reset control */
+       u8 reserved_0x920[28];
+       u32 scr_gate_reset;     /* 0x93c SCR gate/reset control */
+       u32 spi0_clk_cfg;       /* 0x940 SPI0 clock control */
+       u32 spi1_clk_cfg;       /* 0x944 SPI1 clock control */
+       u8 reserved_0x948[36];
+       u32 spi_gate_reset;     /* 0x96c SPI gate/reset control */
+       u8 reserved_0x970[12];
+       u32 emac_gate_reset;    /* 0x97c EMAC gate/reset control */
+       u8 reserved_0x980[48];
+       u32 ts_clk_cfg;         /* 0x9b0 TS clock control */
+       u8 reserved_0x9b4[8];
+       u32 ts_gate_reset;      /* 0x9bc TS gate/reset control */
+       u32 irtx_clk_cfg;       /* 0x9c0 IR TX clock control */
+       u8 reserved_0x9c4[8];
+       u32 irtx_gate_reset;    /* 0x9cc IR TX gate/reset control */
+       u8 reserved_0x9d0[44];
+       u32 ths_gate_reset;     /* 0x9fc THS gate/reset control */
+       u8 reserved_0xa00[12];
+       u32 i2s3_clk_cfg;       /* 0xa0c I2S3 clock control */
+       u32 i2s0_clk_cfg;       /* 0xa10 I2S0 clock control */
+       u32 i2s1_clk_cfg;       /* 0xa14 I2S1 clock control */
+       u32 i2s2_clk_cfg;       /* 0xa18 I2S2 clock control */
+       u32 i2s_gate_reset;     /* 0xa1c I2S gate/reset control */
+       u32 spdif_clk_cfg;      /* 0xa20 SPDIF clock control */
+       u8 reserved_0xa24[8];
+       u32 spdif_gate_reset;   /* 0xa2c SPDIF gate/reset control */
+       u8 reserved_0xa30[16];
+       u32 dmic_clk_cfg;       /* 0xa40 DMIC clock control */
+       u8 reserved_0xa44[8];
+       u32 dmic_gate_reset;    /* 0xa4c DMIC gate/reset control */
+       u8 reserved_0xa50[16];
+       u32 ahub_clk_cfg;       /* 0xa60 Audio HUB clock control */
+       u8 reserved_0xa64[8];
+       u32 ahub_gate_reset;    /* 0xa6c Audio HUB gate/reset control */
+       u32 usb0_clk_cfg;       /* 0xa70 USB0(OTG) clock control */
+       u32 usb1_clk_cfg;       /* 0xa74 USB1(XHCI) clock control */
+       u8 reserved_0xa78[4];
+       u32 usb3_clk_cfg;       /* 0xa78 USB3 clock control */
+       u8 reserved_0xa80[12];
+       u32 usb_gate_reset;     /* 0xa8c USB gate/reset control */
+       u8 reserved_0xa90[32];
+       u32 pcie_ref_clk_cfg;   /* 0xab0 PCIE REF clock control */
+       u32 pcie_axi_clk_cfg;   /* 0xab4 PCIE AXI clock control */
+       u32 pcie_aux_clk_cfg;   /* 0xab8 PCIE AUX clock control */
+       u32 pcie_gate_reset;    /* 0xabc PCIE gate/reset control */
+       u8 reserved_0xac0[64];
+       u32 hdmi_clk_cfg;       /* 0xb00 HDMI clock control */
+       u32 hdmi_slow_clk_cfg;  /* 0xb04 HDMI slow clock control */
+       u8 reserved_0xb08[8];
+       u32 hdmi_cec_clk_cfg;   /* 0xb10 HDMI CEC clock control */
+       u8 reserved_0xb14[8];
+       u32 hdmi_gate_reset;    /* 0xb1c HDMI gate/reset control */
+       u8 reserved_0xb20[60];
+       u32 tcon_top_gate_reset;/* 0xb5c TCON TOP gate/reset control */
+       u32 tcon_lcd0_clk_cfg;  /* 0xb60 TCON LCD0 clock control */
+       u8 reserved_0xb64[24];
+       u32 tcon_lcd_gate_reset;/* 0xb7c TCON LCD gate/reset control */
+       u32 tcon_tv0_clk_cfg;   /* 0xb80 TCON TV0 clock control */
+       u8 reserved_0xb84[24];
+       u32 tcon_tv_gate_reset; /* 0xb9c TCON TV gate/reset control */
+       u8 reserved_0xba0[96];
+       u32 csi_misc_clk_cfg;   /* 0xc00 CSI MISC clock control */
+       u32 csi_top_clk_cfg;    /* 0xc04 CSI TOP clock control */
+       u32 csi_mclk_cfg;       /* 0xc08 CSI Master clock control */
+       u8 reserved_0xc0c[32];
+       u32 csi_gate_reset;     /* 0xc2c CSI gate/reset control */
+       u8 reserved_0xc30[16];
+       u32 hdcp_clk_cfg;       /* 0xc40 HDCP clock control */
+       u8 reserved_0xc44[8];
+       u32 hdcp_gate_reset;    /* 0xc4c HDCP gate/reset control */
+       u8 reserved_0xc50[688];
+       u32 ccu_sec_switch;     /* 0xf00 CCU security switch */
+       u32 pll_lock_dbg_ctrl;  /* 0xf04 PLL lock debugging control */
+};
+
+/* pll1 bit field */
+#define CCM_PLL1_CTRL_EN               BIT(31)
+#define CCM_PLL1_LOCK_EN               BIT(29)
+#define CCM_PLL1_LOCK                  BIT(28)
+#define CCM_PLL1_CLOCK_TIME_2          (2 << 24)
+#define CCM_PLL1_CTRL_P(p)             ((p) << 16)
+#define CCM_PLL1_CTRL_N(n)             ((n) << 8)
+
+/* pll5 bit field */
+#define CCM_PLL5_CTRL_EN               BIT(31)
+#define CCM_PLL5_LOCK_EN               BIT(29)
+#define CCM_PLL5_LOCK                  BIT(28)
+#define CCM_PLL5_CTRL_N(n)             ((n) << 8)
+#define CCM_PLL5_CTRL_DIV1(div1)       ((div1) << 0)
+#define CCM_PLL5_CTRL_DIV2(div0)       ((div0) << 1)
+
+/* pll6 bit field */
+#define CCM_PLL6_CTRL_EN               BIT(31)
+#define CCM_PLL6_LOCK_EN               BIT(29)
+#define CCM_PLL6_LOCK                  BIT(28)
+#define CCM_PLL6_CTRL_N_SHIFT          8
+#define CCM_PLL6_CTRL_N_MASK           (0xff << CCM_PLL6_CTRL_N_SHIFT)
+#define CCM_PLL6_CTRL_DIV1_SHIFT       0
+#define CCM_PLL6_CTRL_DIV1_MASK                (0x1 << CCM_PLL6_CTRL_DIV1_SHIFT)
+#define CCM_PLL6_CTRL_DIV2_SHIFT       1
+#define CCM_PLL6_CTRL_DIV2_MASK                (0x1 << CCM_PLL6_CTRL_DIV2_SHIFT)
+#define CCM_PLL6_DEFAULT               0xa0006300
+
+/* cpu_axi bit field*/
+#define CCM_CPU_AXI_MUX_MASK           (0x3 << 24)
+#define CCM_CPU_AXI_MUX_OSC24M         (0x0 << 24)
+#define CCM_CPU_AXI_MUX_PLL_CPUX       (0x3 << 24)
+#define CCM_CPU_AXI_APB_MASK           0x300
+#define CCM_CPU_AXI_AXI_MASK           0x3
+#define CCM_CPU_AXI_DEFAULT_FACTORS    0x301
+
+/* psi_ahb1_ahb2 bit field */
+#define CCM_PSI_AHB1_AHB2_DEFAULT      0x03000102
+
+/* ahb3 bit field */
+#define CCM_AHB3_DEFAULT               0x03000002
+
+/* apb1 bit field */
+#define CCM_APB1_DEFAULT               0x03000102
+
+/* apb2 bit field */
+#define APB2_CLK_SRC_OSC24M            (0x0 << 24)
+#define APB2_CLK_SRC_OSC32K            (0x1 << 24)
+#define APB2_CLK_SRC_PSI               (0x2 << 24)
+#define APB2_CLK_SRC_PLL6              (0x3 << 24)
+#define APB2_CLK_SRC_MASK              (0x3 << 24)
+#define APB2_CLK_RATE_N_1              (0x0 << 8)
+#define APB2_CLK_RATE_N_2              (0x1 << 8)
+#define APB2_CLK_RATE_N_4              (0x2 << 8)
+#define APB2_CLK_RATE_N_8              (0x3 << 8)
+#define APB2_CLK_RATE_N_MASK           (3 << 8)
+#define APB2_CLK_RATE_M(m)             (((m)-1) << 0)
+#define APB2_CLK_RATE_M_MASK            (3 << 0)
+
+/* MBUS clock bit field */
+#define MBUS_ENABLE                    BIT(31)
+#define MBUS_RESET                     BIT(30)
+#define MBUS_CLK_SRC_MASK              GENMASK(25, 24)
+#define MBUS_CLK_SRC_OSCM24            (0 << 24)
+#define MBUS_CLK_SRC_PLL6X2            (1 << 24)
+#define MBUS_CLK_SRC_PLL5              (2 << 24)
+#define MBUS_CLK_SRC_PLL6X4            (3 << 24)
+#define MBUS_CLK_M(m)                  (((m)-1) << 0)
+
+/* Module gate/reset shift*/
+#define RESET_SHIFT                    (16)
+
+/* DRAM clock bit field */
+#define DRAM_MOD_RESET                 BIT(30)
+#define DRAM_CLK_UPDATE                        BIT(27)
+#define DRAM_CLK_SRC_MASK              GENMASK(25, 24)
+#define DRAM_CLK_SRC_PLL5              (0 << 24)
+#define DRAM_CLK_M(m)                  (((m)-1) << 0)
+
+/* MMC clock bit field */
+#define CCM_MMC_CTRL_M(x)              ((x) - 1)
+#define CCM_MMC_CTRL_N(x)              ((x) << 8)
+#define CCM_MMC_CTRL_OSCM24            (0x0 << 24)
+#define CCM_MMC_CTRL_PLL6X2            (0x1 << 24)
+#define CCM_MMC_CTRL_PLL_PERIPH2X2     (0x2 << 24)
+#define CCM_MMC_CTRL_ENABLE            (0x1 << 31)
+/* H6 doesn't have these delays */
+#define CCM_MMC_CTRL_OCLK_DLY(a)       ((void) (a), 0)
+#define CCM_MMC_CTRL_SCLK_DLY(a)       ((void) (a), 0)
+
+#ifndef __ASSEMBLY__
+void clock_set_pll1(unsigned int hz);
+unsigned int clock_get_pll6(void);
+#endif
+
+#endif /* _SUNXI_CLOCK_SUN50I_H6_H */
index 0534ccc8dad5a1a6e11f511a3eb2bb929616f29f..4c399b0a15beb363810f91d21d13eb7ecd3dbb29 100644 (file)
@@ -8,6 +8,8 @@
 
 #if defined(CONFIG_MACH_SUN9I)
 #include <asm/arch/cpu_sun9i.h>
+#elif defined(CONFIG_MACH_SUN50I_H6)
+#include <asm/arch/cpu_sun50i_h6.h>
 #else
 #include <asm/arch/cpu_sun4i.h>
 #endif
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
new file mode 100644 (file)
index 0000000..f568def
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * (C) Copyright 2017 Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _SUNXI_CPU_SUN50I_H6_H
+#define _SUNXI_CPU_SUN50I_H6_H
+
+#define SUNXI_SRAM_A1_BASE             CONFIG_SUNXI_SRAM_ADDRESS
+#define SUNXI_SRAM_C_BASE              0x00028000
+#define SUNXI_SRAM_A2_BASE             0x00100000
+
+#define SUNXI_DE3_BASE                 0x01000000
+#define SUNXI_SS_BASE                  0x01904000
+#define SUNXI_EMCE_BASE                        0x01905000
+
+#define SUNXI_SRAMC_BASE               0x03000000
+#define SUNXI_CCM_BASE                 0x03001000
+#define SUNXI_DMA_BASE                 0x03002000
+/* SID address space starts at 0x03006000, but e-fuse is at offset 0x200 */
+#define SUNXI_SIDC_BASE                        0x03006000
+#define SNUXI_SID_BASE                 0x03006200
+#define SUNXI_TIMER_BASE               0x03009000
+#define SUNXI_PIO_BASE                 0x0300B000
+#define SUNXI_PSI_BASE                 0x0300C000
+
+#define SUNXI_GIC400_BASE              0x03020000
+#define SUNXI_IOMMU_BASE               0x030F0000
+
+#define SUNXI_DRAM_COM_BASE            0x04002000
+#define SUNXI_DRAM_CTL0_BASE           0x04003000
+#define SUNXI_DRAM_PHY0_BASE           0x04005000
+#define SUNXI_NFC_BASE                 0x04011000
+#define SUNXI_MMC0_BASE                        0x04020000
+#define SUNXI_MMC1_BASE                        0x04021000
+#define SUNXI_MMC2_BASE                        0x04022000
+
+#define SUNXI_UART0_BASE               0x05000000
+#define SUNXI_UART1_BASE               0x05000400
+#define SUNXI_UART2_BASE               0x05000800
+#define SUNXI_UART3_BASE               0x05000C00
+#define SUNXI_TWI0_BASE                        0x05002000
+#define SUNXI_TWI1_BASE                        0x05002400
+#define SUNXI_TWI2_BASE                        0x05002800
+#define SUNXI_TWI3_BASE                        0x05002C00
+#define SUNXI_SPI0_BASE                        0x05010000
+#define SUNXI_SPI1_BASE                        0x05011000
+#define SUNXI_GMAC_BASE                        0x05020000
+#define SUNXI_USB0_BASE                        0x05100000
+#define SUNXI_XHCI_BASE                        0x05200000
+#define SUNXI_USB3_BASE                        0x05311000
+#define SUNXI_PCIE_BASE                        0x05400000
+
+#define SUNXI_HDMI_BASE                        0x06000000
+#define SUNXI_TCON_TOP_BASE            0x06510000
+#define SUNXI_TCON_LCD0_BASE           0x06511000
+#define SUNXI_TCON_TV0_BASE            0x06515000
+
+#define SUNXI_RTC_BASE                 0x07000000
+#define SUNXI_R_CPUCFG_BASE            0x07000400
+#define SUNXI_PRCM_BASE                        0x07010000
+#define SUNXI_R_PIO_BASE               0x07022000
+#define SUNXI_R_UART_BASE              0x07080000
+#define SUNXI_R_TWI_BASE               0x07081400
+
+#ifndef __ASSEMBLY__
+void sunxi_board_init(void);
+void sunxi_reset(void);
+int sunxi_get_sid(unsigned int *sid);
+#endif
+
+#endif /* _SUNXI_CPU_SUN9I_H */
index a5c091eeaa89ecdca9c86b278a9d9b6c53a6d3b2..8002b7efdc196bc06416ffb0d284966782f2c95b 100644 (file)
@@ -27,6 +27,8 @@
 #include <asm/arch/dram_sunxi_dw.h>
 #elif defined(CONFIG_MACH_SUN9I)
 #include <asm/arch/dram_sun9i.h>
+#elif defined(CONFIG_MACH_SUN50I_H6)
+#include <asm/arch/dram_sun50i_h6.h>
 #else
 #include <asm/arch/dram_sun4i.h>
 #endif
diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
new file mode 100644 (file)
index 0000000..eeb4da5
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * H6 dram controller register and constant defines
+ *
+ * (C) Copyright 2017  Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _SUNXI_DRAM_SUN50I_H6_H
+#define _SUNXI_DRAM_SUN50I_H6_H
+
+enum sunxi_dram_type {
+       SUNXI_DRAM_TYPE_DDR3 = 3,
+       SUNXI_DRAM_TYPE_DDR4,
+       SUNXI_DRAM_TYPE_LPDDR2 = 6,
+       SUNXI_DRAM_TYPE_LPDDR3,
+};
+
+/*
+ * The following information is mainly retrieved by disassembly and some FPGA
+ * test code of sun50iw3 platform.
+ */
+struct sunxi_mctl_com_reg {
+       u32 cr;                 /* 0x000 control register */
+       u8 reserved_0x004[4];   /* 0x004 */
+       u32 unk_0x008;          /* 0x008 */
+       u32 tmr;                /* 0x00c timer register */
+       u8 reserved_0x010[4];   /* 0x010 */
+       u32 unk_0x014;          /* 0x014 */
+       u8 reserved_0x018[8];   /* 0x018 */
+       u32 maer0;              /* 0x020 master enable register 0 */
+       u32 maer1;              /* 0x024 master enable register 1 */
+       u32 maer2;              /* 0x028 master enable register 2 */
+       u8 reserved_0x02c[468]; /* 0x02c */
+       u32 bwcr;               /* 0x200 bandwidth control register */
+       u8 reserved_0x204[12];  /* 0x204 */
+       /*
+        * The last master configured by BSP libdram is at 0x49x, so the
+        * size of this struct array is set to 41 (0x29) now.
+        */
+       struct {
+               u32 cfg0;               /* 0x0 */
+               u32 cfg1;               /* 0x4 */
+               u8 reserved_0x8[8];     /* 0x8 */
+       } master[41];           /* 0x210 + index * 0x10 */
+};
+check_member(sunxi_mctl_com_reg, master[40].reserved_0x8, 0x498);
+
+/*
+ * The following register information are retrieved from some similar DRAM
+ * controllers, including the DRAM controllers in Allwinner A23/A80 SoCs,
+ * Rockchip RK3328 SoC, NXP i.MX7 SoCs and Xilinx Zynq UltraScale+ SoCs.
+ *
+ * The DRAM controller in Allwinner A23/A80 SoCs and NXP i.MX7 SoCs seems
+ * to be older than the one in Allwinner H6, as the DRAMTMG9 register
+ * is missing in these SoCs. (From the product specifications of these
+ * SoCs they're not capable of DDR4)
+ *
+ * Information sources:
+ * - dram_sun9i.h and dram_sun8i_a23.h in the same directory.
+ * - sdram_rk3328.h from the RK3328 TPL DRAM patchset
+ * - i.MX 7Solo Applications Processor Reference Manual (IMX7SRM)
+ * - Zynq UltraScale+ MPSoC Register Reference (UG1087)
+ */
+struct sunxi_mctl_ctl_reg {
+       u32 mstr;               /* 0x000 */
+       u32 statr;              /* 0x004 unused */
+       u32 mstr1;              /* 0x008 unused */
+       u32 unk_0x00c;          /* 0x00c */
+       u32 mrctrl0;            /* 0x010 unused */
+       u32 mrctrl1;            /* 0x014 unused */
+       u32 mrstatr;            /* 0x018 unused */
+       u32 mrctrl2;            /* 0x01c unused */
+       u32 derateen;           /* 0x020 unused */
+       u32 derateint;          /* 0x024 unused */
+       u8 reserved_0x028[8];   /* 0x028 */
+       u32 pwrctl;             /* 0x030 unused */
+       u32 pwrtmg;             /* 0x034 unused */
+       u32 hwlpctl;            /* 0x038 unused */
+       u8 reserved_0x03c[20];  /* 0x03c */
+       u32 rfshctl0;           /* 0x050 unused */
+       u32 rfshctl1;           /* 0x054 unused */
+       u8 reserved_0x058[8];   /* 0x05c */
+       u32 rfshctl3;           /* 0x060 */
+       u32 rfshtmg;            /* 0x064 */
+       u8 reserved_0x068[104]; /* 0x068 reserved for ECC&CRC (from ZynqMP) */
+       u32 init[8];            /* 0x0d0 */
+       u32 dimmctl;            /* 0x0f0 unused */
+       u32 rankctl;            /* 0x0f4 */
+       u8 reserved_0x0f8[8];   /* 0x0f8 */
+       u32 dramtmg[17];        /* 0x100 */
+       u8 reserved_0x144[60];  /* 0x144 */
+       u32 zqctl[3];           /* 0x180 */
+       u32 zqstat;             /* 0x18c unused */
+       u32 dfitmg0;            /* 0x190 */
+       u32 dfitmg1;            /* 0x194 */
+       u32 dfilpcfg[2];        /* 0x198 unused */
+       u32 dfiupd[3];          /* 0x1a0 */
+       u32 reserved_0x1ac;     /* 0x1ac */
+       u32 dfimisc;            /* 0x1b0 */
+       u32 dfitmg2;            /* 0x1b4 unused, may not exist */
+       u8 reserved_0x1b8[8];   /* 0x1b8 */
+       u32 dbictl;             /* 0x1c0 */
+       u8 reserved_0x1c4[60];  /* 0x1c4 */
+       u32 addrmap[12];        /* 0x200 */
+       u8 reserved_0x230[16];  /* 0x230 */
+       u32 odtcfg;             /* 0x240 */
+       u32 odtmap;             /* 0x244 */
+       u8 reserved_0x248[8];   /* 0x248 */
+       u32 sched[2];           /* 0x250 */
+       u8 reserved_0x258[180]; /* 0x258 */
+       u32 dbgcmd;             /* 0x30c unused */
+       u32 dbgstat;            /* 0x310 unused */
+       u8 reserved_0x314[12];  /* 0x314 */
+       u32 swctl;              /* 0x320 */
+       u32 swstat;             /* 0x324 */
+};
+check_member(sunxi_mctl_ctl_reg, swstat, 0x324);
+
+#define MSTR_DEVICETYPE_DDR3   BIT(0)
+#define MSTR_DEVICETYPE_LPDDR2 BIT(2)
+#define MSTR_DEVICETYPE_LPDDR3 BIT(3)
+#define MSTR_DEVICETYPE_DDR4   BIT(4)
+#define MSTR_DEVICETYPE_MASK   GENMASK(5, 0)
+#define MSTR_2TMODE            BIT(10)
+#define MSTR_BUSWIDTH_FULL     (0 << 12)
+#define MSTR_BUSWIDTH_HALF     (1 << 12)
+#define MSTR_ACTIVE_RANKS(x)   (((x == 2) ? 3 : 1) << 24)
+#define MSTR_BURST_LENGTH(x)   (((x) >> 1) << 16)
+
+/*
+ * The following register information is based on Zynq UltraScale+
+ * MPSoC Register Reference, as it's the currently only known
+ * DDR PHY similar to the one used in H6; however although the
+ * map is similar, the bit fields definitions are different.
+ *
+ * Other DesignWare DDR PHY's have similar register names, but the
+ * offset and definitions are both different.
+ */
+struct sunxi_mctl_phy_reg {
+       u32 ver;                /* 0x000 guess based on similar PHYs */
+       u32 pir;                /* 0x004 */
+       u8 reserved_0x008[8];   /* 0x008 */
+       /*
+        * The ZynqMP manual didn't document PGCR1, however this register
+        * exists on H6 and referenced by libdram.
+        */
+       u32 pgcr[8];            /* 0x010 */
+       /*
+        * By comparing the hardware and the ZynqMP manual, the PGSR seems
+        * to start at 0x34 on H6.
+        */
+       u8 reserved_0x030[4];   /* 0x030 */
+       u32 pgsr[3];            /* 0x034 */
+       u32 ptr[7];             /* 0x040 */
+       /*
+        * According to ZynqMP reference there's PLLCR0~6 in this area,
+        * but they're tagged "Type B PLL Only" and H6 seems to have
+        * no them.
+        * 0x080 is not present in ZynqMP reference but it seems to be
+        * present on H6.
+        */
+       u8 reserved_0x05c[36];  /* 0x05c */
+       u32 unk_0x080;          /* 0x080 */
+       u8 reserved_0x084[4];   /* 0x084 */
+       u32 dxccr;              /* 0x088 */
+       u8 reserved_0x08c[4];   /* 0x08c */
+       u32 dsgcr;              /* 0x090 */
+       u8 reserved_0x094[4];   /* 0x094 */
+       u32 odtcr;              /* 0x098 */
+       u8 reserved_0x09c[4];   /* 0x09c */
+       u32 aacr;               /* 0x0a0 */
+       u8 reserved_0x0a4[32];  /* 0x0a4 */
+       u32 gpr1;               /* 0x0c4 */
+       u8 reserved_0x0c8[56];  /* 0x0c8 */
+       u32 dcr;                /* 0x100 */
+       u8 reserved_0x104[12];  /* 0x104 */
+       u32 dtpr[7];            /* 0x110 */
+       u8 reserved_0x12c[20];  /* 0x12c */
+       u32 rdimmgcr[3];        /* 0x140 */
+       u8 reserved_0x14c[4];   /* 0x14c */
+       u32 rdimmcr[5];         /* 0x150 */
+       u8 reserved_0x164[4];   /* 0x164 */
+       u32 schcr[2];           /* 0x168 */
+       u8 reserved_0x170[16];  /* 0x170 */
+       /*
+        * The ZynqMP manual documents MR0~7, 11~14 and 22.
+        */
+       u32 mr[23];             /* 0x180 */
+       u8 reserved_0x1dc[36];  /* 0x1dc */
+       u32 dtcr[2];            /* 0x200 */
+       u32 dtar[3];            /* 0x208 */
+       u8 reserved_0x214[4];   /* 0x214 */
+       u32 dtdr[2];            /* 0x218 */
+       u8 reserved_0x220[16];  /* 0x220 */
+       u32 dtedr0;             /* 0x230 */
+       u32 dtedr1;             /* 0x234 */
+       u32 dtedr2;             /* 0x238 */
+       u32 vtdr;               /* 0x23c */
+       u32 catr[2];            /* 0x240 */
+       u8 reserved_0x248[8];
+       u32 dqsdr[3];           /* 0x250 */
+       u32 dtedr3;             /* 0x25c */
+       u8 reserved_0x260[160]; /* 0x260 */
+       u32 dcuar;              /* 0x300 */
+       u32 dcudr;              /* 0x304 */
+       u32 dcurr;              /* 0x308 */
+       u32 dculr;              /* 0x30c */
+       u32 dcugcr;             /* 0x310 */
+       u32 dcutpr;             /* 0x314 */
+       u32 dcusr[2];           /* 0x318 */
+       u8 reserved_0x320[444]; /* 0x320 */
+       u32 rankidr;            /* 0x4dc */
+       u32 riocr[6];           /* 0x4e0 */
+       u8 reserved_0x4f8[8];   /* 0x4f8 */
+       u32 aciocr[6];          /* 0x500 */
+       u8 reserved_0x518[8];   /* 0x518 */
+       u32 iovcr[2];           /* 0x520 */
+       u32 vtcr[2];            /* 0x528 */
+       u8 reserved_0x530[16];  /* 0x530 */
+       u32 acbdlr[17];         /* 0x540 */
+       u32 aclcdlr;            /* 0x584 */
+       u8 reserved_0x588[24];  /* 0x588 */
+       u32 acmdlr[2];          /* 0x5a0 */
+       u8 reserved_0x5a8[216]; /* 0x5a8 */
+       struct {
+               u32 zqcr;       /* 0x00 only the first one valid */
+               u32 zqpr[2];    /* 0x04 */
+               u32 zqdr[2];    /* 0x0c */
+               u32 zqor[2];    /* 0x14 */
+               u32 zqsr;       /* 0x1c */
+       } zq[2];                /* 0x680, 0x6a0 */
+       u8 reserved_0x6c0[64];  /* 0x6c0 */
+       struct {
+               u32 gcr[7];             /* 0x00 */
+               u8 reserved_0x1c[36];   /* 0x1c */
+               u32 bdlr0;              /* 0x40 */
+               u32 bdlr1;              /* 0x44 */
+               u32 bdlr2;              /* 0x48 */
+               u8 reserved_0x4c[4];    /* 0x4c */
+               u32 bdlr3;              /* 0x50 */
+               u32 bdlr4;              /* 0x54 */
+               u32 bdlr5;              /* 0x58 */
+               u8 reserved_0x5c[4];    /* 0x5c */
+               u32 bdlr6;              /* 0x60 */
+               u8 reserved_0x64[28];   /* 0x64 */
+               u32 lcdlr[6];           /* 0x80 */
+               u8 reserved_0x98[8];    /* 0x98 */
+               u32 mdlr[2];            /* 0xa0 */
+               u8 reserved_0xa8[24];   /* 0xa8 */
+               u32 gtr0;               /* 0xc0 */
+               u8 reserved_0xc4[12];   /* 0xc4 */
+               /*
+                * DXnRSR0 is not documented in ZynqMP manual but
+                * it's used in libdram.
+                */
+               u32 rsr[4];             /* 0xd0 */
+               u32 gsr[4];             /* 0xe0 */
+               u8 reserved_0xf0[16];   /* 0xf0 */
+       } dx[4];                /* 0x700, 0x800, 0x900, 0xa00 */
+};
+check_member(sunxi_mctl_phy_reg, dx[3].reserved_0xf0, 0xaf0);
+
+#define PIR_INIT       BIT(0)
+#define PIR_ZCAL       BIT(1)
+#define PIR_CA         BIT(2)
+#define PIR_PLLINIT    BIT(4)
+#define PIR_DCAL       BIT(5)
+#define PIR_PHYRST     BIT(6)
+#define PIR_DRAMRST    BIT(7)
+#define PIR_DRAMINIT   BIT(8)
+#define PIR_WL         BIT(9)
+#define PIR_QSGATE     BIT(10)
+#define PIR_WLADJ      BIT(11)
+#define PIR_RDDSKW     BIT(12)
+#define PIR_WRDSKW     BIT(13)
+#define PIR_RDEYE      BIT(14)
+#define PIR_WREYE      BIT(15)
+#define PIR_VREF       BIT(17)
+#define PIR_CTLDINIT   BIT(18)
+#define PIR_DQS2DQ     BIT(20)
+#define PIR_DCALPSE    BIT(29)
+#define PIR_ZCALBYP    BIT(30)
+
+#define DCR_LPDDR3     (1 << 0)
+#define DCR_DDR3       (3 << 0)
+#define DCR_DDR4       (4 << 0)
+#define DCR_DDR8BANK   BIT(3)
+
+static inline int ns_to_t(int nanoseconds)
+{
+       const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
+
+       return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
+}
+
+#endif /* _SUNXI_DRAM_SUN50I_H6_H */
index e4fe54d8b8d2101098b6edd2ddb6df203e120e01..6a5eafc3d31f643fed539cb501c07943aa411f49 100644 (file)
@@ -198,6 +198,7 @@ enum sunxi_gpio_number {
 #define SUN6I_GPH_TWI2         2
 #define SUN6I_GPH_UART0                2
 #define SUN9I_GPH_UART0                2
+#define SUN50I_H6_GPH_UART0    2
 
 #define SUNXI_GPI_SDC3         2
 #define SUN7I_GPI_TWI3         3
index 1574b8e8feda1340a75a922d18bdd53067a7c47d..d98c53faaa1f0cf166e771cf1719c141b4f593a5 100644 (file)
@@ -45,7 +45,7 @@ struct sunxi_mmc {
        u32 chda;               /* 0x90 */
        u32 cbda;               /* 0x94 */
        u32 res2[26];
-#ifdef CONFIG_SUNXI_GEN_SUN6I
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
        u32 res3[64];
 #endif
        u32 fifo;               /* 0x100 / 0x200 FIFO access address */
index 4277d836e59cd317d50a8c13303822d897088239..55f2deb18d105998b2f11a12b05c694c13c77e9c 100644 (file)
 #define SPL_SIGNATURE          "SPL" /* marks "sunxi" SPL header */
 #define SPL_HEADER_VERSION     2
 
-#ifdef CONFIG_SUNXI_HIGH_SRAM
-#define SPL_ADDR               0x10000
-#else
-#define SPL_ADDR               0x0
-#endif
+#define SPL_ADDR               CONFIG_SUNXI_SRAM_ADDRESS
 
 /* The low 8-bits of the 'boot_media' field in the SPL header */
 #define SUNXI_BOOTED_FROM_MMC0 0
index cb02dd8bf8fbda747e39390bf8723471d2860bc1..6f138d04b806495d2af17d641b02efa9a71bab08 100644 (file)
@@ -76,7 +76,7 @@ struct sunxi_timer_reg {
        struct sunxi_tgp tgp[4];
        u8 res5[8];
        u32 cpu_cfg;
-#elif defined(CONFIG_SUNXI_GEN_SUN6I)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
        u8 res3[16];
        struct sunxi_wdog wdog[5];      /* We have 5 watchdogs */
 #endif
index 678e33dd40e8bb6501960fd47a9d4546562cbb67..558363b52d23b235a6bdafcaea96612009fc3c95 100644 (file)
@@ -42,6 +42,12 @@ config DRAM_SUN9I
          Select this dram controller driver for Sun9i platforms,
          like A80.
 
+config DRAM_SUN50I_H6
+       bool
+       help
+         Select this dram controller driver for some sun50i platforms,
+         like H6.
+
 config SUN6I_P2WI
        bool "Allwinner sun6i internal P2WI controller"
        help
@@ -73,16 +79,16 @@ config SUN8I_RSB
          with various RSB based devices, such as AXP223, AXP8XX PMICs,
          and AC100/AC200 ICs.
 
-config SUNXI_HIGH_SRAM
-       bool
-       default n
+config SUNXI_SRAM_ADDRESS
+       hex
+       default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
+       default 0x20000 if MACH_SUN50I_H6
+       default 0x0
        ---help---
        Older Allwinner SoCs have their mask boot ROM mapped just below 4GB,
        with the first SRAM region being located at address 0.
        Some newer SoCs map the boot ROM at address 0 instead and move the
-       SRAM to 64KB, just behind the mask ROM.
-       Chips using the latter setup are supposed to select this option to
-       adjust the addresses accordingly.
+       SRAM to a different address.
 
 config SUNXI_A64_TIMER_ERRATUM
        bool
@@ -257,7 +263,6 @@ config MACH_SUN9I
        select CPU_V7A
        select DRAM_SUN9I
        select SUN6I_PRCM
-       select SUNXI_HIGH_SRAM
        select SUNXI_GEN_SUN6I
        select SUN8I_RSB
        select SUPPORT_SPL
@@ -269,7 +274,6 @@ config MACH_SUN50I
        select PHY_SUN4I_USB
        select SUNXI_DE2
        select SUNXI_GEN_SUN6I
-       select SUNXI_HIGH_SRAM
        select SUPPORT_SPL
        select SUNXI_DRAM_DW
        select SUNXI_DRAM_DW_32BIT
@@ -281,10 +285,17 @@ config MACH_SUN50I_H5
        bool "sun50i (Allwinner H5)"
        select ARM64
        select MACH_SUNXI_H3_H5
-       select SUNXI_HIGH_SRAM
        select FIT
        select SPL_LOAD_FIT
 
+config MACH_SUN50I_H6
+       bool "sun50i (Allwinner H6)"
+       select ARM64
+       select SUPPORT_SPL
+       select FIT
+       select SPL_LOAD_FIT
+       select DRAM_SUN50I_H6
+
 endchoice
 
 # The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 || A33"
@@ -378,6 +389,7 @@ config DRAM_CLK
        default 360 if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || \
                       MACH_SUN8I_V3S
        default 672 if MACH_SUN50I
+       default 744 if MACH_SUN50I_H6
        ---help---
        Set the dram clock speed, valid range 240 - 480 (prior to sun9i),
        must be a multiple of 24. For the sun9i (A80), the tested values
@@ -397,7 +409,7 @@ config DRAM_ZQ
        default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN8I
        default 127 if MACH_SUN7I
        default 14779 if MACH_SUN8I_V3S
-       default 3881979 if MACH_SUN8I_R40
+       default 3881979 if MACH_SUN8I_R40 || MACH_SUN50I_H6
        default 4145117 if MACH_SUN9I
        default 3881915 if MACH_SUN50I
        ---help---
@@ -409,6 +421,7 @@ config DRAM_ODT_EN
        default y if MACH_SUN8I_A23
        default y if MACH_SUN8I_R40
        default y if MACH_SUN50I
+       default y if MACH_SUN50I_H6
        ---help---
        Select this to enable dram odt (on die termination).
 
@@ -499,6 +512,7 @@ config SYS_CLK_FREQ
        default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
        default 1008000000 if MACH_SUN8I
        default 1008000000 if MACH_SUN9I
+       default 888000000 if MACH_SUN50I_H6
 
 config SYS_CONFIG_NAME
        default "sun4i" if MACH_SUN4I
@@ -508,6 +522,7 @@ config SYS_CONFIG_NAME
        default "sun8i" if MACH_SUN8I
        default "sun9i" if MACH_SUN9I
        default "sun50i" if MACH_SUN50I
+       default "sun50i" if MACH_SUN50I_H6
 
 config SYS_BOARD
        default "sunxi"
@@ -713,6 +728,7 @@ config VIDEO_SUNXI
        depends on !MACH_SUN8I_V3S
        depends on !MACH_SUN9I
        depends on !MACH_SUN50I
+       depends on !MACH_SUN50I_H6
        select VIDEO
        imply VIDEO_DT_SIMPLEFB
        default y
@@ -945,6 +961,7 @@ config SPL_STACK_R_ADDR
        default 0x4fe00000 if MACH_SUN8I
        default 0x2fe00000 if MACH_SUN9I
        default 0x4fe00000 if MACH_SUN50I
+       default 0x4fe00000 if MACH_SUN50I_H6
 
 config SPL_SPI_SUNXI
        bool "Support for SPI Flash on Allwinner SoCs in SPL"
index 4c752491a15313f1797b7e6b440dad876c7e0933..43a93e3085724f4412bc72f6fb2b28c4b92530e8 100644 (file)
@@ -26,6 +26,7 @@ else
 obj-$(CONFIG_MACH_SUN8I)       += clock_sun6i.o
 endif
 obj-$(CONFIG_MACH_SUN9I)       += clock_sun9i.o gtbus_sun9i.o
+obj-$(CONFIG_MACH_SUN50I_H6)   += clock_sun50i_h6.o
 
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_DRAM_SUN4I)       += dram_sun4i.o
@@ -37,4 +38,5 @@ obj-$(CONFIG_DRAM_SUN9I)      += dram_sun9i.o
 obj-$(CONFIG_SPL_SPI_SUNXI)    += spl_spi_sunxi.o
 obj-$(CONFIG_SUNXI_DRAM_DW)    += dram_sunxi_dw.o
 obj-$(CONFIG_SUNXI_DRAM_DW)    += dram_timings/
+obj-$(CONFIG_DRAM_SUN50I_H6)   += dram_sun50i_h6.o
 endif
index 58fef05bd737b57bdcc27b90087bfe1fb4421ab6..d22a84ea6babb068c247cf08ae04b02d91cd241a 100644 (file)
@@ -107,6 +107,10 @@ static int gpio_init(void)
        sunxi_gpio_set_cfgpin(SUNXI_GPB(8), SUN50I_GPB_UART0);
        sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN50I_GPB_UART0);
        sunxi_gpio_set_pull(SUNXI_GPB(9), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN50I_H6)
+       sunxi_gpio_set_cfgpin(SUNXI_GPH(0), SUN50I_H6_GPH_UART0);
+       sunxi_gpio_set_cfgpin(SUNXI_GPH(1), SUN50I_H6_GPH_UART0);
+       sunxi_gpio_set_pull(SUNXI_GPH(1), SUNXI_GPIO_PULL_UP);
 #elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_A83T)
        sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN8I_A83T_GPB_UART0);
        sunxi_gpio_set_cfgpin(SUNXI_GPB(10), SUN8I_A83T_GPB_UART0);
@@ -282,7 +286,7 @@ void reset_cpu(ulong addr)
                /* sun5i sometimes gets stuck without this */
                writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
        }
-#elif defined(CONFIG_SUNXI_GEN_SUN6I)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
        static const struct sunxi_wdog *wdog =
                 ((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
 
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
new file mode 100644 (file)
index 0000000..ba8a26e
--- /dev/null
@@ -0,0 +1,94 @@
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/clock.h>
+
+#ifdef CONFIG_SPL_BUILD
+void clock_init_safe(void)
+{
+       struct sunxi_ccm_reg *const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+       clock_set_pll1(408000000);
+
+       writel(CCM_PLL6_DEFAULT, &ccm->pll6_cfg);
+       while (!(readl(&ccm->pll6_cfg) & CCM_PLL6_LOCK))
+               ;
+
+       clrsetbits_le32(&ccm->cpu_axi_cfg, CCM_CPU_AXI_APB_MASK | CCM_CPU_AXI_AXI_MASK,
+                       CCM_CPU_AXI_DEFAULT_FACTORS);
+
+       writel(CCM_PSI_AHB1_AHB2_DEFAULT, &ccm->psi_ahb1_ahb2_cfg);
+       writel(CCM_AHB3_DEFAULT, &ccm->ahb3_cfg);
+       writel(CCM_APB1_DEFAULT, &ccm->apb1_cfg);
+
+       /*
+        * The mux and factor are set, but the clock will be enabled in
+        * DRAM initialization code.
+        */
+       writel(MBUS_CLK_SRC_PLL6X2 | MBUS_CLK_M(3), &ccm->mbus_cfg);
+}
+#endif
+
+void clock_init_uart(void)
+{
+       struct sunxi_ccm_reg *const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+       /* uart clock source is apb2 */
+       writel(APB2_CLK_SRC_OSC24M|
+              APB2_CLK_RATE_N_1|
+              APB2_CLK_RATE_M(1),
+              &ccm->apb2_cfg);
+
+       /* open the clock for uart */
+       setbits_le32(&ccm->uart_gate_reset,
+                    1 << (CONFIG_CONS_INDEX - 1));
+
+       /* deassert uart reset */
+       setbits_le32(&ccm->uart_gate_reset,
+                    1 << (RESET_SHIFT + CONFIG_CONS_INDEX - 1));
+}
+
+#ifdef CONFIG_SPL_BUILD
+void clock_set_pll1(unsigned int clk)
+{
+       struct sunxi_ccm_reg * const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+       u32 val;
+
+       /* Do not support clocks < 288MHz as they need factor P */
+       if (clk < 288000000) clk = 288000000;
+
+       /* Switch to 24MHz clock while changing PLL1 */
+       val = readl(&ccm->cpu_axi_cfg);
+       val &= ~CCM_CPU_AXI_MUX_MASK;
+       val |= CCM_CPU_AXI_MUX_OSC24M;
+       writel(val, &ccm->cpu_axi_cfg);
+
+       /* clk = 24*n/p, p is ignored if clock is >288MHz */
+       writel(CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2 |
+              CCM_PLL1_CTRL_N(clk / 24000000), &ccm->pll1_cfg);
+       while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
+
+       /* Switch CPU to PLL1 */
+       val = readl(&ccm->cpu_axi_cfg);
+       val &= ~CCM_CPU_AXI_MUX_MASK;
+       val |= CCM_CPU_AXI_MUX_PLL_CPUX;
+       writel(val, &ccm->cpu_axi_cfg);
+}
+#endif
+
+unsigned int clock_get_pll6(void)
+{
+       struct sunxi_ccm_reg *const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+       uint32_t rval = readl(&ccm->pll6_cfg);
+       int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT);
+       int div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
+                       CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
+       int div2 = ((rval & CCM_PLL6_CTRL_DIV2_MASK) >>
+                       CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
+       /* The register defines PLL6-4X, not plain PLL6 */
+       return 24000000 / 4 * n / div1 / div2;
+}
index aadf575ef2b05435a5f082eec5fbdec87b352cf3..ae4745bfeccaab0815bd4fc05b60d4526e616bb0 100644 (file)
@@ -96,6 +96,8 @@ int print_cpuinfo(void)
        puts("CPU:   Allwinner A64 (SUN50I)\n");
 #elif defined CONFIG_MACH_SUN50I_H5
        puts("CPU:   Allwinner H5 (SUN50I)\n");
+#elif defined CONFIG_MACH_SUN50I_H6
+       puts("CPU:   Allwinner H6 (SUN50I)\n");
 #else
 #warning Please update cpu_info.c with correct CPU information
        puts("CPU:   SUNXI Family\n");
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
new file mode 100644 (file)
index 0000000..6b94cf3
--- /dev/null
@@ -0,0 +1,755 @@
+/*
+ * sun50i H6 platform dram controller init
+ *
+ * (C) Copyright 2017      Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/cpu.h>
+#include <linux/bitops.h>
+#include <linux/kconfig.h>
+
+/*
+ * The DRAM controller structure on H6 is similar to the ones on A23/A80:
+ * they all contains 3 parts, COM, CTL and PHY. (As a note on A33/A83T/H3/A64
+ * /H5/R40 CTL and PHY is composed).
+ *
+ * COM is allwinner-specific. On H6, the address mapping function is moved
+ * from COM to CTL (with the standard ADDRMAP registers on DesignWare memory
+ * controller).
+ *
+ * CTL (controller) and PHY is from DesignWare.
+ *
+ * The CTL part is a bit similar to the one on A23/A80 (because they all
+ * originate from DesignWare), but gets more registers added.
+ *
+ * The PHY part is quite new, not seen in any previous Allwinner SoCs, and
+ * not seen on other SoCs in U-Boot. The only SoC that is also known to have
+ * similar PHY is ZynqMP.
+ */
+
+/*
+ * The delay parameters below allow to allegedly specify delay times of some
+ * unknown unit for each individual bit trace in each of the four data bytes
+ * the 32-bit wide access consists of. Also three control signals can be
+ * adjusted individually.
+ */
+#define NR_OF_BYTE_LANES       (32 / BITS_PER_BYTE)
+/* The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable and DQSN */
+#define WR_LINES_PER_BYTE_LANE (BITS_PER_BYTE + 4)
+/*
+ * The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable, DQSN,
+ * Termination and Power down
+ */
+#define RD_LINES_PER_BYTE_LANE (BITS_PER_BYTE + 6)
+struct dram_para {
+       u32 clk;
+       enum sunxi_dram_type type;
+       u8 cols;
+       u8 rows;
+       u8 ranks;
+       const u8 dx_read_delays[NR_OF_BYTE_LANES][RD_LINES_PER_BYTE_LANE];
+       const u8 dx_write_delays[NR_OF_BYTE_LANES][WR_LINES_PER_BYTE_LANE];
+};
+
+static void mctl_sys_init(struct dram_para *para);
+static void mctl_com_init(struct dram_para *para);
+static void mctl_set_timing_lpddr3(struct dram_para *para);
+static void mctl_channel_init(struct dram_para *para);
+
+static void mctl_core_init(struct dram_para *para)
+{
+       mctl_sys_init(para);
+       mctl_com_init(para);
+       switch (para->type) {
+       case SUNXI_DRAM_TYPE_LPDDR3:
+               mctl_set_timing_lpddr3(para);
+               break;
+       default:
+               panic("Unsupported DRAM type!");
+       };
+       mctl_channel_init(para);
+}
+
+static void mctl_phy_pir_init(u32 val)
+{
+       struct sunxi_mctl_phy_reg * const mctl_phy =
+                       (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+
+       writel(val | BIT(0), &mctl_phy->pir);
+       mctl_await_completion(&mctl_phy->pgsr[0], BIT(0), BIT(0));
+}
+
+enum {
+       MBUS_PORT_CPU           = 0,
+       MBUS_PORT_GPU           = 1,
+       MBUS_PORT_MAHB          = 2,
+       MBUS_PORT_DMA           = 3,
+       MBUS_PORT_VE            = 4,
+       MBUS_PORT_CE            = 5,
+       MBUS_PORT_TSC0          = 6,
+       MBUS_PORT_NDFC0         = 8,
+       MBUS_PORT_CSI0          = 11,
+       MBUS_PORT_DI0           = 14,
+       MBUS_PORT_DI1           = 15,
+       MBUS_PORT_DE300         = 16,
+       MBUS_PORT_IOMMU         = 25,
+       MBUS_PORT_VE2           = 26,
+       MBUS_PORT_USB3        = 37,
+       MBUS_PORT_PCIE          = 38,
+       MBUS_PORT_VP9           = 39,
+       MBUS_PORT_HDCP2       = 40,
+};
+
+enum {
+       MBUS_QOS_LOWEST = 0,
+       MBUS_QOS_LOW,
+       MBUS_QOS_HIGH,
+       MBUS_QOS_HIGHEST
+};
+inline void mbus_configure_port(u8 port,
+                               bool bwlimit,
+                               bool priority,
+                               u8 qos,
+                               u8 waittime,
+                               u8 acs,
+                               u16 bwl0,
+                               u16 bwl1,
+                               u16 bwl2)
+{
+       struct sunxi_mctl_com_reg * const mctl_com =
+                       (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+
+       const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
+                          | (priority ? (1 << 1) : 0)
+                          | ((qos & 0x3) << 2)
+                          | ((waittime & 0xf) << 4)
+                          | ((acs & 0xff) << 8)
+                          | (bwl0 << 16) );
+       const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
+
+       debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
+       writel(cfg0, &mctl_com->master[port].cfg0);
+       writel(cfg1, &mctl_com->master[port].cfg1);
+}
+
+#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2)   \
+       mbus_configure_port(MBUS_PORT_ ## port, bwlimit, false, \
+                           MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
+
+static void mctl_set_master_priority(void)
+{
+       struct sunxi_mctl_com_reg * const mctl_com =
+                       (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+
+       /* enable bandwidth limit windows and set windows size 1us */
+       writel(399, &mctl_com->tmr);
+       writel(BIT(16), &mctl_com->bwcr);
+
+       MBUS_CONF(  CPU,  true, HIGHEST, 0,  256,  128,  100);
+       MBUS_CONF(  GPU,  true,    HIGH, 0, 1536, 1400,  256);
+       MBUS_CONF( MAHB,  true, HIGHEST, 0,  512,  256,   96);
+       MBUS_CONF(  DMA,  true,    HIGH, 0,  256,  100,   80);
+       MBUS_CONF(   VE,  true,    HIGH, 2, 8192, 5500, 5000);
+       MBUS_CONF(   CE,  true,    HIGH, 2,  100,   64,   32);
+       MBUS_CONF( TSC0,  true,    HIGH, 2,  100,   64,   32);
+       MBUS_CONF(NDFC0,  true,    HIGH, 0,  256,  128,   64);
+       MBUS_CONF( CSI0,  true,    HIGH, 0,  256,  128,  100);
+       MBUS_CONF(  DI0,  true,    HIGH, 0, 1024,  256,   64);
+       MBUS_CONF(DE300,  true, HIGHEST, 6, 8192, 2800, 2400);
+       MBUS_CONF(IOMMU,  true, HIGHEST, 0,  100,   64,   32);
+       MBUS_CONF(  VE2,  true,    HIGH, 2, 8192, 5500, 5000);
+       MBUS_CONF( USB3,  true,    HIGH, 0,  256,  128,   64);
+       MBUS_CONF( PCIE,  true,    HIGH, 2,  100,   64,   32);
+       MBUS_CONF(  VP9,  true,    HIGH, 2, 8192, 5500, 5000);
+       MBUS_CONF(HDCP2,  true,    HIGH, 2,  100,   64,   32);
+}
+
+static u32 mr_lpddr3[12] = {
+       0x00000000, 0x00000043, 0x0000001a, 0x00000001,
+       0x00000000, 0x00000000, 0x00000048, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000003,
+};
+
+/* TODO: flexible timing */
+static void mctl_set_timing_lpddr3(struct dram_para *para)
+{
+       struct sunxi_mctl_ctl_reg * const mctl_ctl =
+                       (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+       struct sunxi_mctl_phy_reg * const mctl_phy =
+                       (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+
+       u8 tccd         = 2;
+       u8 tfaw         = max(ns_to_t(50), 4);
+       u8 trrd         = max(ns_to_t(10), 2);
+       u8 trcd         = max(ns_to_t(24), 2);
+       u8 trc          = ns_to_t(70);
+       u8 txp          = max(ns_to_t(8), 2);
+       u8 twtr         = max(ns_to_t(8), 2);
+       u8 trtp         = max(ns_to_t(8), 2);
+       u8 twr          = max(ns_to_t(15), 2);
+       u8 trp          = ns_to_t(18);
+       u8 tras         = ns_to_t(42);
+       u8 twtr_sa      = ns_to_t(5);
+       u8 tcksrea      = ns_to_t(11);
+       u16 trefi       = ns_to_t(3900) / 32;
+       u16 trfc        = ns_to_t(210);
+       u16 txsr        = ns_to_t(220);
+
+       if (CONFIG_DRAM_CLK % 400 == 0) {
+               /* Round up these parameters */
+               twtr_sa++;
+               tcksrea++;
+       }
+
+       u8 tmrw         = 5;
+       u8 tmrd         = 5;
+       u8 tmod         = 12;
+       u8 tcke         = 3;
+       u8 tcksrx       = 5;
+       u8 tcksre       = 5;
+       u8 tckesr       = 5;
+       u8 trasmax      = CONFIG_DRAM_CLK / 60;
+       u8 txs          = 4;
+       u8 txsdll       = 4;
+       u8 txsabort     = 4;
+       u8 txsfast      = 4;
+
+       u8 tcl          = 5; /* CL 10 */
+       u8 tcwl         = 3; /* CWL 6 */
+       u8 t_rdata_en   = twtr_sa + 8;
+
+       u32 tdinit0     = (200 * CONFIG_DRAM_CLK) + 1;          /* 200us */
+       u32 tdinit1     = (100 * CONFIG_DRAM_CLK) / 1000 + 1;   /* 100ns */
+       u32 tdinit2     = (11 * CONFIG_DRAM_CLK) + 1;           /* 11us */
+       u32 tdinit3     = (1 * CONFIG_DRAM_CLK) + 1;            /* 1us */
+
+       u8 twtp         = tcwl + 4 + twr + 1;
+       /*
+        * The code below for twr2rd and trd2wr follows the IP core's
+        * document from ZynqMP and i.MX7. The BSP has both number
+        * substracted by 2.
+        */
+       u8 twr2rd       = tcwl + 4 + 1 + twtr;
+       u8 trd2wr       = tcl + 4 + (tcksrea >> 1) - tcwl + 1;
+
+       /* set mode register */
+       memcpy(mctl_phy->mr, mr_lpddr3, sizeof(mr_lpddr3));
+
+       /* set DRAM timing */
+       writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
+              &mctl_ctl->dramtmg[0]);
+       writel((txp << 16) | (trtp << 8) | trc, &mctl_ctl->dramtmg[1]);
+       writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | twr2rd,
+              &mctl_ctl->dramtmg[2]);
+       writel((tmrw << 20) | (tmrd << 12) | tmod, &mctl_ctl->dramtmg[3]);
+       writel((trcd << 24) | (tccd << 16) | (trrd << 8) | trp,
+              &mctl_ctl->dramtmg[4]);
+       writel((tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | tcke,
+              &mctl_ctl->dramtmg[5]);
+       /* Value suggested by ZynqMP manual and used by libdram */
+       writel((txp + 2) | 0x02020000, &mctl_ctl->dramtmg[6]);
+       writel((txsfast << 24) | (txsabort << 16) | (txsdll << 8) | txs,
+              &mctl_ctl->dramtmg[8]);
+       writel(txsr, &mctl_ctl->dramtmg[14]);
+
+       clrsetbits_le32(&mctl_ctl->init[0], (3 << 30), (1 << 30));
+       writel(0, &mctl_ctl->dfimisc);
+       clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
+
+       /*
+        * Set timing registers of the PHY.
+        * Note: the PHY is clocked 2x from the DRAM frequency.
+        */
+       writel((trrd << 25) | (tras << 17) | (trp << 9) | (trtp << 1),
+              &mctl_phy->dtpr[0]);
+       writel((tfaw << 17) | 0x28000400 | (tmrd << 1), &mctl_phy->dtpr[1]);
+       writel(((txs << 6) - 1) | (tcke << 17), &mctl_phy->dtpr[2]);
+       writel(((txsdll << 22) - (0x1 << 16)) | twtr_sa | (tcksrea << 8),
+              &mctl_phy->dtpr[3]);
+       writel((txp << 1) | (trfc << 17) | 0x800, &mctl_phy->dtpr[4]);
+       writel((trc << 17) | (trcd << 9) | (twtr << 1), &mctl_phy->dtpr[5]);
+       writel(0x0505, &mctl_phy->dtpr[6]);
+
+       /* Configure DFI timing */
+       writel(tcl | 0x2000200 | (t_rdata_en << 16) | 0x808000,
+              &mctl_ctl->dfitmg0);
+       writel(0x040201, &mctl_ctl->dfitmg1);
+
+       /* Configure PHY timing */
+       writel(tdinit0 | (tdinit1 << 20), &mctl_phy->ptr[3]);
+       writel(tdinit2 | (tdinit3 << 18), &mctl_phy->ptr[4]);
+
+       /* set refresh timing */
+       writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
+}
+
+static void mctl_sys_init(struct dram_para *para)
+{
+       struct sunxi_ccm_reg * const ccm =
+                       (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+       struct sunxi_mctl_com_reg * const mctl_com =
+                       (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+       struct sunxi_mctl_ctl_reg * const mctl_ctl =
+                       (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+       /* Put all DRAM-related blocks to reset state */
+       clrbits_le32(&ccm->mbus_cfg, MBUS_ENABLE | MBUS_RESET);
+       writel(0, &ccm->dram_gate_reset);
+       clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
+       clrbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
+
+       udelay(5);
+
+       /* Set PLL5 rate to doubled DRAM clock rate */
+       writel(CCM_PLL5_CTRL_EN | CCM_PLL5_LOCK_EN |
+              CCM_PLL5_CTRL_N(para->clk * 2 / 24 - 1), &ccm->pll5_cfg);
+       mctl_await_completion(&ccm->pll5_cfg, CCM_PLL5_LOCK, CCM_PLL5_LOCK);
+
+       /* Configure DRAM mod clock */
+       writel(DRAM_CLK_SRC_PLL5, &ccm->dram_clk_cfg);
+       setbits_le32(&ccm->dram_clk_cfg, DRAM_CLK_UPDATE);
+       writel(BIT(0) | BIT(RESET_SHIFT), &ccm->dram_gate_reset);
+
+       /* Disable all channels */
+       writel(0, &mctl_com->maer0);
+       writel(0, &mctl_com->maer1);
+       writel(0, &mctl_com->maer2);
+
+       /* Configure MBUS and enable DRAM mod reset */
+       setbits_le32(&ccm->mbus_cfg, MBUS_RESET);
+       setbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
+       setbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
+       udelay(5);
+
+       /* Unknown hack from the BSP, which enables access of mctl_ctl regs */
+       writel(0x8000, &mctl_ctl->unk_0x00c);
+}
+
+static void mctl_set_addrmap(struct dram_para *para)
+{
+       struct sunxi_mctl_ctl_reg * const mctl_ctl =
+                       (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+       u8 cols = para->cols;
+       u8 rows = para->rows;
+       u8 ranks = para->ranks;
+
+       /* Ranks */
+       if (ranks == 2)
+               mctl_ctl->addrmap[0] = rows + cols - 3;
+       else
+               mctl_ctl->addrmap[0] = 0x1F;
+
+       /* Banks, hardcoded to 8 banks now */
+       mctl_ctl->addrmap[1] = (cols - 2) | (cols - 2) << 8 | (cols - 2) << 16;
+
+       /* Columns */
+       mctl_ctl->addrmap[2] = 0;
+       switch (cols) {
+       case 8:
+               mctl_ctl->addrmap[3] = 0x1F1F0000;
+               mctl_ctl->addrmap[4] = 0x1F1F;
+               break;
+       case 9:
+               mctl_ctl->addrmap[3] = 0x1F000000;
+               mctl_ctl->addrmap[4] = 0x1F1F;
+               break;
+       case 10:
+               mctl_ctl->addrmap[3] = 0;
+               mctl_ctl->addrmap[4] = 0x1F1F;
+               break;
+       case 11:
+               mctl_ctl->addrmap[3] = 0;
+               mctl_ctl->addrmap[4] = 0x1F00;
+               break;
+       case 12:
+               mctl_ctl->addrmap[3] = 0;
+               mctl_ctl->addrmap[4] = 0;
+               break;
+       default:
+               panic("Unsupported DRAM configuration: column number invalid\n");
+       }
+
+       /* Rows */
+       mctl_ctl->addrmap[5] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
+       switch (rows) {
+       case 13:
+               mctl_ctl->addrmap[6] = (cols - 3) | 0x0F0F0F00;
+               mctl_ctl->addrmap[7] = 0x0F0F;
+               break;
+       case 14:
+               mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | 0x0F0F0000;
+               mctl_ctl->addrmap[7] = 0x0F0F;
+               break;
+       case 15:
+               mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | 0x0F000000;
+               mctl_ctl->addrmap[7] = 0x0F0F;
+               break;
+       case 16:
+               mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
+               mctl_ctl->addrmap[7] = 0x0F0F;
+               break;
+       case 17:
+               mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
+               mctl_ctl->addrmap[7] = (cols - 3) | 0x0F00;
+               break;
+       case 18:
+               mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
+               mctl_ctl->addrmap[7] = (cols - 3) | ((cols - 3) << 8);
+               break;
+       default:
+               panic("Unsupported DRAM configuration: row number invalid\n");
+       }
+
+       /* Bank groups, DDR4 only */
+       mctl_ctl->addrmap[8] = 0x3F3F;
+}
+
+static void mctl_com_init(struct dram_para *para)
+{
+       struct sunxi_mctl_com_reg * const mctl_com =
+                       (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+       struct sunxi_mctl_ctl_reg * const mctl_ctl =
+                       (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+       struct sunxi_mctl_phy_reg * const mctl_phy =
+                       (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+       u32 reg_val, tmp;
+
+       mctl_set_addrmap(para);
+
+       setbits_le32(&mctl_com->cr, BIT(31));
+       /*
+        * This address is magic; it's in SID memory area, but there's no
+        * known definition of it.
+        * On my Pine H64 board it has content 7.
+        */
+       if (readl(0x03006100) == 7)
+               clrbits_le32(&mctl_com->cr, BIT(27));
+       else if (readl(0x03006100) == 3)
+               setbits_le32(&mctl_com->cr, BIT(27));
+
+       if (para->clk > 408)
+               reg_val = 0xf00;
+       else if (para->clk > 246)
+               reg_val = 0x1f00;
+       else
+               reg_val = 0x3f00;
+       clrsetbits_le32(&mctl_com->unk_0x008, 0x3f00, reg_val);
+
+       /* TODO: half DQ, non-LPDDR3 types */
+       writel(MSTR_DEVICETYPE_LPDDR3 | MSTR_BUSWIDTH_FULL |
+              MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(para->ranks) |
+              0x80000000, &mctl_ctl->mstr);
+       writel(DCR_LPDDR3 | DCR_DDR8BANK | 0x400, &mctl_phy->dcr);
+
+       if (para->ranks == 2)
+               writel(0x0303, &mctl_ctl->odtmap);
+       else
+               writel(0x0201, &mctl_ctl->odtmap);
+
+       /* TODO: non-LPDDR3 types */
+       tmp = para->clk * 7 / 2000;
+       reg_val = 0x0400;
+       reg_val |= (tmp + 7) << 24;
+       reg_val |= (((para->clk < 400) ? 3 : 4) - tmp) << 16;
+       writel(reg_val, &mctl_ctl->odtcfg);
+
+       /* TODO: half DQ */
+}
+
+static void mctl_bit_delay_set(struct dram_para *para)
+{
+       struct sunxi_mctl_phy_reg * const mctl_phy =
+                       (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+       int i, j;
+       u32 val;
+
+       for (i = 0; i < 4; i++) {
+               val = readl(&mctl_phy->dx[i].bdlr0);
+               for (j = 0; j < 4; j++)
+                       val += para->dx_write_delays[i][j] << (j * 8);
+               writel(val, &mctl_phy->dx[i].bdlr0);
+
+               val = readl(&mctl_phy->dx[i].bdlr1);
+               for (j = 0; j < 4; j++)
+                       val += para->dx_write_delays[i][j + 4] << (j * 8);
+               writel(val, &mctl_phy->dx[i].bdlr1);
+
+               val = readl(&mctl_phy->dx[i].bdlr2);
+               for (j = 0; j < 4; j++)
+                       val += para->dx_write_delays[i][j + 8] << (j * 8);
+               writel(val, &mctl_phy->dx[i].bdlr2);
+       }
+       clrbits_le32(&mctl_phy->pgcr[0], BIT(26));
+
+       for (i = 0; i < 4; i++) {
+               val = readl(&mctl_phy->dx[i].bdlr3);
+               for (j = 0; j < 4; j++)
+                       val += para->dx_read_delays[i][j] << (j * 8);
+               writel(val, &mctl_phy->dx[i].bdlr3);
+
+               val = readl(&mctl_phy->dx[i].bdlr4);
+               for (j = 0; j < 4; j++)
+                       val += para->dx_read_delays[i][j + 4] << (j * 8);
+               writel(val, &mctl_phy->dx[i].bdlr4);
+
+               val = readl(&mctl_phy->dx[i].bdlr5);
+               for (j = 0; j < 4; j++)
+                       val += para->dx_read_delays[i][j + 8] << (j * 8);
+               writel(val, &mctl_phy->dx[i].bdlr5);
+
+               val = readl(&mctl_phy->dx[i].bdlr6);
+               val += (para->dx_read_delays[i][12] << 8) |
+                      (para->dx_read_delays[i][13] << 16);
+               writel(val, &mctl_phy->dx[i].bdlr6);
+       }
+       setbits_le32(&mctl_phy->pgcr[0], BIT(26));
+       udelay(1);
+
+       for (i = 1; i < 14; i++) {
+               val = readl(&mctl_phy->acbdlr[i]);
+               val += 0x0a0a0a0a;
+               writel(val, &mctl_phy->acbdlr[i]);
+       }
+}
+
+static void mctl_channel_init(struct dram_para *para)
+{
+       struct sunxi_mctl_com_reg * const mctl_com =
+                       (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+       struct sunxi_mctl_ctl_reg * const mctl_ctl =
+                       (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+       struct sunxi_mctl_phy_reg * const mctl_phy =
+                       (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+       int i;
+       u32 val;
+
+       setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
+       setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
+       writel(0x2f05, &mctl_ctl->sched[0]);
+       setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
+       setbits_le32(&mctl_ctl->dfimisc, BIT(0));
+       setbits_le32(&mctl_ctl->unk_0x00c, BIT(8));
+       clrsetbits_le32(&mctl_phy->pgcr[1], 0x180, 0xc0);
+       /* TODO: non-LPDDR3 types */
+       clrsetbits_le32(&mctl_phy->pgcr[2], GENMASK(17, 0), ns_to_t(7800));
+       clrbits_le32(&mctl_phy->pgcr[6], BIT(0));
+       clrsetbits_le32(&mctl_phy->dxccr, 0xee0, 0x220);
+       /* TODO: VT compensation */
+       clrsetbits_le32(&mctl_phy->dsgcr, BIT(0), 0x440060);
+       clrbits_le32(&mctl_phy->vtcr[1], BIT(1));
+
+       for (i = 0; i < 4; i++)
+               clrsetbits_le32(&mctl_phy->dx[i].gcr[0], 0xe00, 0x800);
+       for (i = 0; i < 4; i++)
+               clrsetbits_le32(&mctl_phy->dx[i].gcr[2], 0xffff, 0x5555);
+       for (i = 0; i < 4; i++)
+               clrsetbits_le32(&mctl_phy->dx[i].gcr[3], 0x3030, 0x1010);
+
+       udelay(100);
+
+       if (para->ranks == 2)
+               setbits_le32(&mctl_phy->dtcr[1], 0x30000);
+       else
+               clrsetbits_le32(&mctl_phy->dtcr[1], 0x30000, 0x10000);
+
+       clrbits_le32(&mctl_phy->dtcr[1], BIT(1));
+       if (para->ranks == 2) {
+               writel(0x00010001, &mctl_phy->rankidr);
+               writel(0x20000, &mctl_phy->odtcr);
+       } else {
+               writel(0x0, &mctl_phy->rankidr);
+               writel(0x10000, &mctl_phy->odtcr);
+       }
+
+       /* TODO: non-LPDDR3 types */
+       clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000, 0x10000040);
+       if (para->clk <= 792) {
+               if (para->clk <= 672) {
+                       if (para->clk <= 600)
+                               val = 0x300;
+                       else
+                               val = 0x400;
+               } else {
+                       val = 0x500;
+               }
+       } else {
+               val = 0x600;
+       }
+       /* FIXME: NOT REVIEWED YET */
+       clrsetbits_le32(&mctl_phy->zq[0].zqcr, 0x700, val);
+       clrsetbits_le32(&mctl_phy->zq[0].zqpr[0], 0xff,
+                       CONFIG_DRAM_ZQ & 0xff);
+       clrbits_le32(&mctl_phy->zq[0].zqor[0], 0xfffff);
+       setbits_le32(&mctl_phy->zq[0].zqor[0], (CONFIG_DRAM_ZQ >> 8) & 0xff);
+       setbits_le32(&mctl_phy->zq[0].zqor[0], (CONFIG_DRAM_ZQ & 0xf00) - 0x100);
+       setbits_le32(&mctl_phy->zq[0].zqor[0], (CONFIG_DRAM_ZQ & 0xff00) << 4);
+       clrbits_le32(&mctl_phy->zq[1].zqpr[0], 0xfffff);
+       setbits_le32(&mctl_phy->zq[1].zqpr[0], (CONFIG_DRAM_ZQ >> 16) & 0xff);
+       setbits_le32(&mctl_phy->zq[1].zqpr[0], ((CONFIG_DRAM_ZQ >> 8) & 0xf00) - 0x100);
+       setbits_le32(&mctl_phy->zq[1].zqpr[0], (CONFIG_DRAM_ZQ & 0xff0000) >> 4);
+       if (para->type == SUNXI_DRAM_TYPE_LPDDR3) {
+               for (i = 1; i < 14; i++)
+                       writel(0x06060606, &mctl_phy->acbdlr[i]);
+       }
+
+       /* TODO: non-LPDDR3 types */
+       mctl_phy_pir_init(PIR_ZCAL | PIR_DCAL | PIR_PHYRST | PIR_DRAMINIT |
+                         PIR_QSGATE | PIR_RDDSKW | PIR_WRDSKW | PIR_RDEYE |
+                         PIR_WREYE);
+
+       /* TODO: non-LPDDR3 types */
+       for (i = 0; i < 4; i++)
+               writel(0x00000909, &mctl_phy->dx[i].gcr[5]);
+
+       for (i = 0; i < 4; i++) {
+               if (IS_ENABLED(CONFIG_DRAM_ODT_EN))
+                       val = 0x0;
+               else
+                       val = 0xaaaa;
+               clrsetbits_le32(&mctl_phy->dx[i].gcr[2], 0xffff, val);
+
+               if (IS_ENABLED(CONFIG_DRAM_ODT_EN))
+                       val = 0x0;
+               else
+                       val = 0x2020;
+               clrsetbits_le32(&mctl_phy->dx[i].gcr[3], 0x3030, val);
+       }
+
+       mctl_bit_delay_set(para);
+       udelay(1);
+
+       setbits_le32(&mctl_phy->pgcr[6], BIT(0));
+       clrbits_le32(&mctl_phy->pgcr[6], 0xfff8);
+       for (i = 0; i < 4; i++)
+               clrbits_le32(&mctl_phy->dx[i].gcr[3], ~0x3ffff);
+       udelay(10);
+
+       if (readl(&mctl_phy->pgsr[0]) & 0x400000)
+       {
+               /*
+                * Detect single rank.
+                * TODO: also detect half DQ.
+                */
+               if ((readl(&mctl_phy->dx[0].rsr[0]) & 0x3) == 2 &&
+                   (readl(&mctl_phy->dx[1].rsr[0]) & 0x3) == 2 &&
+                   (readl(&mctl_phy->dx[2].rsr[0]) & 0x3) == 2 &&
+                   (readl(&mctl_phy->dx[3].rsr[0]) & 0x3) == 2) {
+                       para->ranks = 1;
+                       /* Restart DRAM initialization from scratch. */
+                       mctl_core_init(para);
+                       return;
+               }
+               else {
+                       panic("This DRAM setup is currently not supported.\n");
+               }
+       }
+
+       if (readl(&mctl_phy->pgsr[0]) & 0xff00000) {
+               /* Oops! There's something wrong! */
+               debug("PLL = %x\n", readl(0x3001010));
+               debug("DRAM PHY PGSR0 = %x\n", readl(&mctl_phy->pgsr[0]));
+               for (i = 0; i < 4; i++)
+                       debug("DRAM PHY DX%dRSR0 = %x\n", i, readl(&mctl_phy->dx[i].rsr[0]));
+               panic("Error while initializing DRAM PHY!\n");
+       }
+
+       clrsetbits_le32(&mctl_phy->dsgcr, 0xc0, 0x40);
+       clrbits_le32(&mctl_phy->pgcr[1], 0x40);
+       clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
+       writel(1, &mctl_ctl->swctl);
+       mctl_await_completion(&mctl_ctl->swstat, 1, 1);
+       clrbits_le32(&mctl_ctl->rfshctl3, BIT(0));
+
+       setbits_le32(&mctl_com->unk_0x014, BIT(31));
+       writel(0xffffffff, &mctl_com->maer0);
+       writel(0x7ff, &mctl_com->maer1);
+       writel(0xffff, &mctl_com->maer2);
+}
+
+static void mctl_auto_detect_dram_size(struct dram_para *para)
+{
+       /* TODO: non-LPDDR3, half DQ */
+       /*
+        * Detect rank number by the code in mctl_channel_init. Furtherly
+        * when DQ detection is available it will also be executed there.
+        */
+       mctl_core_init(para);
+
+       /* detect row address bits */
+       para->cols = 8;
+       para->rows = 18;
+       mctl_core_init(para);
+
+       for (para->rows = 13; para->rows < 18; para->rows++) {
+               /* 8 banks, 8 bit per byte and 32 bit width */
+               if (mctl_mem_matches((1 << (para->rows + para->cols + 5))))
+                       break;
+       }
+
+       /* detect column address bits */
+       para->cols = 11;
+       mctl_core_init(para);
+
+       for (para->cols = 8; para->cols < 11; para->cols++) {
+               /* 8 bits per byte and 32 bit width */
+               if (mctl_mem_matches(1 << (para->cols + 2)))
+                       break;
+       }
+}
+
+unsigned long mctl_calc_size(struct dram_para *para)
+{
+       /* TODO: non-LPDDR3, half DQ */
+
+       /* 8 banks, 32-bit (4 byte) data width */
+       return (1ULL << (para->cols + para->rows + 3)) * 4 * para->ranks;
+}
+
+#define SUN50I_H6_DX_WRITE_DELAYS                              \
+       {{  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },    \
+        {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },    \
+        {  0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  4,  0 },    \
+        {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
+#define SUN50I_H6_DX_READ_DELAYS                                       \
+       {{  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },    \
+        {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },    \
+        {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },    \
+        {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 }}
+
+unsigned long sunxi_dram_init(void)
+{
+       struct sunxi_mctl_com_reg * const mctl_com =
+                       (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+       struct dram_para para = {
+               .clk = CONFIG_DRAM_CLK,
+               .type = SUNXI_DRAM_TYPE_LPDDR3,
+               .ranks = 2,
+               .cols = 11,
+               .rows = 14,
+               .dx_read_delays  = SUN50I_H6_DX_READ_DELAYS,
+               .dx_write_delays = SUN50I_H6_DX_WRITE_DELAYS,
+       };
+
+       unsigned long size;
+
+       /* RES_CAL_CTRL_REG in BSP U-boot*/
+       setbits_le32(0x7010310, BIT(8));
+       clrbits_le32(0x7010318, 0x3f);
+
+       mctl_auto_detect_dram_size(&para);
+
+       mctl_core_init(&para);
+
+       size = mctl_calc_size(&para);
+
+       clrsetbits_le32(&mctl_com->cr, 0xf0, (size >> (10 + 10 + 4)) & 0xf0);
+
+       mctl_set_master_priority();
+
+       return size;
+};
index cefa93001ba18c1fa3ac92a6bc9c933a13384a96..fafd306f95b11e242ea156c33636039c2fad761a 100644 (file)
 @ reference and to be able to regenerate a (probably fixed) version of this
 @ code found in encoded form in boot0.h.
 
+#include <config.h>
+
 .text
 
+#ifndef CONFIG_MACH_SUN50I_H6
        ldr     r1, =0x017000a0         @ MMIO mapped RVBAR[0] register
+#else
+       ldr     r1, =0x09010040         @ MMIO mapped RVBAR[0] register
+#endif
        ldr     r0, =0x57aA7add         @ start address, to be replaced
        str     r0, [r1]
        dsb     sy
index d85cbadf6ec5d974ded6727486e278257b004346..2b1c49f78309798fbd2885f3753c3f8808952011 100644 (file)
@@ -138,5 +138,13 @@ int sandbox_clk_test_free(struct udevice *dev);
  * @return:    0 if OK, or a negative error code.
  */
 int sandbox_clk_test_release_bulk(struct udevice *dev);
+/**
+ * sandbox_clk_test_valid - Ask the sandbox clock test device to check its
+ * clocks are valid.
+ *
+ * @dev:       The sandbox clock test (client) devivce.
+ * @return:    0 if OK, or a negative error code.
+ */
+int sandbox_clk_test_valid(struct udevice *dev);
 
 #endif
index 1253fa51c2295658df7b8abda5d1b20b8a598ed6..1050236330a5630b8dd6b78cde6ed28d729343f0 100644 (file)
@@ -11,7 +11,7 @@
        binman {
                filename = "u-boot.rom";
                end-at-4gb;
-               sort-by-pos;
+               sort-by-offset;
                pad-byte = <0xff>;
                size = <CONFIG_ROM_SIZE>;
 #ifdef CONFIG_HAVE_INTEL_ME
 #endif
 #ifdef CONFIG_SPL
                u-boot-spl-with-ucode-ptr {
-                       pos = <CONFIG_SPL_TEXT_BASE>;
+                       offset = <CONFIG_SPL_TEXT_BASE>;
                };
 
                u-boot-dtb-with-ucode2 {
                        type = "u-boot-dtb-with-ucode";
                };
                u-boot {
-                       pos = <0xfff00000>;
+                       offset = <0xfff00000>;
                };
 #else
                u-boot-with-ucode-ptr {
-                       pos = <CONFIG_SYS_TEXT_BASE>;
+                       offset = <CONFIG_SYS_TEXT_BASE>;
                };
 #endif
                u-boot-dtb-with-ucode {
                };
 #ifdef CONFIG_HAVE_MRC
                intel-mrc {
-                       pos = <CONFIG_X86_MRC_ADDR>;
+                       offset = <CONFIG_X86_MRC_ADDR>;
                };
 #endif
 #ifdef CONFIG_HAVE_FSP
                intel-fsp {
                        filename = CONFIG_FSP_FILE;
-                       pos = <CONFIG_FSP_ADDR>;
+                       offset = <CONFIG_FSP_ADDR>;
                };
 #endif
 #ifdef CONFIG_HAVE_CMC
                intel-cmc {
                        filename = CONFIG_CMC_FILE;
-                       pos = <CONFIG_CMC_ADDR>;
+                       offset = <CONFIG_CMC_ADDR>;
                };
 #endif
 #ifdef CONFIG_HAVE_VGA_BIOS
                intel-vga {
                        filename = CONFIG_VGA_BIOS_FILE;
-                       pos = <CONFIG_VGA_BIOS_ADDR>;
+                       offset = <CONFIG_VGA_BIOS_ADDR>;
                };
 #endif
 #ifdef CONFIG_HAVE_VBT
                intel-vbt {
                        filename = CONFIG_VBT_FILE;
-                       pos = <CONFIG_VBT_ADDR>;
+                       offset = <CONFIG_VBT_ADDR>;
                };
 #endif
 #ifdef CONFIG_HAVE_REFCODE
                intel-refcode {
-                       pos = <CONFIG_X86_REFCODE_ADDR>;
+                       offset = <CONFIG_X86_REFCODE_ADDR>;
                };
 #endif
 #ifdef CONFIG_SPL
                x86-start16-spl {
-                       pos = <CONFIG_SYS_X86_START16>;
+                       offset = <CONFIG_SYS_X86_START16>;
                };
 #else
                x86-start16 {
-                       pos = <CONFIG_SYS_X86_START16>;
+                       offset = <CONFIG_SYS_X86_START16>;
                };
 #endif
        };
index db51f48ab60225c9bdb3a4633661cbc00cdbd672..2f9597644514a1c92fbc91bef34854974e38473c 100644 (file)
@@ -330,6 +330,11 @@ S: Maintained
 F:     configs/A20-Olimex-SOM204-EVB_defconfig
 F:     configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
 
+ORANGEPI ONE PLUS BOARD
+M:     Jagan Teki <jagan@amarulasolutions.com>
+S:     Maintained
+F:     configs/orangepi_one_plus_defconfig
+
 ORANGEPI WIN/WIN PLUS BOARD
 M:     Jagan Teki <jagan@amarulasolutions.com>
 S:     Maintained
@@ -370,6 +375,11 @@ M: Andre Przywara <andre.przywara@arm.com>
 S:     Maintained
 F:     configs/pine64_plus_defconfig
 
+PINE H64 BOARD
+M:     Icenowy Zheng <icenowy@aosc.io>
+S:     Maintained
+F:     configs/pine_h64_defconfig
+
 R16 EVB PARROT BOARD
 M:     Quentin Schulz <quentin.schulz@free-electrons.com>
 S:     Maintained
index 5ed1b8bae188a22929941175048b36c9749ec9fe..857d5ff0103538b70e56896ade03f6e65ffe505e 100644 (file)
@@ -443,6 +443,13 @@ static void mmc_pinmux_setup(int sdc)
                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
                        sunxi_gpio_set_drv(pin, 2);
                }
+#elif defined(CONFIG_MACH_SUN50I_H6)
+               /* SDC2: PC4-PC14 */
+               for (pin = SUNXI_GPC(4); pin <= SUNXI_GPC(14); pin++) {
+                       sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
+                       sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+                       sunxi_gpio_set_drv(pin, 2);
+               }
 #elif defined(CONFIG_MACH_SUN9I)
                /* SDC2: PC6-PC16 */
                for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(16); pin++) {
index 36abe9efed45beedde0e1f278ec6f2d8b1f8ea26..88ad71974706614014619d0f1cb08fa16e68f0ab 100755 (executable)
@@ -13,6 +13,12 @@ if [ ! -f $BL31 ]; then
        BL31=/dev/null
 fi
 
+if grep -q "^CONFIG_MACH_SUN50I_H6=y" .config; then
+       BL31_ADDR=0x104000
+else
+       BL31_ADDR=0x44000
+fi
+
 cat << __HEADER_EOF
 /dts-v1/;
 
@@ -35,8 +41,8 @@ cat << __HEADER_EOF
                        type = "firmware";
                        arch = "arm64";
                        compression = "none";
-                       load = <0x44000>;
-                       entry = <0x44000>;
+                       load = <$BL31_ADDR>;
+                       entry = <$BL31_ADDR>;
                };
 __HEADER_EOF
 
index 147ff0b2f00278cbf684d52f0f75b7ea5f490617..a359d20021fd97ae92b0d110b7e476b7e2347080 100644 (file)
@@ -725,6 +725,8 @@ int board_late_init(void)
 
        if (board_is_bbg1())
                name = "BBG1";
+       if (board_is_bben())
+               name = "BBEN";
        set_board_info_env(name);
 
        /*
@@ -870,7 +872,7 @@ int board_eth_init(bd_t *bis)
        (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
 
 #ifdef CONFIG_DRIVER_TI_CPSW
-       if (board_is_bone() || board_is_bone_lt() ||
+       if (board_is_bone() || board_is_bone_lt() || board_is_bben() ||
            board_is_idk()) {
                writel(MII_MODE_ENABLE, &cdev->miisel);
                cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if =
@@ -906,7 +908,7 @@ int board_eth_init(bd_t *bis)
 #define AR8051_DEBUG_RGMII_CLK_DLY_REG 0x5
 #define AR8051_RGMII_TX_CLK_DLY                0x100
 
-       if (board_is_evm_sk() || board_is_gp_evm()) {
+       if (board_is_evm_sk() || board_is_gp_evm() || board_is_bben()) {
                const char *devname;
                devname = miiphy_get_current_dev();
 
index 652b10b5e4c35f416c3c2e1589dca9f1d1b650ea..48df914af96cfdc4b05a4ef5bac552b3577bf2da 100644 (file)
@@ -43,9 +43,15 @@ static inline int board_is_bbg1(void)
        return board_is_bone_lt() && !strncmp(board_ti_get_rev(), "BBG1", 4);
 }
 
+static inline int board_is_bben(void)
+{
+       return board_is_bone_lt() && !strncmp(board_ti_get_rev(), "SE", 2);
+}
+
 static inline int board_is_beaglebonex(void)
 {
-       return board_is_pb() || board_is_bone() || board_is_bone_lt() || board_is_bbg1();
+       return board_is_pb() || board_is_bone() || board_is_bone_lt() ||
+              board_is_bbg1() || board_is_bben();
 }
 
 static inline int board_is_evm_sk(void)
index aa187605d091ef6053da2bdc00180bf1356d0130..41333f93f40dc57fedfcbaec51b93f2aa9446cd9 100644 (file)
@@ -380,6 +380,13 @@ void enable_board_pin_mux(void)
                configure_module_pin_mux(rgmii1_pin_mux);
                configure_module_pin_mux(mmc0_pin_mux_sk_evm);
        } else if (board_is_bone_lt()) {
+               if (board_is_bben()) {
+                       /* SanCloud Beaglebone LT Enhanced pinmux */
+                       configure_module_pin_mux(rgmii1_pin_mux);
+               } else {
+                       /* Beaglebone LT pinmux */
+                       configure_module_pin_mux(mii1_pin_mux);
+               }
                /* Beaglebone LT pinmux */
                configure_module_pin_mux(mii1_pin_mux);
                configure_module_pin_mux(mmc0_pin_mux);
index 2af26a881af05a3cec061ccdb68e5ee4eb9fa237..0be8ff0d87d7240a92c057e7e27c322b7e4891b0 100644 (file)
@@ -256,7 +256,7 @@ config SPL_SHA256_SUPPORT
 config SPL_FIT_IMAGE_TINY
        bool "Remove functionality from SPL FIT loading to reduce size"
        depends on SPL_FIT
-       default y if MACH_SUN50I || MACH_SUN50I_H5
+       default y if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6
        help
          Enable this to reduce the size of the FIT image loading code
          in SPL, if space for the SPL binary is very tight.
index a1e7b9fa914ef26fdd52bd28e5662200b52c161e..eda84d0c74cd5eadfdb50edcfd7229c50865d795 100644 (file)
@@ -34,7 +34,7 @@ DECLARE_GLOBAL_DATA_PTR;
 u32 *boot_params_ptr = NULL;
 
 /* See spl.h for information about this */
-binman_sym_declare(ulong, u_boot_any, pos);
+binman_sym_declare(ulong, u_boot_any, image_pos);
 
 /* Define board data structure */
 static bd_t bdata __attribute__ ((section(".data")));
@@ -129,7 +129,7 @@ __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);
+       ulong u_boot_pos = binman_sym(ulong, u_boot_any, image_pos);
 
        spl_image->size = CONFIG_SYS_MONITOR_LEN;
 
index e8701934b8708d1efd50901c0f6586e98ef9477c..e594beaeaa3a5534b1188c4fdc3b14152b9d3724 100644 (file)
@@ -49,7 +49,7 @@ 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);
+               ulong u_boot_pos = binman_sym(ulong, u_boot_any, image_pos);
 
                debug("Legacy image\n");
                /*
index 9d75108d0486714a9a6c488d63a9e326cacb5c91..313e09a764735f943f3564837540e372f9f72496 100644 (file)
@@ -7,8 +7,11 @@ CONFIG_DRAM_ZQ=3881979
 CONFIG_DRAM_ODT_EN=y
 CONFIG_MMC0_CD_PIN="PH13"
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-v40-bananapi-m2-berry"
+CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
+CONFIG_SCSI_AHCI=y
 CONFIG_AXP_DLDO4_VOLT=2500
 CONFIG_AXP_ELDO3_VOLT=1200
+CONFIG_SCSI=y
diff --git a/configs/orangepi_one_plus_defconfig b/configs/orangepi_one_plus_defconfig
new file mode 100644 (file)
index 0000000..48bc6e5
--- /dev/null
@@ -0,0 +1,14 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN50I_H6=y
+CONFIG_DRAM_ODT_EN=y
+CONFIG_MMC0_CD_PIN="PF6"
+# CONFIG_PSCI_RESET is not set
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-orangepi-one-plus"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL=y
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_ISO_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
new file mode 100644 (file)
index 0000000..e9596c0
--- /dev/null
@@ -0,0 +1,15 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN50I_H6=y
+CONFIG_DRAM_ODT_EN=y
+CONFIG_MMC0_CD_PIN="PF6"
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+# CONFIG_PSCI_RESET is not set
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-pine-h64"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL=y
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_ISO_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
index 1b14a496406705857c682e41a3de36178549163a..3ddd5c50fb1d12b27d03c23b3df596205c599e16 100644 (file)
@@ -26,7 +26,6 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_CONTROL=y
 CONFIG_OF_EMBED=y
-# CONFIG_BLK is not set
 CONFIG_DM_MMC=y
 CONFIG_ARM_PL180_MMCI=y
 CONFIG_MTD_NOR_FLASH=y
index 4de03edcc2ca1d8fdf13f95b927188dba1aad352..a55476f2f32322289bf89d2a44e46471e536a30c 100644 (file)
@@ -26,7 +26,6 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_CONTROL=y
 CONFIG_OF_EMBED=y
-# CONFIG_BLK is not set
 CONFIG_DM_MMC=y
 CONFIG_ARM_PL180_MMCI=y
 CONFIG_MTD_NOR_FLASH=y
index aa7403f3c516307cf06a6df5d6eeb08a86e059af..6f07ff155862a2efeff8749ae70b6210eac5d353 100644 (file)
@@ -40,7 +40,6 @@ CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_CONTROL=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_NETCONSOLE=y
-# CONFIG_BLK is not set
 CONFIG_DM_MMC=y
 # CONFIG_SPL_DM_MMC is not set
 CONFIG_ARM_PL180_MMCI=y
index c72a440dff1dcccb13b7fcc76eeeb6e12495d7e1..7a9a83e3aec57e75465bb3099def1f661ab0c6ac 100644 (file)
@@ -18,6 +18,7 @@ CONFIG_SYS_PROMPT="STM32MP> "
 # CONFIG_CMD_EXPORTENV is not set
 # CONFIG_CMD_IMPORTENV is not set
 CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_ADC=y
 CONFIG_CMD_FUSE=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
@@ -27,6 +28,7 @@ CONFIG_CMD_PMIC=y
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_SPL_DOS_PARTITION is not set
+CONFIG_STM32_ADC=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_STM32F7=y
 CONFIG_DM_MMC=y
diff --git a/doc/device-tree-bindings/adc/st,stm32-adc.txt b/doc/device-tree-bindings/adc/st,stm32-adc.txt
new file mode 100644 (file)
index 0000000..07fb6cd
--- /dev/null
@@ -0,0 +1,141 @@
+STMicroelectronics STM32 ADC device
+
+STM32 ADC is a successive approximation analog-to-digital converter.
+It has several multiplexed input channels. Conversions can be performed
+in single, continuous, scan or discontinuous mode. Result of the ADC is
+stored in a left-aligned or right-aligned 32-bit data register.
+Conversions can be launched in software or using hardware triggers.
+
+The analog watchdog feature allows the application to detect if the input
+voltage goes beyond the user-defined, higher or lower thresholds.
+
+Each STM32 ADC block can have up to 3 ADC instances.
+
+Each instance supports two contexts to manage conversions, each one has its
+own configurable sequence and trigger:
+- regular conversion can be done in sequence, running in background
+- injected conversions have higher priority, and so have the ability to
+  interrupt regular conversion sequence (either triggered in SW or HW).
+  Regular sequence is resumed, in case it has been interrupted.
+
+Contents of a stm32 adc root node:
+-----------------------------------
+Required properties:
+- compatible: Should be one of:
+  "st,stm32f4-adc-core"
+  "st,stm32h7-adc-core"
+  "st,stm32mp1-adc-core"
+- reg: Offset and length of the ADC block register set.
+- interrupts: One or more interrupts for ADC block. Some parts like stm32f4
+  and stm32h7 share a common ADC interrupt line. stm32mp1 has two separate
+  interrupt lines, one for each ADC within ADC block.
+- clocks: Core can use up to two clocks, depending on part used:
+  - "adc" clock: for the analog circuitry, common to all ADCs.
+    It's required on stm32f4.
+    It's optional on stm32h7.
+  - "bus" clock: for registers access, common to all ADCs.
+    It's not present on stm32f4.
+    It's required on stm32h7.
+- clock-names: Must be "adc" and/or "bus" depending on part used.
+- interrupt-controller: Identifies the controller node as interrupt-parent
+- vref-supply: Phandle to the vref input analog reference voltage.
+- #interrupt-cells = <1>;
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- A pinctrl state named "default" for each ADC channel may be defined to set
+  inX ADC pins in mode of operation for analog input on external pin.
+
+Contents of a stm32 adc child node:
+-----------------------------------
+An ADC block node should contain at least one subnode, representing an
+ADC instance available on the machine.
+
+Required properties:
+- compatible: Should be one of:
+  "st,stm32f4-adc"
+  "st,stm32h7-adc"
+  "st,stm32mp1-adc"
+- reg: Offset of ADC instance in ADC block (e.g. may be 0x0, 0x100, 0x200).
+- clocks: Input clock private to this ADC instance. It's required only on
+  stm32f4, that has per instance clock input for registers access.
+- interrupt-parent: Phandle to the parent interrupt controller.
+- interrupts: IRQ Line for the ADC (e.g. may be 0 for adc@0, 1 for adc@100 or
+  2 for adc@200).
+- st,adc-channels: List of single-ended channels muxed for this ADC.
+  It can have up to 16 channels on stm32f4 or 20 channels on stm32h7, numbered
+  from 0 to 15 or 19 (resp. for in0..in15 or in0..in19).
+- st,adc-diff-channels: List of differential channels muxed for this ADC.
+  Depending on part used, some channels can be configured as differential
+  instead of single-ended (e.g. stm32h7). List here positive and negative
+  inputs pairs as <vinp vinn>, <vinp vinn>,... vinp and vinn are numbered
+  from 0 to 19 on stm32h7)
+  Note: At least one of "st,adc-channels" or "st,adc-diff-channels" is required.
+  Both properties can be used together. Some channels can be used as
+  single-ended and some other ones as differential (mixed). But channels
+  can't be configured both as single-ended and differential (invalid).
+- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
+  Documentation/devicetree/bindings/iio/iio-bindings.txt
+
+Optional properties:
+- dmas: Phandle to dma channel for this ADC instance.
+  See ../../dma/dma.txt for details.
+- dma-names: Must be "rx" when dmas property is being used.
+- assigned-resolution-bits: Resolution (bits) to use for conversions. Must
+  match device available resolutions:
+  * can be 6, 8, 10 or 12 on stm32f4
+  * can be 8, 10, 12, 14 or 16 on stm32h7
+  Default is maximum resolution if unset.
+- st,min-sample-time-nsecs: Minimum sampling time in nanoseconds.
+  Depending on hardware (board) e.g. high/low analog input source impedance,
+  fine tune of ADC sampling time may be recommended.
+  This can be either one value or an array that matches 'st,adc-channels' list,
+  to set sample time resp. for all channels, or independently for each channel.
+
+Example:
+       adc: adc@40012000 {
+               compatible = "st,stm32f4-adc-core";
+               reg = <0x40012000 0x400>;
+               interrupts = <18>;
+               clocks = <&rcc 0 168>;
+               clock-names = "adc";
+               vref-supply = <&reg_vref>;
+               interrupt-controller;
+               pinctrl-names = "default";
+               pinctrl-0 = <&adc3_in8_pin>;
+
+               #interrupt-cells = <1>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               adc@0 {
+                       compatible = "st,stm32f4-adc";
+                       #io-channel-cells = <1>;
+                       reg = <0x0>;
+                       clocks = <&rcc 0 168>;
+                       interrupt-parent = <&adc>;
+                       interrupts = <0>;
+                       st,adc-channels = <8>;
+                       dmas = <&dma2 0 0 0x400 0x0>;
+                       dma-names = "rx";
+                       assigned-resolution-bits = <8>;
+               };
+               ...
+               other adc child nodes follow...
+       };
+
+Example to setup:
+- channel 1 as single-ended
+- channels 2 & 3 as differential (with resp. 6 & 7 negative inputs)
+
+       adc: adc@40022000 {
+               compatible = "st,stm32h7-adc-core";
+               ...
+               adc1: adc@0 {
+                       compatible = "st,stm32h7-adc";
+                       ...
+                       st,adc-channels = <1>;
+                       st,adc-diff-channels = <2 6>, <3 7>;
+               };
+       };
index 93e27f131cab01e1678e6988975b2f15f19956aa..e719c38bb31a7176ccddfaf51b1459c196fe47f4 100644 (file)
@@ -47,3 +47,19 @@ config SARADC_ROCKCHIP
          - 2~6 analog input channels
          - 1O or 12 bits resolution
          - Up to 1MSPS of sample rate
+
+config STM32_ADC
+       bool "Enable STMicroelectronics STM32 ADC driver"
+       depends on ADC && (STM32H7 || ARCH_STM32MP)
+       help
+         This enables driver for STMicroelectronics STM32 analog-to-digital
+         converter (ADC).
+         A STM32 ADC block can be composed of several individual ADCs.
+         Each has its own private registers, but shares some resources:
+         - clock selection and prescaler
+         - voltage reference
+         - common registers area.
+         STM32 ADC driver is composed of:
+         - core driver to deal with common resources
+         - child driver to deal with individual ADC resources (declare ADC
+         device and associated channels, start/stop conversions)
index 95c93d4c57a1218769495f453e7bcd623c66a994..cca0fecd59773bc38fba75a2a1fcfaeaec7d5058 100644 (file)
@@ -10,3 +10,4 @@ obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o
 obj-$(CONFIG_ADC_SANDBOX) += sandbox.o
 obj-$(CONFIG_SARADC_ROCKCHIP) += rockchip-saradc.o
 obj-$(CONFIG_SARADC_MESON) += meson-saradc.o
+obj-$(CONFIG_STM32_ADC) += stm32-adc.o stm32-adc-core.o
index 17c1a4e52aaa21113b99938e5fa2eb8fe3678886..738c1eabdc347f5fa03c81983e1544be1e303e1c 100644 (file)
@@ -264,10 +264,8 @@ static int adc_vdd_platdata_update(struct udevice *dev)
         * will bind before its supply regulator device, then the below 'get'
         * will return an error.
         */
-       ret = device_get_supply_regulator(dev, "vdd-supply",
-                                         &uc_pdata->vdd_supply);
-       if (ret)
-               return ret;
+       if (!uc_pdata->vdd_supply)
+               return 0;
 
        ret = regulator_get_value(uc_pdata->vdd_supply);
        if (ret < 0)
@@ -283,10 +281,8 @@ static int adc_vss_platdata_update(struct udevice *dev)
        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
        int ret;
 
-       ret = device_get_supply_regulator(dev, "vss-supply",
-                                         &uc_pdata->vss_supply);
-       if (ret)
-               return ret;
+       if (!uc_pdata->vss_supply)
+               return 0;
 
        ret = regulator_get_value(uc_pdata->vss_supply);
        if (ret < 0)
@@ -302,14 +298,11 @@ int adc_vdd_value(struct udevice *dev, int *uV)
        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
        int ret, value_sign = uc_pdata->vdd_polarity_negative ? -1 : 1;
 
-       if (!uc_pdata->vdd_supply)
-               goto nodev;
-
        /* Update the regulator Value. */
        ret = adc_vdd_platdata_update(dev);
        if (ret)
                return ret;
-nodev:
+
        if (uc_pdata->vdd_microvolts == -ENODATA)
                return -ENODATA;
 
@@ -323,14 +316,11 @@ int adc_vss_value(struct udevice *dev, int *uV)
        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
        int ret, value_sign = uc_pdata->vss_polarity_negative ? -1 : 1;
 
-       if (!uc_pdata->vss_supply)
-               goto nodev;
-
        /* Update the regulator Value. */
        ret = adc_vss_platdata_update(dev);
        if (ret)
                return ret;
-nodev:
+
        if (uc_pdata->vss_microvolts == -ENODATA)
                return -ENODATA;
 
@@ -348,7 +338,12 @@ static int adc_vdd_platdata_set(struct udevice *dev)
        prop = "vdd-polarity-negative";
        uc_pdata->vdd_polarity_negative = dev_read_bool(dev, prop);
 
-       ret = adc_vdd_platdata_update(dev);
+       /* Optionally get regulators */
+       ret = device_get_supply_regulator(dev, "vdd-supply",
+                                         &uc_pdata->vdd_supply);
+       if (!ret)
+               return adc_vdd_platdata_update(dev);
+
        if (ret != -ENOENT)
                return ret;
 
@@ -368,7 +363,11 @@ static int adc_vss_platdata_set(struct udevice *dev)
        prop = "vss-polarity-negative";
        uc_pdata->vss_polarity_negative = dev_read_bool(dev, prop);
 
-       ret = adc_vss_platdata_update(dev);
+       ret = device_get_supply_regulator(dev, "vss-supply",
+                                         &uc_pdata->vss_supply);
+       if (!ret)
+               return adc_vss_platdata_update(dev);
+
        if (ret != -ENOENT)
                return ret;
 
diff --git a/drivers/adc/stm32-adc-core.c b/drivers/adc/stm32-adc-core.c
new file mode 100644 (file)
index 0000000..a9aa143
--- /dev/null
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
+ *
+ * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc-core.c.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <power/regulator.h>
+#include "stm32-adc-core.h"
+
+/* STM32H7 - common registers for all ADC instances */
+#define STM32H7_ADC_CCR                        (STM32_ADCX_COMN_OFFSET + 0x08)
+
+/* STM32H7_ADC_CCR - bit fields */
+#define STM32H7_PRESC_SHIFT            18
+#define STM32H7_PRESC_MASK             GENMASK(21, 18)
+#define STM32H7_CKMODE_SHIFT           16
+#define STM32H7_CKMODE_MASK            GENMASK(17, 16)
+
+/* STM32 H7 maximum analog clock rate (from datasheet) */
+#define STM32H7_ADC_MAX_CLK_RATE       36000000
+
+/**
+ * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock
+ * @ckmode: ADC clock mode, Async or sync with prescaler.
+ * @presc: prescaler bitfield for async clock mode
+ * @div: prescaler division ratio
+ */
+struct stm32h7_adc_ck_spec {
+       u32 ckmode;
+       u32 presc;
+       int div;
+};
+
+static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
+       /* 00: CK_ADC[1..3]: Asynchronous clock modes */
+       { 0, 0, 1 },
+       { 0, 1, 2 },
+       { 0, 2, 4 },
+       { 0, 3, 6 },
+       { 0, 4, 8 },
+       { 0, 5, 10 },
+       { 0, 6, 12 },
+       { 0, 7, 16 },
+       { 0, 8, 32 },
+       { 0, 9, 64 },
+       { 0, 10, 128 },
+       { 0, 11, 256 },
+       /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */
+       { 1, 0, 1 },
+       { 2, 0, 2 },
+       { 3, 0, 4 },
+};
+
+static int stm32h7_adc_clk_sel(struct udevice *dev,
+                              struct stm32_adc_common *common)
+{
+       u32 ckmode, presc;
+       unsigned long rate;
+       int i, div;
+
+       /* stm32h7 bus clock is common for all ADC instances (mandatory) */
+       if (!clk_valid(&common->bclk)) {
+               dev_err(dev, "No bclk clock found\n");
+               return -ENOENT;
+       }
+
+       /*
+        * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry.
+        * So, choice is to have bus clock mandatory and adc clock optional.
+        * If optional 'adc' clock has been found, then try to use it first.
+        */
+       if (clk_valid(&common->aclk)) {
+               /*
+                * Asynchronous clock modes (e.g. ckmode == 0)
+                * From spec: PLL output musn't exceed max rate
+                */
+               rate = clk_get_rate(&common->aclk);
+               if (!rate) {
+                       dev_err(dev, "Invalid aclk rate: 0\n");
+                       return -EINVAL;
+               }
+
+               for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
+                       ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
+                       presc = stm32h7_adc_ckmodes_spec[i].presc;
+                       div = stm32h7_adc_ckmodes_spec[i].div;
+
+                       if (ckmode)
+                               continue;
+
+                       if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
+                               goto out;
+               }
+       }
+
+       /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */
+       rate = clk_get_rate(&common->bclk);
+       if (!rate) {
+               dev_err(dev, "Invalid bus clock rate: 0\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
+               ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
+               presc = stm32h7_adc_ckmodes_spec[i].presc;
+               div = stm32h7_adc_ckmodes_spec[i].div;
+
+               if (!ckmode)
+                       continue;
+
+               if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
+                       goto out;
+       }
+
+       dev_err(dev, "clk selection failed\n");
+       return -EINVAL;
+
+out:
+       /* rate used later by each ADC instance to control BOOST mode */
+       common->rate = rate / div;
+
+       /* Set common clock mode and prescaler */
+       clrsetbits_le32(common->base + STM32H7_ADC_CCR,
+                       STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK,
+                       ckmode << STM32H7_CKMODE_SHIFT |
+                       presc << STM32H7_PRESC_SHIFT);
+
+       dev_dbg(dev, "Using %s clock/%d source at %ld kHz\n",
+               ckmode ? "bus" : "adc", div, common->rate / 1000);
+
+       return 0;
+}
+
+static int stm32_adc_core_probe(struct udevice *dev)
+{
+       struct stm32_adc_common *common = dev_get_priv(dev);
+       int ret;
+
+       common->base = dev_read_addr_ptr(dev);
+       if (!common->base) {
+               dev_err(dev, "can't get address\n");
+               return -ENOENT;
+       }
+
+       ret = device_get_supply_regulator(dev, "vref-supply", &common->vref);
+       if (ret) {
+               dev_err(dev, "can't get vref-supply: %d\n", ret);
+               return ret;
+       }
+
+       ret = regulator_get_value(common->vref);
+       if (ret < 0) {
+               dev_err(dev, "can't get vref-supply value: %d\n", ret);
+               return ret;
+       }
+       common->vref_uv = ret;
+
+       ret = clk_get_by_name(dev, "adc", &common->aclk);
+       if (!ret) {
+               ret = clk_enable(&common->aclk);
+               if (ret) {
+                       dev_err(dev, "Can't enable aclk: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = clk_get_by_name(dev, "bus", &common->bclk);
+       if (!ret) {
+               ret = clk_enable(&common->bclk);
+               if (ret) {
+                       dev_err(dev, "Can't enable bclk: %d\n", ret);
+                       goto err_aclk_disable;
+               }
+       }
+
+       ret = stm32h7_adc_clk_sel(dev, common);
+       if (ret)
+               goto err_bclk_disable;
+
+       return ret;
+
+err_bclk_disable:
+       if (clk_valid(&common->bclk))
+               clk_disable(&common->bclk);
+
+err_aclk_disable:
+       if (clk_valid(&common->aclk))
+               clk_disable(&common->aclk);
+
+       return ret;
+}
+
+static const struct udevice_id stm32_adc_core_ids[] = {
+       { .compatible = "st,stm32h7-adc-core" },
+       { .compatible = "st,stm32mp1-adc-core" },
+       {}
+};
+
+U_BOOT_DRIVER(stm32_adc_core) = {
+       .name  = "stm32-adc-core",
+       .id = UCLASS_SIMPLE_BUS,
+       .of_match = stm32_adc_core_ids,
+       .probe = stm32_adc_core_probe,
+       .priv_auto_alloc_size = sizeof(struct stm32_adc_common),
+};
diff --git a/drivers/adc/stm32-adc-core.h b/drivers/adc/stm32-adc-core.h
new file mode 100644 (file)
index 0000000..ba0e10e
--- /dev/null
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
+ *
+ * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc-core.h.
+ */
+
+#ifndef __STM32_ADC_H
+#define __STM32_ADC_H
+
+/*
+ * STM32 - ADC global register map
+ * ________________________________________________________
+ * | Offset |                 Register                    |
+ * --------------------------------------------------------
+ * | 0x000  |                Master ADC1                  |
+ * --------------------------------------------------------
+ * | 0x100  |                Slave ADC2                   |
+ * --------------------------------------------------------
+ * | 0x200  |                Slave ADC3                   |
+ * --------------------------------------------------------
+ * | 0x300  |         Master & Slave common regs          |
+ * --------------------------------------------------------
+ */
+#define STM32_ADC_MAX_ADCS             3
+#define STM32_ADCX_COMN_OFFSET         0x300
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+
+/**
+ * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
+ * @base:              control registers base cpu addr
+ * @rate:              clock rate used for analog circuitry
+ * @aclk:              clock for the analog circuitry
+ * @bclk:              bus clock common for all ADCs
+ * @vref:              regulator reference
+ * @vref_uv:           reference supply voltage (uV)
+ */
+struct stm32_adc_common {
+       void __iomem *base;
+       unsigned long rate;
+       struct clk aclk;
+       struct clk bclk;
+       struct udevice *vref;
+       int vref_uv;
+};
+
+#endif
diff --git a/drivers/adc/stm32-adc.c b/drivers/adc/stm32-adc.c
new file mode 100644 (file)
index 0000000..e108062
--- /dev/null
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
+ *
+ * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc.c.
+ */
+
+#include <common.h>
+#include <adc.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+#include "stm32-adc-core.h"
+
+/* STM32H7 - Registers for each ADC instance */
+#define STM32H7_ADC_ISR                        0x00
+#define STM32H7_ADC_CR                 0x08
+#define STM32H7_ADC_CFGR               0x0C
+#define STM32H7_ADC_SMPR1              0x14
+#define STM32H7_ADC_SMPR2              0x18
+#define STM32H7_ADC_PCSEL              0x1C
+#define STM32H7_ADC_SQR1               0x30
+#define STM32H7_ADC_DR                 0x40
+#define STM32H7_ADC_DIFSEL             0xC0
+
+/* STM32H7_ADC_ISR - bit fields */
+#define STM32MP1_VREGREADY             BIT(12)
+#define STM32H7_EOC                    BIT(2)
+#define STM32H7_ADRDY                  BIT(0)
+
+/* STM32H7_ADC_CR - bit fields */
+#define STM32H7_DEEPPWD                        BIT(29)
+#define STM32H7_ADVREGEN               BIT(28)
+#define STM32H7_BOOST                  BIT(8)
+#define STM32H7_ADSTART                        BIT(2)
+#define STM32H7_ADDIS                  BIT(1)
+#define STM32H7_ADEN                   BIT(0)
+
+/* STM32H7_ADC_CFGR bit fields */
+#define STM32H7_EXTEN                  GENMASK(11, 10)
+#define STM32H7_DMNGT                  GENMASK(1, 0)
+
+/* STM32H7_ADC_SQR1 - bit fields */
+#define STM32H7_SQ1_SHIFT              6
+
+/* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
+#define STM32H7_BOOST_CLKRATE          20000000UL
+
+#define STM32_ADC_CH_MAX               20      /* max number of channels */
+#define STM32_ADC_TIMEOUT_US           100000
+
+struct stm32_adc_cfg {
+       unsigned int max_channels;
+       unsigned int num_bits;
+       bool has_vregready;
+};
+
+struct stm32_adc {
+       void __iomem *regs;
+       int active_channel;
+       const struct stm32_adc_cfg *cfg;
+};
+
+static int stm32_adc_stop(struct udevice *dev)
+{
+       struct stm32_adc *adc = dev_get_priv(dev);
+
+       setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS);
+       clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
+       /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
+       setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
+       adc->active_channel = -1;
+
+       return 0;
+}
+
+static int stm32_adc_start_channel(struct udevice *dev, int channel)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
+       struct stm32_adc *adc = dev_get_priv(dev);
+       int ret;
+       u32 val;
+
+       /* Exit deep power down, then enable ADC voltage regulator */
+       clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
+       setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN);
+       if (common->rate > STM32H7_BOOST_CLKRATE)
+               setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
+
+       /* Wait for startup time */
+       if (!adc->cfg->has_vregready) {
+               udelay(20);
+       } else {
+               ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
+                                        val & STM32MP1_VREGREADY,
+                                        STM32_ADC_TIMEOUT_US);
+               if (ret < 0) {
+                       stm32_adc_stop(dev);
+                       dev_err(dev, "Failed to enable vreg: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       /* Only use single ended channels */
+       writel(0, adc->regs + STM32H7_ADC_DIFSEL);
+
+       /* Enable ADC, Poll for ADRDY to be set (after adc startup time) */
+       setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADEN);
+       ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
+                                val & STM32H7_ADRDY, STM32_ADC_TIMEOUT_US);
+       if (ret < 0) {
+               stm32_adc_stop(dev);
+               dev_err(dev, "Failed to enable ADC: %d\n", ret);
+               return ret;
+       }
+
+       /* Preselect channels */
+       writel(uc_pdata->channel_mask, adc->regs + STM32H7_ADC_PCSEL);
+
+       /* Set sampling time to max value by default */
+       writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR1);
+       writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR2);
+
+       /* Program regular sequence: chan in SQ1 & len = 0 for one channel */
+       writel(channel << STM32H7_SQ1_SHIFT, adc->regs + STM32H7_ADC_SQR1);
+
+       /* Trigger detection disabled (conversion can be launched in SW) */
+       clrbits_le32(adc->regs + STM32H7_ADC_CFGR, STM32H7_EXTEN |
+                    STM32H7_DMNGT);
+       adc->active_channel = channel;
+
+       return 0;
+}
+
+static int stm32_adc_channel_data(struct udevice *dev, int channel,
+                                 unsigned int *data)
+{
+       struct stm32_adc *adc = dev_get_priv(dev);
+       int ret;
+       u32 val;
+
+       if (channel != adc->active_channel) {
+               dev_err(dev, "Requested channel is not active!\n");
+               return -EINVAL;
+       }
+
+       setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADSTART);
+       ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
+                                val & STM32H7_EOC, STM32_ADC_TIMEOUT_US);
+       if (ret < 0) {
+               dev_err(dev, "conversion timed out: %d\n", ret);
+               return ret;
+       }
+
+       *data = readl(adc->regs + STM32H7_ADC_DR);
+
+       return 0;
+}
+
+static int stm32_adc_chan_of_init(struct udevice *dev)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       struct stm32_adc *adc = dev_get_priv(dev);
+       u32 chans[STM32_ADC_CH_MAX];
+       int i, num_channels, ret;
+
+       /* Retrieve single ended channels listed in device tree */
+       num_channels = dev_read_size(dev, "st,adc-channels");
+       if (num_channels < 0) {
+               dev_err(dev, "can't get st,adc-channels: %d\n", num_channels);
+               return num_channels;
+       }
+       num_channels /= sizeof(u32);
+
+       if (num_channels > adc->cfg->max_channels) {
+               dev_err(dev, "too many st,adc-channels: %d\n", num_channels);
+               return -EINVAL;
+       }
+
+       ret = dev_read_u32_array(dev, "st,adc-channels", chans, num_channels);
+       if (ret < 0) {
+               dev_err(dev, "can't read st,adc-channels: %d\n", ret);
+               return ret;
+       }
+
+       for (i = 0; i < num_channels; i++) {
+               if (chans[i] >= adc->cfg->max_channels) {
+                       dev_err(dev, "bad channel %u\n", chans[i]);
+                       return -EINVAL;
+               }
+               uc_pdata->channel_mask |= 1 << chans[i];
+       }
+
+       uc_pdata->data_mask = (1 << adc->cfg->num_bits) - 1;
+       uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
+       uc_pdata->data_timeout_us = 100000;
+
+       return 0;
+}
+
+static int stm32_adc_probe(struct udevice *dev)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
+       struct stm32_adc *adc = dev_get_priv(dev);
+       int offset;
+
+       offset = dev_read_u32_default(dev, "reg", -ENODATA);
+       if (offset < 0) {
+               dev_err(dev, "Can't read reg property\n");
+               return offset;
+       }
+       adc->regs = common->base + offset;
+       adc->cfg = (const struct stm32_adc_cfg *)dev_get_driver_data(dev);
+
+       /* VDD supplied by common vref pin */
+       uc_pdata->vdd_supply = common->vref;
+       uc_pdata->vdd_microvolts = common->vref_uv;
+       uc_pdata->vss_microvolts = 0;
+
+       return stm32_adc_chan_of_init(dev);
+}
+
+static const struct adc_ops stm32_adc_ops = {
+       .start_channel = stm32_adc_start_channel,
+       .channel_data = stm32_adc_channel_data,
+       .stop = stm32_adc_stop,
+};
+
+static const struct stm32_adc_cfg stm32h7_adc_cfg = {
+       .num_bits = 16,
+       .max_channels = STM32_ADC_CH_MAX,
+};
+
+static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
+       .num_bits = 16,
+       .max_channels = STM32_ADC_CH_MAX,
+       .has_vregready = true,
+};
+
+static const struct udevice_id stm32_adc_ids[] = {
+       { .compatible = "st,stm32h7-adc",
+         .data = (ulong)&stm32h7_adc_cfg },
+       { .compatible = "st,stm32mp1-adc",
+         .data = (ulong)&stm32mp1_adc_cfg },
+       {}
+};
+
+U_BOOT_DRIVER(stm32_adc) = {
+       .name  = "stm32-adc",
+       .id = UCLASS_ADC,
+       .of_match = stm32_adc_ids,
+       .probe = stm32_adc_probe,
+       .ops = &stm32_adc_ops,
+       .priv_auto_alloc_size = sizeof(struct stm32_adc),
+};
index a3162c97edd3d9a01a64645e91a1ba662c6bc537..646c563f8a4a5f7d400ff1af39a77ea822fbf19e 100644 (file)
 __weak void bootcount_store(ulong a)
 {
        void *reg = (void *)CONFIG_SYS_BOOTCOUNT_ADDR;
+       uintptr_t flush_start = rounddown(CONFIG_SYS_BOOTCOUNT_ADDR,
+                                         CONFIG_SYS_CACHELINE_SIZE);
+       uintptr_t flush_end;
 
 #if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
        raw_bootcount_store(reg, (BOOTCOUNT_MAGIC & 0xffff0000) | a);
+
+       flush_end = roundup(CONFIG_SYS_BOOTCOUNT_ADDR + 4,
+                           CONFIG_SYS_CACHELINE_SIZE);
 #else
        raw_bootcount_store(reg, a);
        raw_bootcount_store(reg + 4, BOOTCOUNT_MAGIC);
+
+       flush_end = roundup(CONFIG_SYS_BOOTCOUNT_ADDR + 8,
+                           CONFIG_SYS_CACHELINE_SIZE);
 #endif /* defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD */
-       flush_dcache_range(CONFIG_SYS_BOOTCOUNT_ADDR,
-                               CONFIG_SYS_BOOTCOUNT_ADDR +
-                               CONFIG_SYS_CACHELINE_SIZE);
+       flush_dcache_range(flush_start, flush_end);
 }
 
 __weak ulong bootcount_load(void)
index 419d4515acc6c240299d75572ffdab8af3cf0656..2b15978e141a35ab706ee448b540d86f3c0310ef 100644 (file)
@@ -154,6 +154,10 @@ static int clk_set_default_parents(struct udevice *dev)
        for (index = 0; index < num_parents; index++) {
                ret = clk_get_by_indexed_prop(dev, "assigned-clock-parents",
                                              index, &parent_clk);
+               /* If -ENOENT, this is a no-op entry */
+               if (ret == -ENOENT)
+                       continue;
+
                if (ret) {
                        debug("%s: could not get parent clock %d for %s\n",
                              __func__, index, dev_read_name(dev));
@@ -210,6 +214,10 @@ static int clk_set_default_rates(struct udevice *dev)
                goto fail;
 
        for (index = 0; index < num_rates; index++) {
+               /* If 0 is passed, this is a no-op */
+               if (!rates[index])
+                       continue;
+
                ret = clk_get_by_indexed_prop(dev, "assigned-clocks",
                                              index, &clk);
                if (ret) {
index 8cd4abb84f573eb8bd6efc8c0fa0fe5c69be6482..e8465dbfad1d99fcbf23f0922071253f23955cdd 100644 (file)
@@ -116,6 +116,19 @@ int sandbox_clk_test_release_bulk(struct udevice *dev)
        return clk_release_bulk(&sbct->bulk);
 }
 
+int sandbox_clk_test_valid(struct udevice *dev)
+{
+       struct sandbox_clk_test *sbct = dev_get_priv(dev);
+       int i;
+
+       for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
+               if (!clk_valid(&sbct->clks[i]))
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 static const struct udevice_id sandbox_clk_test_ids[] = {
        { .compatible = "sandbox,clk-test" },
        { }
index e267cd782e8b1f4d5e9f144ebe6f2a3636c0bde9..f71d79ecd6bae01bfa93700b42380d504da3b01e 100644 (file)
@@ -357,13 +357,13 @@ static const struct mmc_ops arm_pl180_mmci_ops = {
        .set_ios = host_set_ios,
        .init = mmc_host_reset,
 };
-#endif
 
 /*
  * mmc_host_init - initialize the mmc controller.
  * Set initial clock and power for mmc slot.
  * Initialize mmc struct and register with mmc framework.
  */
+
 int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
 {
        u32 sdi_u32;
@@ -377,9 +377,8 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
        writel(sdi_u32, &host->base->mask0);
 
        host->cfg.name = host->name;
-#ifndef CONFIG_DM_MMC
        host->cfg.ops = &arm_pl180_mmci_ops;
-#endif
+
        /* TODO remove the duplicates */
        host->cfg.host_caps = host->caps;
        host->cfg.voltages = host->voltages;
@@ -393,20 +392,34 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
        *mmc = mmc_create(&host->cfg, host);
        if (!*mmc)
                return -1;
-
        debug("registered mmc interface number is:%d\n",
              (*mmc)->block_dev.devnum);
 
        return 0;
 }
+#endif
 
 #ifdef CONFIG_DM_MMC
+static void arm_pl180_mmc_init(struct pl180_mmc_host *host)
+{
+       u32 sdi_u32;
+
+       writel(host->pwr_init, &host->base->power);
+       writel(host->clkdiv_init, &host->base->clock);
+       udelay(CLK_CHANGE_DELAY);
+
+       /* Disable mmc interrupts */
+       sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
+       writel(sdi_u32, &host->base->mask0);
+}
+
 static int arm_pl180_mmc_probe(struct udevice *dev)
 {
        struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
        struct mmc *mmc = &pdata->mmc;
-       struct pl180_mmc_host *host = mmc->priv;
+       struct pl180_mmc_host *host = dev->priv;
+       struct mmc_config *cfg = &pdata->cfg;
        struct clk clk;
        u32 bus_width;
        int ret;
@@ -417,31 +430,33 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
 
        ret = clk_enable(&clk);
        if (ret) {
+               clk_free(&clk);
                dev_err(dev, "failed to enable clock\n");
                return ret;
        }
 
-       strcpy(host->name, "MMC");
        host->pwr_init = INIT_PWR;
        host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V1 | SDI_CLKCR_CLKEN |
                            SDI_CLKCR_HWFC_EN;
-       host->voltages = VOLTAGE_WINDOW_SD;
-       host->caps = 0;
        host->clock_in = clk_get_rate(&clk);
-       host->clock_min = host->clock_in / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1));
-       host->clock_max = dev_read_u32_default(dev, "max-frequency",
-                                              MMC_CLOCK_MAX);
        host->version2 = dev_get_driver_data(dev);
 
+       cfg->name = dev->name;
+       cfg->voltages = VOLTAGE_WINDOW_SD;
+       cfg->host_caps = 0;
+       cfg->f_min = host->clock_in / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1));
+       cfg->f_max = dev_read_u32_default(dev, "max-frequency", MMC_CLOCK_MAX);
+       cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
        gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN);
 
        bus_width = dev_read_u32_default(dev, "bus-width", 1);
        switch (bus_width) {
        case 8:
-               host->caps |= MMC_MODE_8BIT;
+               cfg->host_caps |= MMC_MODE_8BIT;
                /* Hosts capable of 8-bit transfers can also do 4 bits */
        case 4:
-               host->caps |= MMC_MODE_4BIT;
+               cfg->host_caps |= MMC_MODE_4BIT;
                break;
        case 1:
                break;
@@ -449,19 +464,21 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
                dev_err(dev, "Invalid bus-width value %u\n", bus_width);
        }
 
-       ret = arm_pl180_mmci_init(host, &mmc);
-       if (ret) {
-               dev_err(dev, "arm_pl180_mmci init failed\n");
-               return ret;
-       }
-
+       arm_pl180_mmc_init(host);
+       mmc->priv = host;
        mmc->dev = dev;
-       dev->priv = host;
        upriv->mmc = mmc;
 
        return 0;
 }
 
+int arm_pl180_mmc_bind(struct udevice *dev)
+{
+       struct arm_pl180_mmc_plat *plat = dev_get_platdata(dev);
+
+       return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
 static int dm_host_request(struct udevice *dev, struct mmc_cmd *cmd,
                           struct mmc_data *data)
 {
@@ -479,16 +496,11 @@ static int dm_host_set_ios(struct udevice *dev)
 
 static int dm_mmc_getcd(struct udevice *dev)
 {
-       struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
-       struct mmc *mmc = &pdata->mmc;
-       struct pl180_mmc_host *host = mmc->priv;
+       struct pl180_mmc_host *host = dev->priv;
        int value = 1;
 
-       if (dm_gpio_is_valid(&host->cd_gpio)) {
+       if (dm_gpio_is_valid(&host->cd_gpio))
                value = dm_gpio_get_value(&host->cd_gpio);
-               if (host->cd_inverted)
-                       return !value;
-       }
 
        return value;
 }
@@ -501,12 +513,10 @@ static const struct dm_mmc_ops arm_pl180_dm_mmc_ops = {
 
 static int arm_pl180_mmc_ofdata_to_platdata(struct udevice *dev)
 {
-       struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
-       struct mmc *mmc = &pdata->mmc;
-       struct pl180_mmc_host *host = mmc->priv;
+       struct pl180_mmc_host *host = dev->priv;
        fdt_addr_t addr;
 
-       addr = devfdt_get_addr(dev);
+       addr = dev_read_addr(dev);
        if (addr == FDT_ADDR_T_NONE)
                return -EINVAL;
 
@@ -527,6 +537,7 @@ U_BOOT_DRIVER(arm_pl180_mmc) = {
        .ops = &arm_pl180_dm_mmc_ops,
        .probe = arm_pl180_mmc_probe,
        .ofdata_to_platdata = arm_pl180_mmc_ofdata_to_platdata,
+       .bind = arm_pl180_mmc_bind,
        .priv_auto_alloc_size = sizeof(struct pl180_mmc_host),
        .platdata_auto_alloc_size = sizeof(struct arm_pl180_mmc_plat),
 };
index 6b98db6cd978d6c407102064f68a5a9dd4b1a82e..36487be288b2887a3b389a343731b7bbe095bf4a 100644 (file)
@@ -192,7 +192,6 @@ struct pl180_mmc_host {
        struct mmc_config cfg;
 #ifdef CONFIG_DM_MMC
        struct gpio_desc cd_gpio;
-       bool cd_inverted;
 #endif
 };
 
index 7fa1ae8b162f61a755e4d783755e6eda57757647..39f15eb4236c252f9e24b71894452e3be28bddc8 100644 (file)
@@ -70,10 +70,12 @@ static int mmc_resource_init(int sdc_no)
                priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
                priv->mclkreg = &ccm->sd2_clk_cfg;
                break;
+#ifdef SUNXI_MMC3_BASE
        case 3:
                priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;
                priv->mclkreg = &ccm->sd3_clk_cfg;
                break;
+#endif
        default:
                printf("Wrong mmc number %d\n", sdc_no);
                return -1;
@@ -116,6 +118,9 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
 #ifdef CONFIG_MACH_SUN9I
                pll = CCM_MMC_CTRL_PLL_PERIPH0;
                pll_hz = clock_get_pll4_periph0();
+#elif defined(CONFIG_MACH_SUN50I_H6)
+               pll = CCM_MMC_CTRL_PLL6X2;
+               pll_hz = clock_get_pll6() * 2;
 #else
                pll = CCM_MMC_CTRL_PLL6;
                pll_hz = clock_get_pll6();
@@ -494,7 +499,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
 
        cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
        cfg->host_caps = MMC_MODE_4BIT;
-#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I)
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I_H6)
        if (sdc_no == 2)
                cfg->host_caps = MMC_MODE_8BIT;
 #endif
@@ -509,6 +514,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
 
        /* config ahb clock */
        debug("init mmc %d clock and io\n", sdc_no);
+#if !defined(CONFIG_MACH_SUN50I_H6)
        setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
 
 #ifdef CONFIG_SUNXI_GEN_SUN6I
@@ -519,6 +525,11 @@ struct mmc *sunxi_mmc_init(int sdc_no)
        /* sun9i has a mmc-common module, also set the gate and reset there */
        writel(SUNXI_MMC_COMMON_CLK_GATE | SUNXI_MMC_COMMON_RESET,
               SUNXI_MMC_COMMON_BASE + 4 * sdc_no);
+#endif
+#else /* CONFIG_MACH_SUN50I_H6 */
+       setbits_le32(&ccm->sd_gate_reset, 1 << sdc_no);
+       /* unassert reset */
+       setbits_le32(&ccm->sd_gate_reset, 1 << (RESET_SHIFT + sdc_no));
 #endif
        ret = mmc_set_mod_clk(priv, 24000000);
        if (ret)
index 64e4621aaaf1324667763fb6fa67001959a63125..9094f857c1e88d44e19b3573dc44f7eb372eb7ba 100644 (file)
@@ -3041,7 +3041,7 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
        if (!chip->onfi_version ||
            !(le16_to_cpu(chip->onfi_params.opt_cmd)
              & ONFI_OPT_CMD_SET_GET_FEATURES))
-               return -EINVAL;
+               return -ENOTSUPP;
 #endif
 
        chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
@@ -3070,7 +3070,7 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
        if (!chip->onfi_version ||
            !(le16_to_cpu(chip->onfi_params.opt_cmd)
              & ONFI_OPT_CMD_SET_GET_FEATURES))
-               return -EINVAL;
+               return -ENOTSUPP;
 #endif
 
        chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
index bb87aca6987ffbf3345e51912dc2d43efff1d393..3ccb168d1371584dd7a99affac105731ece471ba 100644 (file)
@@ -1369,7 +1369,7 @@ static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip)
                                                ONFI_FEATURE_ADDR_TIMING_MODE,
                                                feature);
                        chip->nand.select_chip(mtd, -1);
-                       if (ret)
+                       if (ret && ret != -ENOTSUPP)
                                return ret;
                }
        }
index 2b3cf48025cd1377d84d62bb56f9f113be8663e1..a7d7e3f044aeafeb8f9af084f6394eb96cfd03da 100644 (file)
@@ -117,9 +117,6 @@ struct sun4i_usb_phy_info {
                .gpio_vbus = CONFIG_USB3_VBUS_PIN,
                .gpio_vbus_det = NULL,
                .gpio_id_det = NULL,
-#ifdef CONFIG_MACH_SUN6I
-               .rst_mask = (CCM_USB_CTRL_PHY3_RST | CCM_USB_CTRL_PHY3_CLK),
-#endif
        },
 };
 
@@ -300,8 +297,7 @@ static int sun4i_usb_phy_init(struct phy *phy)
                                    data->cfg->disc_thresh, PHY_DISCON_TH_LEN);
        }
 
-       if (usb_phy->id != 0)
-               sun4i_usb_phy_passby(phy, true);
+       sun4i_usb_phy_passby(phy, true);
 
        sun4i_usb_phy0_reroute(data, true);
 
@@ -461,10 +457,10 @@ static int sun4i_usb_phy_probe(struct udevice *dev)
 
                phy->id = i;
                phy->rst_mask = info->rst_mask;
+               if ((data->cfg->type == sun8i_h3_phy) && (phy->id == 3))
+                       phy->rst_mask = (BIT(3) | BIT(11));
        };
 
-       setbits_le32(&data->ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
-
        debug("Allwinner Sun4I USB PHY driver loaded\n");
        return 0;
 }
index 4ed035d556a852d49903374a1d19bdf92838a772..8333ddc44c08d49c8ac11d41cf082a06c8fdce0b 100644 (file)
@@ -347,6 +347,9 @@ int sunxi_simplefb_setup(void *blob)
        if (ret) {
                debug("DE2 not present\n");
                return 0;
+       } else if (!device_active(de2)) {
+               debug("DE2 present but not probed\n");
+               return 0;
        }
 
        ret = uclass_find_device_by_name(UCLASS_DISPLAY,
index 9a357646ff04a893fc046eda5d96a381e103e674..f6d1cc53a1fc9c8b2d31a3cbcee44c5f3293b355 100644 (file)
@@ -294,4 +294,14 @@ int clk_disable_bulk(struct clk_bulk *bulk);
 
 int soc_clk_dump(void);
 
+/**
+ * clk_valid() - check if clk is valid
+ *
+ * @clk:       the clock to check
+ * @return true if valid, or false
+ */
+static inline bool clk_valid(struct clk *clk)
+{
+       return !!clk->dev;
+}
 #endif
index ff87adcd490babc0fa426d06c2f62e08ec7ac6e8..f1aa653a9ae413ef379f47fab9ae6e3f71fa4d40 100644 (file)
                        "setenv fdtfile am335x-bonegreen-wireless.dtb; fi; " \
                "if test $board_name = BBBL; then " \
                        "setenv fdtfile am335x-boneblue.dtb; fi; " \
+               "if test $board_name = BBEN; then " \
+                       "setenv fdtfile am335x-sancloud-bbe.dtb; fi; " \
                "if test $board_name = A33515BB; then " \
                        "setenv fdtfile am335x-evm.dtb; fi; " \
                "if test $board_name = A335X_SK; then " \
index 5081f3200e2a48d050d4da9bd9a3812e6179ac4d..72f04c3c18c5f1df3f7b96fe36cad213fe086d00 100644 (file)
  * function per_clocks_enable().
  */
 #ifdef CONFIG_SPL_BUILD
-#undef CONFIG_SYS_NS16550_COM3
-#define CONFIG_SYS_NS16550_COM2                OMAP34XX_UART2
 #undef CONFIG_SERIAL3
 #define CONFIG_SERIAL2
 #endif
index 4d811e096cc90642b4793fa2d2e42ab2a946e4c9..3b65a8505f01a26e526b155ec631c540d5501818 100644 (file)
 
 #include <configs/ti_omap3_common.h>
 
-#ifdef CONFIG_SPL_BUILD
-/* select serial console configuration for SPL */
-#define CONFIG_SYS_NS16550_COM1                OMAP34XX_UART1
-#endif
-
-
 /*
  * We are only ever GP parts and will utilize all of the "downloaded image"
  * area in SRAM which starts at 0x40200000 and ends at 0x4020FFFF (64KB) in
index 63c84b1ceb6a94ff8e2b3efc02e5c21a4ad35a49..af079a71ee56a59ce60758376a5a70e322d93b0d 100644 (file)
@@ -15,8 +15,6 @@
 #define CONFIG_USB_EHCI_SUNXI
 #endif
 
-#define CONFIG_SUNXI_USB_PHYS  3
-
 /*
  * Include common sunxi configuration where most the settings are
  */
index 5ce2cde388cb9558333f20e90b15a57a876d3a2b..2d73c75b8c0f332784c423c84209acb02db564d8 100644 (file)
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
 #endif
 
-#define CONFIG_SUNXI_USB_PHYS  1
-
+#ifndef CONFIG_MACH_SUN50I_H6
 #define GICD_BASE              0x1c81000
 #define GICC_BASE              0x1c82000
+#else
+#define GICD_BASE              0x3021000
+#define GICC_BASE              0x3022000
+#endif
 
 /*
  * Include common sunxi configuration where most the settings are
index cb33d01e16014dfdce732d541802d855a46dc8cb..c3692caa73eeba7da79eda32d7ae5cd375dffab8 100644 (file)
@@ -15,8 +15,6 @@
 #define CONFIG_USB_EHCI_SUNXI
 #endif
 
-#define CONFIG_SUNXI_USB_PHYS  2
-
 /*
  * Include common sunxi configuration where most the settings are
  */
index a3f768f93648e2580cebcf6b8ceb96e6f50ec88a..1523684fadef89b205d14babbcbe8c3203326b57 100644 (file)
@@ -18,8 +18,6 @@
 #define CONFIG_USB_EHCI_SUNXI
 #endif
 
-#define CONFIG_SUNXI_USB_PHYS  3
-
 #define CONFIG_ARMV7_SECURE_BASE       SUNXI_SRAM_B_BASE
 #define CONFIG_ARMV7_SECURE_MAX_SIZE    (64 * 1024) /* 64 KB */
 
index d3c4c7dbcf8579e93c8be5cbf5036b449cd190fe..bb8f217b25da6b41d440b83574a71a0e4dfbfaa3 100644 (file)
@@ -16,8 +16,6 @@
 #define CONFIG_USB_EHCI_SUNXI
 #endif
 
-#define CONFIG_SUNXI_USB_PHYS  3
-
 #define CONFIG_ARMV7_SECURE_BASE       SUNXI_SRAM_B_BASE
 #define CONFIG_ARMV7_SECURE_MAX_SIZE   (64 * 1024) /* 64 KB */
 
index 4fdf68a4915a2c240be711d2627ca448433ca7e8..7dc8693b765cc6559d9a9d872f201266453b3a13 100644 (file)
 #define CONFIG_USB_EHCI_SUNXI
 #endif
 
-#ifdef CONFIG_MACH_SUN8I_H3
-       #define CONFIG_SUNXI_USB_PHYS   4
-#elif defined CONFIG_MACH_SUN8I_A83T
-       #define CONFIG_SUNXI_USB_PHYS   3
-#elif defined CONFIG_MACH_SUN8I_V3S
-       #define CONFIG_SUNXI_USB_PHYS   1
-#else
-       #define CONFIG_SUNXI_USB_PHYS   2
-#endif
-
 /*
  * Include common sunxi configuration where most the settings are
  */
index 516b5f2d08119789aa0286a317d1c5129508426a..93690481a1a5aad9d551131737a4e302efb902c8 100644 (file)
 
 #define CONFIG_SPL_BSS_MAX_SIZE                0x00080000 /* 512 KiB */
 
-#ifdef CONFIG_SUNXI_HIGH_SRAM
 /*
  * The A80's A1 sram starts at 0x00010000 rather then at 0x00000000 and is
  * slightly bigger. Note that it is possible to map the first 32 KiB of the
  * A1 at 0x00000000 like with older SoCs by writing 0x16aa0001 to the
  * undocumented 0x008000e0 SYS_CTRL register. Where the 16aa is a key and
  * the 1 actually activates the mapping of the first 32 KiB to 0x00000000.
+ * A64 and H5 also has SRAM A1 at 0x00010000, but no magic remap register
+ * is known yet.
+ * H6 has SRAM A1 at 0x00020000.
  */
-#define CONFIG_SYS_INIT_RAM_ADDR       0x10000
-#define CONFIG_SYS_INIT_RAM_SIZE       0x08000 /* FIXME: 40 KiB ? */
-#else
-#define CONFIG_SYS_INIT_RAM_ADDR       0x0
-#define CONFIG_SYS_INIT_RAM_SIZE       0x8000  /* 32 KiB */
-#endif
+#define CONFIG_SYS_INIT_RAM_ADDR       CONFIG_SUNXI_SRAM_ADDRESS
+/* FIXME: this may be larger on some SoCs */
+#define CONFIG_SYS_INIT_RAM_SIZE       0x8000 /* 32 KiB */
 
 #define CONFIG_SYS_INIT_SP_OFFSET \
        (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
 #define CONFIG_SPL_BOARD_LOAD_IMAGE
 #endif
 
-#ifdef CONFIG_SUNXI_HIGH_SRAM
+/*
+ * We cannot use expressions here, because expressions won't be evaluated in
+ * autoconf.mk.
+ */
+#if CONFIG_SUNXI_SRAM_ADDRESS == 0x10000
 #define CONFIG_SPL_TEXT_BASE           0x10060         /* sram start+header */
 #define CONFIG_SPL_MAX_SIZE            0x7fa0          /* 32 KiB */
 #ifdef CONFIG_ARM64
 #else
 #define LOW_LEVEL_SRAM_STACK           0x00018000
 #endif /* !CONFIG_ARM64 */
+#elif CONFIG_SUNXI_SRAM_ADDRESS == 0x20000
+#define CONFIG_SPL_TEXT_BASE           0x20060         /* sram start+header */
+#define CONFIG_SPL_MAX_SIZE            0x7fa0          /* 32 KiB */
+/* end of SRAM A2 on H6 for now */
+#define LOW_LEVEL_SRAM_STACK           0x00118000
 #else
 #define CONFIG_SPL_TEXT_BASE           0x60            /* sram start+header */
 #define CONFIG_SPL_MAX_SIZE            0x5fa0          /* 24KB on sun4i/sun7i */
index 7cd4272ce5bf3efd861c3cfe830e43dcd8eeaaf4..6d16fc782bd2b8a342c84f6b2286ef6568ca07d2 100644 (file)
@@ -38,6 +38,8 @@
 
 /* Select serial console configuration */
 #ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_NS16550_COM1                OMAP34XX_UART1
+#define CONFIG_SYS_NS16550_COM2                OMAP34XX_UART2
 #define CONFIG_SYS_NS16550_COM3                OMAP34XX_UART3
 #define CONFIG_SERIAL3                 3
 #endif
diff --git a/include/dt-bindings/clock/sun50i-h6-ccu.h b/include/dt-bindings/clock/sun50i-h6-ccu.h
new file mode 100644 (file)
index 0000000..a1545cd
--- /dev/null
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_H6_H_
+#define _DT_BINDINGS_CLK_SUN50I_H6_H_
+
+#define CLK_PLL_PERIPH0                3
+
+#define CLK_CPUX               21
+
+#define CLK_APB1               26
+
+#define CLK_DE                 29
+#define CLK_BUS_DE             30
+#define CLK_DEINTERLACE                31
+#define CLK_BUS_DEINTERLACE    32
+#define CLK_GPU                        33
+#define CLK_BUS_GPU            34
+#define CLK_CE                 35
+#define CLK_BUS_CE             36
+#define CLK_VE                 37
+#define CLK_BUS_VE             38
+#define CLK_EMCE               39
+#define CLK_BUS_EMCE           40
+#define CLK_VP9                        41
+#define CLK_BUS_VP9            42
+#define CLK_BUS_DMA            43
+#define CLK_BUS_MSGBOX         44
+#define CLK_BUS_SPINLOCK       45
+#define CLK_BUS_HSTIMER                46
+#define CLK_AVS                        47
+#define CLK_BUS_DBG            48
+#define CLK_BUS_PSI            49
+#define CLK_BUS_PWM            50
+#define CLK_BUS_IOMMU          51
+
+#define CLK_MBUS_DMA           53
+#define CLK_MBUS_VE            54
+#define CLK_MBUS_CE            55
+#define CLK_MBUS_TS            56
+#define CLK_MBUS_NAND          57
+#define CLK_MBUS_CSI           58
+#define CLK_MBUS_DEINTERLACE   59
+
+#define CLK_NAND0              61
+#define CLK_NAND1              62
+#define CLK_BUS_NAND           63
+#define CLK_MMC0               64
+#define CLK_MMC1               65
+#define CLK_MMC2               66
+#define CLK_BUS_MMC0           67
+#define CLK_BUS_MMC1           68
+#define CLK_BUS_MMC2           69
+#define CLK_BUS_UART0          70
+#define CLK_BUS_UART1          71
+#define CLK_BUS_UART2          72
+#define CLK_BUS_UART3          73
+#define CLK_BUS_I2C0           74
+#define CLK_BUS_I2C1           75
+#define CLK_BUS_I2C2           76
+#define CLK_BUS_I2C3           77
+#define CLK_BUS_SCR0           78
+#define CLK_BUS_SCR1           79
+#define CLK_SPI0               80
+#define CLK_SPI1               81
+#define CLK_BUS_SPI0           82
+#define CLK_BUS_SPI1           83
+#define CLK_BUS_EMAC           84
+#define CLK_TS                 85
+#define CLK_BUS_TS             86
+#define CLK_IR_TX              87
+#define CLK_BUS_IR_TX          88
+#define CLK_BUS_THS            89
+#define CLK_I2S3               90
+#define CLK_I2S0               91
+#define CLK_I2S1               92
+#define CLK_I2S2               93
+#define CLK_BUS_I2S0           94
+#define CLK_BUS_I2S1           95
+#define CLK_BUS_I2S2           96
+#define CLK_BUS_I2S3           97
+#define CLK_SPDIF              98
+#define CLK_BUS_SPDIF          99
+#define CLK_DMIC               100
+#define CLK_BUS_DMIC           101
+#define CLK_AUDIO_HUB          102
+#define CLK_BUS_AUDIO_HUB      103
+#define CLK_USB_OHCI0          104
+#define CLK_USB_PHY0           105
+#define CLK_USB_PHY1           106
+#define CLK_USB_OHCI3          107
+#define CLK_USB_PHY3           108
+#define CLK_USB_HSIC_12M       109
+#define CLK_USB_HSIC           110
+#define CLK_BUS_OHCI0          111
+#define CLK_BUS_OHCI3          112
+#define CLK_BUS_EHCI0          113
+#define CLK_BUS_XHCI           114
+#define CLK_BUS_EHCI3          115
+#define CLK_BUS_OTG            116
+#define CLK_PCIE_REF_100M      117
+#define CLK_PCIE_REF           118
+#define CLK_PCIE_REF_OUT       119
+#define CLK_PCIE_MAXI          120
+#define CLK_PCIE_AUX           121
+#define CLK_BUS_PCIE           122
+#define CLK_HDMI               123
+#define CLK_HDMI_SLOW          124
+#define CLK_HDMI_CEC           125
+#define CLK_BUS_HDMI           126
+#define CLK_BUS_TCON_TOP       127
+#define CLK_TCON_LCD0          128
+#define CLK_BUS_TCON_LCD0      129
+#define CLK_TCON_TV0           130
+#define CLK_BUS_TCON_TV0       131
+#define CLK_CSI_CCI            132
+#define CLK_CSI_TOP            133
+#define CLK_CSI_MCLK           134
+#define CLK_BUS_CSI            135
+#define CLK_HDCP               136
+#define CLK_BUS_HDCP           137
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_H6_H_ */
diff --git a/include/dt-bindings/clock/sun50i-h6-r-ccu.h b/include/dt-bindings/clock/sun50i-h6-r-ccu.h
new file mode 100644 (file)
index 0000000..7613613
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_
+
+#define CLK_AR100              0
+
+#define CLK_R_APB1             2
+
+#define CLK_R_APB1_TIMER       4
+#define CLK_R_APB1_TWD         5
+#define CLK_R_APB1_PWM         6
+#define CLK_R_APB2_UART                7
+#define CLK_R_APB2_I2C         8
+#define CLK_R_APB1_IR          9
+#define CLK_R_APB1_W1          10
+
+#define CLK_IR                 11
+#define CLK_W1                 12
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun50i-h6-ccu.h b/include/dt-bindings/reset/sun50i-h6-ccu.h
new file mode 100644 (file)
index 0000000..81106f4
--- /dev/null
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN50I_H6_H_
+#define _DT_BINDINGS_RESET_SUN50I_H6_H_
+
+#define RST_MBUS               0
+#define RST_BUS_DE             1
+#define RST_BUS_DEINTERLACE    2
+#define RST_BUS_GPU            3
+#define RST_BUS_CE             4
+#define RST_BUS_VE             5
+#define RST_BUS_EMCE           6
+#define RST_BUS_VP9            7
+#define RST_BUS_DMA            8
+#define RST_BUS_MSGBOX         9
+#define RST_BUS_SPINLOCK       10
+#define RST_BUS_HSTIMER                11
+#define RST_BUS_DBG            12
+#define RST_BUS_PSI            13
+#define RST_BUS_PWM            14
+#define RST_BUS_IOMMU          15
+#define RST_BUS_DRAM           16
+#define RST_BUS_NAND           17
+#define RST_BUS_MMC0           18
+#define RST_BUS_MMC1           19
+#define RST_BUS_MMC2           20
+#define RST_BUS_UART0          21
+#define RST_BUS_UART1          22
+#define RST_BUS_UART2          23
+#define RST_BUS_UART3          24
+#define RST_BUS_I2C0           25
+#define RST_BUS_I2C1           26
+#define RST_BUS_I2C2           27
+#define RST_BUS_I2C3           28
+#define RST_BUS_SCR0           29
+#define RST_BUS_SCR1           30
+#define RST_BUS_SPI0           31
+#define RST_BUS_SPI1           32
+#define RST_BUS_EMAC           33
+#define RST_BUS_TS             34
+#define RST_BUS_IR_TX          35
+#define RST_BUS_THS            36
+#define RST_BUS_I2S0           37
+#define RST_BUS_I2S1           38
+#define RST_BUS_I2S2           39
+#define RST_BUS_I2S3           40
+#define RST_BUS_SPDIF          41
+#define RST_BUS_DMIC           42
+#define RST_BUS_AUDIO_HUB      43
+#define RST_USB_PHY0           44
+#define RST_USB_PHY1           45
+#define RST_USB_PHY3           46
+#define RST_USB_HSIC           47
+#define RST_BUS_OHCI0          48
+#define RST_BUS_OHCI3          49
+#define RST_BUS_EHCI0          50
+#define RST_BUS_XHCI           51
+#define RST_BUS_EHCI3          52
+#define RST_BUS_OTG            53
+#define RST_BUS_PCIE           54
+#define RST_PCIE_POWERUP       55
+#define RST_BUS_HDMI           56
+#define RST_BUS_HDMI_SUB       57
+#define RST_BUS_TCON_TOP       58
+#define RST_BUS_TCON_LCD0      59
+#define RST_BUS_TCON_TV0       60
+#define RST_BUS_CSI            61
+#define RST_BUS_HDCP           62
+
+#endif /* _DT_BINDINGS_RESET_SUN50I_H6_H_ */
diff --git a/include/dt-bindings/reset/sun50i-h6-r-ccu.h b/include/dt-bindings/reset/sun50i-h6-r-ccu.h
new file mode 100644 (file)
index 0000000..01c84db
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_
+
+#define RST_R_APB1_TIMER       0
+#define RST_R_APB1_TWD         1
+#define RST_R_APB1_PWM         2
+#define RST_R_APB2_UART                3
+#define RST_R_APB2_I2C         4
+#define RST_R_APB1_IR          5
+#define RST_R_APB1_W1          6
+
+#endif /* _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_ */
index 86287874e1b433734ed2c900cee621a5c07e3268..7fad62c043ee082422107872102c5483853b0ffa 100644 (file)
@@ -60,7 +60,7 @@ struct spl_load_info {
  * 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);
+binman_sym_extern(ulong, u_boot_any, image_pos);
 
 /**
  * spl_load_simple_fit() - Loads a fit image from a device.
index 17b903b0f5bf03d427dc9e95a664db601d88324d..08cc824bac3dd4453b11a533a316f36477dc2b9c 100644 (file)
@@ -2,4 +2,3 @@
 # Generated files
 #
 bin2c
-docproc
index e27308a97a570c2c78903f980c3fe2a7020b982a..e7b353f77f43e1d8b572826f3c1d619abd41f17b 100644 (file)
@@ -3,20 +3,11 @@
 # scripts contains sources for various helper programs used throughout
 # the kernel for the build process.
 # ---------------------------------------------------------------------------
-# docproc:       Used in Documentation/DocBook
 
 hostprogs-$(CONFIG_BUILD_BIN2C)                += bin2c
 
 always         := $(hostprogs-y)
 
-# The following hostprogs-y programs are only build on demand
-hostprogs-y += docproc
-
-# These targets are used internally to avoid "is up to date" messages
-PHONY += build_docproc
-build_docproc: $(obj)/docproc
-       @:
-
 # Let clean descend into subdirs
 subdir-        += basic kconfig
 subdir-$(CONFIG_DTC)   += dtc
index 7ced4099f22827961fe4a5aaced87623914ddf21..0d60da3f2815ff32123079b9c1406b1915788c76 100644 (file)
@@ -2011,7 +2011,6 @@ CONFIG_ST_SMI
 CONFIG_SUNXI_AHCI
 CONFIG_SUNXI_GPIO
 CONFIG_SUNXI_MAX_FB_SIZE
-CONFIG_SUNXI_USB_PHYS
 CONFIG_SUPERH_ON_CHIP_R8A66597
 CONFIG_SUPPORT_EMMC_BOOT
 CONFIG_SUVD3
diff --git a/scripts/docproc.c b/scripts/docproc.c
deleted file mode 100644 (file)
index e267e62..0000000
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- *     docproc is a simple preprocessor for the template files
- *      used as placeholders for the kernel internal documentation.
- *     docproc is used for documentation-frontend and
- *      dependency-generator.
- *     The two usages have in common that they require
- *     some knowledge of the .tmpl syntax, therefore they
- *     are kept together.
- *
- *     documentation-frontend
- *             Scans the template file and call kernel-doc for
- *             all occurrences of ![EIF]file
- *             Beforehand each referenced file is scanned for
- *             any symbols that are exported via these macros:
- *                     EXPORT_SYMBOL(), EXPORT_SYMBOL_GPL(), &
- *                     EXPORT_SYMBOL_GPL_FUTURE()
- *             This is used to create proper -function and
- *             -nofunction arguments in calls to kernel-doc.
- *             Usage: docproc doc file.tmpl
- *
- *     dependency-generator:
- *             Scans the template file and list all files
- *             referenced in a format recognized by make.
- *             Usage:  docproc depend file.tmpl
- *             Writes dependency information to stdout
- *             in the following format:
- *             file.tmpl src.c src2.c
- *             The filenames are obtained from the following constructs:
- *             !Efilename
- *             !Ifilename
- *             !Dfilename
- *             !Ffilename
- *             !Pfilename
- *
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-/* exitstatus is used to keep track of any failing calls to kernel-doc,
- * but execution continues. */
-int exitstatus = 0;
-
-typedef void DFL(char *);
-DFL *defaultline;
-
-typedef void FILEONLY(char * file);
-FILEONLY *internalfunctions;
-FILEONLY *externalfunctions;
-FILEONLY *symbolsonly;
-FILEONLY *findall;
-
-typedef void FILELINE(char * file, char * line);
-FILELINE * singlefunctions;
-FILELINE * entity_system;
-FILELINE * docsection;
-
-#define MAXLINESZ     2048
-#define MAXFILES      250
-#define KERNELDOCPATH "scripts/"
-#define KERNELDOC     "kernel-doc"
-#define DOCBOOK       "-docbook"
-#define LIST          "-list"
-#define FUNCTION      "-function"
-#define NOFUNCTION    "-nofunction"
-#define NODOCSECTIONS "-no-doc-sections"
-#define SHOWNOTFOUND  "-show-not-found"
-
-static char *srctree, *kernsrctree;
-
-static char **all_list = NULL;
-static int all_list_len = 0;
-
-static void consume_symbol(const char *sym)
-{
-       int i;
-
-       for (i = 0; i < all_list_len; i++) {
-               if (!all_list[i])
-                       continue;
-               if (strcmp(sym, all_list[i]))
-                       continue;
-               all_list[i] = NULL;
-               break;
-       }
-}
-
-static void usage (void)
-{
-       fprintf(stderr, "Usage: docproc {doc|depend} file\n");
-       fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
-       fprintf(stderr, "doc: frontend when generating kernel documentation\n");
-       fprintf(stderr, "depend: generate list of files referenced within file\n");
-       fprintf(stderr, "Environment variable SRCTREE: absolute path to sources.\n");
-       fprintf(stderr, "                     KBUILD_SRC: absolute path to kernel source tree.\n");
-}
-
-/*
- * Execute kernel-doc with parameters given in svec
- */
-static void exec_kernel_doc(char **svec)
-{
-       pid_t pid;
-       int ret;
-       char real_filename[PATH_MAX + 1];
-       /* Make sure output generated so far are flushed */
-       fflush(stdout);
-       switch (pid=fork()) {
-               case -1:
-                       perror("fork");
-                       exit(1);
-               case  0:
-                       memset(real_filename, 0, sizeof(real_filename));
-                       strncat(real_filename, kernsrctree, PATH_MAX);
-                       strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
-                                       PATH_MAX - strlen(real_filename));
-                       execvp(real_filename, svec);
-                       fprintf(stderr, "exec ");
-                       perror(real_filename);
-                       exit(1);
-               default:
-                       waitpid(pid, &ret ,0);
-       }
-       if (WIFEXITED(ret))
-               exitstatus |= WEXITSTATUS(ret);
-       else
-               exitstatus = 0xff;
-}
-
-/* Types used to create list of all exported symbols in a number of files */
-struct symbols
-{
-       char *name;
-};
-
-struct symfile
-{
-       char *filename;
-       struct symbols *symbollist;
-       int symbolcnt;
-};
-
-struct symfile symfilelist[MAXFILES];
-int symfilecnt = 0;
-
-static void add_new_symbol(struct symfile *sym, char * symname)
-{
-       sym->symbollist =
-         realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
-       sym->symbollist[sym->symbolcnt++].name = strdup(symname);
-}
-
-/* Add a filename to the list */
-static struct symfile * add_new_file(char * filename)
-{
-       symfilelist[symfilecnt++].filename = strdup(filename);
-       return &symfilelist[symfilecnt - 1];
-}
-
-/* Check if file already are present in the list */
-static struct symfile * filename_exist(char * filename)
-{
-       int i;
-       for (i=0; i < symfilecnt; i++)
-               if (strcmp(symfilelist[i].filename, filename) == 0)
-                       return &symfilelist[i];
-       return NULL;
-}
-
-/*
- * List all files referenced within the template file.
- * Files are separated by tabs.
- */
-static void adddep(char * file)                   { printf("\t%s", file); }
-static void adddep2(char * file, char * line)     { line = line; adddep(file); }
-static void noaction(char * line)                 { line = line; }
-static void noaction2(char * file, char * line)   { file = file; line = line; }
-
-/* Echo the line without further action */
-static void printline(char * line)               { printf("%s", line); }
-
-/*
- * Find all symbols in filename that are exported with EXPORT_SYMBOL &
- * EXPORT_SYMBOL_GPL (& EXPORT_SYMBOL_GPL_FUTURE implicitly).
- * All symbols located are stored in symfilelist.
- */
-static void find_export_symbols(char * filename)
-{
-       FILE * fp;
-       struct symfile *sym;
-       char line[MAXLINESZ];
-       if (filename_exist(filename) == NULL) {
-               char real_filename[PATH_MAX + 1];
-               memset(real_filename, 0, sizeof(real_filename));
-               strncat(real_filename, srctree, PATH_MAX);
-               strncat(real_filename, "/", PATH_MAX - strlen(real_filename));
-               strncat(real_filename, filename,
-                               PATH_MAX - strlen(real_filename));
-               sym = add_new_file(filename);
-               fp = fopen(real_filename, "r");
-               if (fp == NULL) {
-                       fprintf(stderr, "docproc: ");
-                       perror(real_filename);
-                       exit(1);
-               }
-               while (fgets(line, MAXLINESZ, fp)) {
-                       char *p;
-                       char *e;
-                       if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != NULL) ||
-                           ((p = strstr(line, "EXPORT_SYMBOL")) != NULL)) {
-                               /* Skip EXPORT_SYMBOL{_GPL} */
-                               while (isalnum(*p) || *p == '_')
-                                       p++;
-                               /* Remove parentheses & additional whitespace */
-                               while (isspace(*p))
-                                       p++;
-                               if (*p != '(')
-                                       continue; /* Syntax error? */
-                               else
-                                       p++;
-                               while (isspace(*p))
-                                       p++;
-                               e = p;
-                               while (isalnum(*e) || *e == '_')
-                                       e++;
-                               *e = '\0';
-                               add_new_symbol(sym, p);
-                       }
-               }
-               fclose(fp);
-       }
-}
-
-/*
- * Document all external or internal functions in a file.
- * Call kernel-doc with following parameters:
- * kernel-doc -docbook -nofunction function_name1 filename
- * Function names are obtained from all the src files
- * by find_export_symbols.
- * intfunc uses -nofunction
- * extfunc uses -function
- */
-static void docfunctions(char * filename, char * type)
-{
-       int i,j;
-       int symcnt = 0;
-       int idx = 0;
-       char **vec;
-
-       for (i=0; i <= symfilecnt; i++)
-               symcnt += symfilelist[i].symbolcnt;
-       vec = malloc((2 + 2 * symcnt + 3) * sizeof(char *));
-       if (vec == NULL) {
-               perror("docproc: ");
-               exit(1);
-       }
-       vec[idx++] = KERNELDOC;
-       vec[idx++] = DOCBOOK;
-       vec[idx++] = NODOCSECTIONS;
-       for (i=0; i < symfilecnt; i++) {
-               struct symfile * sym = &symfilelist[i];
-               for (j=0; j < sym->symbolcnt; j++) {
-                       vec[idx++]     = type;
-                       consume_symbol(sym->symbollist[j].name);
-                       vec[idx++] = sym->symbollist[j].name;
-               }
-       }
-       vec[idx++]     = filename;
-       vec[idx] = NULL;
-       printf("<!-- %s -->\n", filename);
-       exec_kernel_doc(vec);
-       fflush(stdout);
-       free(vec);
-}
-static void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); }
-static void extfunc(char * filename) { docfunctions(filename, FUNCTION);   }
-
-/*
- * Document specific function(s) in a file.
- * Call kernel-doc with the following parameters:
- * kernel-doc -docbook -function function1 [-function function2]
- */
-static void singfunc(char * filename, char * line)
-{
-       char *vec[200]; /* Enough for specific functions */
-       int i, idx = 0;
-       int startofsym = 1;
-       vec[idx++] = KERNELDOC;
-       vec[idx++] = DOCBOOK;
-       vec[idx++] = SHOWNOTFOUND;
-
-       /* Split line up in individual parameters preceded by FUNCTION */
-       for (i=0; line[i]; i++) {
-               if (isspace(line[i])) {
-                       line[i] = '\0';
-                       startofsym = 1;
-                       continue;
-               }
-               if (startofsym) {
-                       startofsym = 0;
-                       vec[idx++] = FUNCTION;
-                       vec[idx++] = &line[i];
-               }
-       }
-       for (i = 0; i < idx; i++) {
-               if (strcmp(vec[i], FUNCTION))
-                       continue;
-               consume_symbol(vec[i + 1]);
-       }
-       vec[idx++] = filename;
-       vec[idx] = NULL;
-       exec_kernel_doc(vec);
-}
-
-/*
- * Insert specific documentation section from a file.
- * Call kernel-doc with the following parameters:
- * kernel-doc -docbook -function "doc section" filename
- */
-static void docsect(char *filename, char *line)
-{
-       /* kerneldoc -docbook -show-not-found -function "section" file NULL */
-       char *vec[7];
-       char *s;
-
-       for (s = line; *s; s++)
-               if (*s == '\n')
-                       *s = '\0';
-
-       if (asprintf(&s, "DOC: %s", line) < 0) {
-               perror("asprintf");
-               exit(1);
-       }
-       consume_symbol(s);
-       free(s);
-
-       vec[0] = KERNELDOC;
-       vec[1] = DOCBOOK;
-       vec[2] = SHOWNOTFOUND;
-       vec[3] = FUNCTION;
-       vec[4] = line;
-       vec[5] = filename;
-       vec[6] = NULL;
-       exec_kernel_doc(vec);
-}
-
-static void find_all_symbols(char *filename)
-{
-       char *vec[4]; /* kerneldoc -list file NULL */
-       pid_t pid;
-       int ret, i, count, start;
-       char real_filename[PATH_MAX + 1];
-       int pipefd[2];
-       char *data, *str;
-       size_t data_len = 0;
-
-       vec[0] = KERNELDOC;
-       vec[1] = LIST;
-       vec[2] = filename;
-       vec[3] = NULL;
-
-       if (pipe(pipefd)) {
-               perror("pipe");
-               exit(1);
-       }
-
-       switch (pid=fork()) {
-               case -1:
-                       perror("fork");
-                       exit(1);
-               case  0:
-                       close(pipefd[0]);
-                       dup2(pipefd[1], 1);
-                       memset(real_filename, 0, sizeof(real_filename));
-                       strncat(real_filename, kernsrctree, PATH_MAX);
-                       strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
-                                       PATH_MAX - strlen(real_filename));
-                       execvp(real_filename, vec);
-                       fprintf(stderr, "exec ");
-                       perror(real_filename);
-                       exit(1);
-               default:
-                       close(pipefd[1]);
-                       data = malloc(4096);
-                       do {
-                               while ((ret = read(pipefd[0],
-                                                  data + data_len,
-                                                  4096)) > 0) {
-                                       data_len += ret;
-                                       data = realloc(data, data_len + 4096);
-                               }
-                       } while (ret == -EAGAIN);
-                       if (ret != 0) {
-                               perror("read");
-                               exit(1);
-                       }
-                       waitpid(pid, &ret ,0);
-       }
-       if (WIFEXITED(ret))
-               exitstatus |= WEXITSTATUS(ret);
-       else
-               exitstatus = 0xff;
-
-       count = 0;
-       /* poor man's strtok, but with counting */
-       for (i = 0; i < data_len; i++) {
-               if (data[i] == '\n') {
-                       count++;
-                       data[i] = '\0';
-               }
-       }
-       start = all_list_len;
-       all_list_len += count;
-       all_list = realloc(all_list, sizeof(char *) * all_list_len);
-       str = data;
-       for (i = 0; i < data_len && start != all_list_len; i++) {
-               if (data[i] == '\0') {
-                       all_list[start] = str;
-                       str = data + i + 1;
-                       start++;
-               }
-       }
-}
-
-/*
- * Parse file, calling action specific functions for:
- * 1) Lines containing !E
- * 2) Lines containing !I
- * 3) Lines containing !D
- * 4) Lines containing !F
- * 5) Lines containing !P
- * 6) Lines containing !C
- * 7) Default lines - lines not matching the above
- */
-static void parse_file(FILE *infile)
-{
-       char line[MAXLINESZ];
-       char * s;
-       while (fgets(line, MAXLINESZ, infile)) {
-               if (line[0] == '!') {
-                       s = line + 2;
-                       switch (line[1]) {
-                               case 'E':
-                                       while (*s && !isspace(*s)) s++;
-                                       *s = '\0';
-                                       externalfunctions(line+2);
-                                       break;
-                               case 'I':
-                                       while (*s && !isspace(*s)) s++;
-                                       *s = '\0';
-                                       internalfunctions(line+2);
-                                       break;
-                               case 'D':
-                                       while (*s && !isspace(*s)) s++;
-                                       *s = '\0';
-                                       symbolsonly(line+2);
-                                       break;
-                               case 'F':
-                                       /* filename */
-                                       while (*s && !isspace(*s)) s++;
-                                       *s++ = '\0';
-                                       /* function names */
-                                       while (isspace(*s))
-                                               s++;
-                                       singlefunctions(line +2, s);
-                                       break;
-                               case 'P':
-                                       /* filename */
-                                       while (*s && !isspace(*s)) s++;
-                                       *s++ = '\0';
-                                       /* DOC: section name */
-                                       while (isspace(*s))
-                                               s++;
-                                       docsection(line + 2, s);
-                                       break;
-                               case 'C':
-                                       while (*s && !isspace(*s)) s++;
-                                       *s = '\0';
-                                       if (findall)
-                                               findall(line+2);
-                                       break;
-                               default:
-                                       defaultline(line);
-                       }
-               } else {
-                       defaultline(line);
-               }
-       }
-       fflush(stdout);
-}
-
-
-int main(int argc, char *argv[])
-{
-       FILE * infile;
-       int i;
-
-       srctree = getenv("SRCTREE");
-       if (!srctree)
-               srctree = getcwd(NULL, 0);
-       kernsrctree = getenv("KBUILD_SRC");
-       if (!kernsrctree || !*kernsrctree)
-               kernsrctree = srctree;
-       if (argc != 3) {
-               usage();
-               exit(1);
-       }
-       /* Open file, exit on error */
-       infile = fopen(argv[2], "r");
-       if (infile == NULL) {
-               fprintf(stderr, "docproc: ");
-               perror(argv[2]);
-               exit(2);
-       }
-
-       if (strcmp("doc", argv[1]) == 0) {
-               /* Need to do this in two passes.
-                * First pass is used to collect all symbols exported
-                * in the various files;
-                * Second pass generate the documentation.
-                * This is required because some functions are declared
-                * and exported in different files :-((
-                */
-               /* Collect symbols */
-               defaultline       = noaction;
-               internalfunctions = find_export_symbols;
-               externalfunctions = find_export_symbols;
-               symbolsonly       = find_export_symbols;
-               singlefunctions   = noaction2;
-               docsection        = noaction2;
-               findall           = find_all_symbols;
-               parse_file(infile);
-
-               /* Rewind to start from beginning of file again */
-               fseek(infile, 0, SEEK_SET);
-               defaultline       = printline;
-               internalfunctions = intfunc;
-               externalfunctions = extfunc;
-               symbolsonly       = printline;
-               singlefunctions   = singfunc;
-               docsection        = docsect;
-               findall           = NULL;
-
-               parse_file(infile);
-
-               for (i = 0; i < all_list_len; i++) {
-                       if (!all_list[i])
-                               continue;
-                       fprintf(stderr, "Warning: didn't use docs for %s\n",
-                               all_list[i]);
-               }
-       } else if (strcmp("depend", argv[1]) == 0) {
-               /* Create first part of dependency chain
-                * file.tmpl */
-               printf("%s\t", argv[2]);
-               defaultline       = noaction;
-               internalfunctions = adddep;
-               externalfunctions = adddep;
-               symbolsonly       = adddep;
-               singlefunctions   = adddep2;
-               docsection        = adddep2;
-               findall           = adddep;
-               parse_file(infile);
-               printf("\n");
-       } else {
-               fprintf(stderr, "Unknown option: %s\n", argv[1]);
-               exit(1);
-       }
-       fclose(infile);
-       fflush(stdout);
-       return exitstatus;
-}
index b06906a3ecfa42ac84383f56ecb1baf9e0ab9562..898c034e27bfb1de7dc0b18f190f2dfb354714e4 100644 (file)
@@ -28,6 +28,7 @@ static int dm_test_clk(struct unit_test_state *uts)
        ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test",
                                              &dev_test));
        ut_assertok(sandbox_clk_test_get(dev_test));
+       ut_assertok(sandbox_clk_test_valid(dev_test));
 
        ut_asserteq(1234,
                    sandbox_clk_test_get_rate(dev_test,
index 207928aa9554ce6037bdb5737d822805446f42bd..cb34171e5fce6718844edc8c4d53e38c0b522d4a 100644 (file)
@@ -238,7 +238,7 @@ below:
                        filename = "spl/sunxi-spl.bin";
                };
                u-boot {
-                       pos = <CONFIG_SPL_PAD_TO>;
+                       offset = <CONFIG_SPL_PAD_TO>;
                };
        };
 
@@ -257,7 +257,7 @@ provide a filename. For 'u-boot', binman knows that this means 'u-boot.bin'.
 
 Entries are normally placed into the image sequentially, one after the other.
 The image size is the total size of all entries. As you can see, you can
-specify the start position of an entry using the 'pos' property.
+specify the start offset of an entry using the 'offset' property.
 
 Note that due to a device tree requirement, all entries must have a unique
 name. If you want to put the same binary in the image multiple times, you can
@@ -265,14 +265,15 @@ use any unique name, with the 'type' property providing the type.
 
 The attributes supported for entries are described below.
 
-pos:
-       This sets the position of an entry within the image. The first byte
-       of the image is normally at position 0. If 'pos' is not provided,
-       binman sets it to the end of the previous region, or the start of
-       the image's entry area (normally 0) if there is no previous region.
+offset:
+       This sets the offset of an entry within the image or section containing
+       it. The first byte of the image is normally at offset 0. If 'offset' is
+       not provided, binman sets it to the end of the previous region, or the
+       start of the image's entry area (normally 0) if there is no previous
+       region.
 
 align:
-       This sets the alignment of the entry. The entry position is adjusted
+       This sets the alignment of the entry. The entry offset is adjusted
        so that the entry starts on an aligned boundary within the image. For
        example 'align = <16>' means that the entry will start on a 16-byte
        boundary. Alignment shold be a power of 2. If 'align' is not
@@ -316,12 +317,18 @@ type:
        possible to use any name, and then add (for example) 'type = "u-boot"'
        to specify the type.
 
-pos-unset:
-       Indicates that the position of this entry should not be set by placing
+offset-unset:
+       Indicates that the offset of this entry should not be set by placing
        it immediately after the entry before. Instead, is set by another
        entry which knows where this entry should go. When this boolean
        property is present, binman will give an error if another entry does
-       not set the position (with the GetPositions() method).
+       not set the offset (with the GetOffsets() method).
+
+image-pos:
+       This cannot be set on entry (or at least it is ignored if it is), but
+       with the -u option, binman will set it to the absolute image position
+       for each entry. This makes it easy to find out exactly where the entry
+       ended up in the image, regardless of parent sections, etc.
 
 
 The attributes supported for images are described below. Several are similar
@@ -338,7 +345,7 @@ align-size:
 
 pad-before:
        This sets the padding before the image entries. The first entry will
-       be positionad after the padding. This defaults to 0.
+       be positioned after the padding. This defaults to 0.
 
 pad-after:
        This sets the padding after the image entries. The padding will be
@@ -351,15 +358,15 @@ pad-byte:
 filename:
        This specifies the image filename. It defaults to 'image.bin'.
 
-sort-by-pos:
+sort-by-offset:
        This causes binman to reorder the entries as needed to make sure they
        are in increasing positional order. This can be used when your entry
        order may not match the positional order. A common situation is where
-       the 'pos' properties are set by CONFIG options, so their ordering is
+       the 'offset' properties are set by CONFIG options, so their ordering is
        not known a priori.
 
        This is a boolean property so needs no value. To enable it, add a
-       line 'sort-by-pos;' to your description.
+       line 'sort-by-offset;' to your description.
 
 multiple-images:
        Normally only a single image is generated. To create more than one
@@ -383,11 +390,11 @@ multiple-images:
        };
 
 end-at-4gb:
-       For x86 machines the ROM positions start just before 4GB and extend
+       For x86 machines the ROM offsets start just before 4GB and extend
        up so that the image finished at the 4GB boundary. This boolean
        option can be enabled to support this. The image size must be
        provided so that binman knows when the image should start. For an
-       8MB ROM, the position of the first entry would be 0xfff80000 with
+       8MB ROM, the offset of the first entry would be 0xfff80000 with
        this option, instead of 0 without this option.
 
 
@@ -446,6 +453,15 @@ name-prefix:
        distinguish binaries with otherwise identical names.
 
 
+Entry Documentation
+-------------------
+
+For details on the various entry types supported by binman and how to use them,
+see README.entries. This is generated from the source code using:
+
+       binman -E >tools/binman/README.entries
+
+
 Special properties
 ------------------
 
@@ -463,7 +479,7 @@ Order of image creation
 Image creation proceeds in the following order, for each entry in the image.
 
 1. AddMissingProperties() - binman can add calculated values to the device
-tree as part of its processing, for example the position and size of each
+tree as part of its processing, for example the offset and size of each
 entry. This method adds any properties associated with this, expanding the
 device tree as needed. These properties can have placeholder values which are
 set later by SetCalculatedProperties(). By that stage the size of sections
@@ -486,15 +502,15 @@ functions must return True when they have read the contents. Binman will
 retry calling the functions a few times if False is returned, allowing
 dependencies between the contents of different entries.
 
-4. GetEntryPositions() - calls Entry.GetPositions() for each entry. This can
+4. GetEntryOffsets() - calls Entry.GetOffsets() for each entry. This can
 return a dict containing entries that need updating. The key should be the
-entry name and the value is a tuple (pos, size). This allows an entry to
-provide the position and size for other entries. The default implementation
-of GetEntryPositions() returns {}.
+entry name and the value is a tuple (offset, size). This allows an entry to
+provide the offset and size for other entries. The default implementation
+of GetEntryOffsets() returns {}.
 
-5. PackEntries() - calls Entry.Pack() which figures out the position and
-size of an entry. The 'current' image position is passed in, and the function
-returns the position immediately after the entry being packed. The default
+5. PackEntries() - calls Entry.Pack() which figures out the offset and
+size of an entry. The 'current' image offset is passed in, and the function
+returns the offset immediately after the entry being packed. The default
 implementation of Pack() is usually sufficient.
 
 6. CheckSize() - checks that the contents of all the entries fits within
@@ -505,16 +521,16 @@ large enough to hold all the entries.
 outside the image.
 
 8. SetCalculatedProperties() - update any calculated properties in the device
-tree. This sets the correct 'pos' and 'size' vaues, for example.
+tree. This sets the correct 'offset' and 'size' vaues, for example.
 
 9. ProcessEntryContents() - this calls Entry.ProcessContents() on each entry.
 The default implementatoin does nothing. This can be overriden to adjust the
 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.
+stage the offset and size of entries should not be adjusted.
 
 10. WriteSymbols() - write the value of symbols into the U-Boot SPL binary.
-See 'Access to binman entry positions at run time' below for a description of
+See 'Access to binman entry offsets at run time' below for a description of
 what happens in this stage.
 
 11. BuildImage() - builds the image and writes it to a file. This is the final
@@ -549,8 +565,8 @@ 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
---------------------------------------------
+Access to binman entry offsets at run time (symbols)
+----------------------------------------------------
 
 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
@@ -560,15 +576,15 @@ 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);
+    binman_sym_declare(ulong, u_boot_any, offset);
 
-declares a ulong value which will be assigned to the position of any U-Boot
+declares a ulong value which will be assigned to the offset 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);
+    ulong u_boot_offset = binman_sym(ulong, u_boot_any, offset);
 
-Thus u_boot_pos will be set to the position of U-Boot in memory, assuming that
+Thus u_boot_offset will be set to the offset 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.
 
@@ -576,25 +592,58 @@ 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.
 
 
+Access to binman entry offsets at run time (fdt)
+------------------------------------------------
+
+Binman can update the U-Boot FDT to include the final position and size of
+each entry in the images it processes. The option to enable this is -u and it
+causes binman to make sure that the 'offset', 'image-pos' and 'size' properties
+are set correctly for every entry. Since it is not necessary to specify these in
+the image definition, binman calculates the final values and writes these to
+the device tree. These can be used by U-Boot at run-time to find the location
+of each entry.
+
+
 Map files
 ---------
 
 The -m option causes binman to output a .map file for each image that it
-generates. This shows the position and size of each entry. For example:
+generates. This shows the offset and size of each entry. For example:
 
-    Position      Size  Name
-    00000000  00000010  section@0
-     00000000  00000004  u-boot
-    00000010  00000010  section@1
-     00000000  00000004  u-boot
+      Offset      Size  Name
+    00000000  00000028  main-section
+     00000000  00000010  section@0
+      00000000  00000004  u-boot
+     00000010  00000010  section@1
+      00000000  00000004  u-boot
 
 This shows a hierarchical image with two sections, each with a single entry. The
-positions of the sections are absolute hex byte offsets within the image. The
-positions of the entries are relative to their respective sections. The size of
+offsets of the sections are absolute hex byte offsets within the image. The
+offsets of the entries are relative to their respective sections. The size of
 each entry is also shown, in bytes (hex). The indentation shows the entries
 nested inside their sections.
 
 
+Passing command-line arguments to entries
+-----------------------------------------
+
+Sometimes it is useful to pass binman the value of an entry property from the
+command line. For example some entries need access to files and it is not
+always convenient to put these filenames in the image definition (device tree).
+
+The-a option supports this:
+
+    -a<prop>=<value>
+
+where
+
+    <prop> is the property to set
+    <value> is the value to set it to
+
+Not all properties can be provided this way. Only some entries support it,
+typically for filenames.
+
+
 Code coverage
 -------------
 
@@ -623,7 +672,7 @@ Entry properties are documented in entry.py. The entry subclasses are free
 to change the values of properties to support special behaviour. For example,
 when Entry_blob loads a file, it sets content_size to the size of the file.
 Entry classes can adjust other entries. For example, an entry that knows
-where other entries should be positioned can set up those entries' positions
+where other entries should be positioned can set up those entries' offsets
 so they don't need to be set in the binman decription. It can also adjust
 entry contents.
 
diff --git a/tools/binman/README.entries b/tools/binman/README.entries
new file mode 100644 (file)
index 0000000..c6e7b22
--- /dev/null
@@ -0,0 +1,585 @@
+Binman Entry Documentation
+===========================
+
+This file describes the entry types supported by binman. These entry types can
+be placed in an image one by one to build up a final firmware image. It is
+fairly easy to create new entry types. Just add a new file to the 'etype'
+directory. You can use the existing entries as examples.
+
+Note that some entries are subclasses of others, using and extending their
+features to produce new behaviours.
+
+
+
+Entry: blob: Entry containing an arbitrary binary blob
+------------------------------------------------------
+
+Note: This should not be used by itself. It is normally used as a parent
+class by other entry types.
+
+Properties / Entry arguments:
+    - filename: Filename of file to read into entry
+
+This entry reads data from a file and places it in the entry. The
+default filename is often specified specified by the subclass. See for
+example the 'u_boot' entry which provides the filename 'u-boot.bin'.
+
+
+
+Entry: blob-named-by-arg: A blob entry which gets its filename property from its subclass
+-----------------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - <xxx>-path: Filename containing the contents of this entry (optional,
+        defaults to 0)
+
+where <xxx> is the blob_fname argument to the constructor.
+
+This entry cannot be used directly. Instead, it is used as a parent class
+for another entry, which defined blob_fname. This parameter is used to
+set the entry-arg or property containing the filename. The entry-arg or
+property is in turn used to set the actual filename.
+
+See cros_ec_rw for an example of this.
+
+
+
+Entry: cros-ec-rw: A blob entry which contains a Chromium OS read-write EC image
+--------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - cros-ec-rw-path: Filename containing the EC image
+
+This entry holds a Chromium OS EC (embedded controller) image, for use in
+updating the EC on startup via software sync.
+
+
+
+Entry: fill: An entry which is filled to a particular byte value
+----------------------------------------------------------------
+
+Properties / Entry arguments:
+    - fill-byte: Byte to use to fill the entry
+
+Note that the size property must be set since otherwise this entry does not
+know how large it should be.
+
+You can often achieve the same effect using the pad-byte property of the
+overall image, in that the space between entries will then be padded with
+that byte. But this entry is sometimes useful for explicitly setting the
+byte value of a region.
+
+
+
+Entry: fmap: An entry which contains an Fmap section
+----------------------------------------------------
+
+Properties / Entry arguments:
+    None
+
+FMAP is a simple format used by flashrom, an open-source utility for
+reading and writing the SPI flash, typically on x86 CPUs. The format
+provides flashrom with a list of areas, so it knows what it in the flash.
+It can then read or write just a single area, instead of the whole flash.
+
+The format is defined by the flashrom project, in the file lib/fmap.h -
+see www.flashrom.org/Flashrom for more information.
+
+When used, this entry will be populated with an FMAP which reflects the
+entries in the current image. Note that any hierarchy is squashed, since
+FMAP does not support this.
+
+
+
+Entry: gbb: An entry which contains a Chromium OS Google Binary Block
+---------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - hardware-id: Hardware ID to use for this build (a string)
+    - keydir: Directory containing the public keys to use
+    - bmpblk: Filename containing images used by recovery
+
+Chromium OS uses a GBB to store various pieces of information, in particular
+the root and recovery keys that are used to verify the boot process. Some
+more details are here:
+
+    https://www.chromium.org/chromium-os/firmware-porting-guide/2-concepts
+
+but note that the page dates from 2013 so is quite out of date. See
+README.chromium for how to obtain the required keys and tools.
+
+
+
+Entry: intel-cmc: Entry containing an Intel Chipset Micro Code (CMC) file
+-------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of file to read into entry
+
+This file contains microcode for some devices in a special format. An
+example filename is 'Microcode/C0_22211.BIN'.
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-descriptor: Intel flash descriptor block (4KB)
+-----------------------------------------------------------
+
+Properties / Entry arguments:
+    filename: Filename of file containing the descriptor. This is typically
+        a 4KB binary file, sometimes called 'descriptor.bin'
+
+This entry is placed at the start of flash and provides information about
+the SPI flash regions. In particular it provides the base address and
+size of the ME (Management Engine) region, allowing us to place the ME
+binary in the right place.
+
+With this entry in your image, the position of the 'intel-me' entry will be
+fixed in the image, which avoids you needed to specify an offset for that
+region. This is useful, because it is not possible to change the position
+of the ME region without updating the descriptor.
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-fsp: Entry containing an Intel Firmware Support Package (FSP) file
+-------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of file to read into entry
+
+This file contains binary blobs which are used on some devices to make the
+platform work. U-Boot executes this code since it is not possible to set up
+the hardware using U-Boot open-source code. Documentation is typically not
+available in sufficient detail to allow this.
+
+An example filename is 'FSP/QUEENSBAY_FSP_GOLD_001_20-DECEMBER-2013.fd'
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-me: Entry containing an Intel Management Engine (ME) file
+----------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of file to read into entry
+
+This file contains code used by the SoC that is required to make it work.
+The Management Engine is like a background task that runs things that are
+not clearly documented, but may include keyboard, deplay and network
+access. For platform that use ME it is not possible to disable it. U-Boot
+does not directly execute code in the ME binary.
+
+A typical filename is 'me.bin'.
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-mrc: Entry containing an Intel Memory Reference Code (MRC) file
+----------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of file to read into entry
+
+This file contains code for setting up the SDRAM on some Intel systems. This
+is executed by U-Boot when needed early during startup. A typical filename
+is 'mrc.bin'.
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-vbt: Entry containing an Intel Video BIOS Table (VBT) file
+-----------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of file to read into entry
+
+This file contains code that sets up the integrated graphics subsystem on
+some Intel SoCs. U-Boot executes this when the display is started up.
+
+See README.x86 for information about Intel binary blobs.
+
+
+
+Entry: intel-vga: Entry containing an Intel Video Graphics Adaptor (VGA) file
+-----------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of file to read into entry
+
+This file contains code that sets up the integrated graphics subsystem on
+some Intel SoCs. U-Boot executes this when the display is started up.
+
+This is similar to the VBT file but in a different format.
+
+See README.x86 for information about Intel binary blobs.
+
+
+
+Entry: section: Entry that contains other entries
+-------------------------------------------------
+
+Properties / Entry arguments: (see binman README for more information)
+    - size: Size of section in bytes
+    - align-size: Align size to a particular power of two
+    - pad-before: Add padding before the entry
+    - pad-after: Add padding after the entry
+    - pad-byte: Pad byte to use when padding
+    - sort-by-offset: Reorder the entries by offset
+    - end-at-4gb: Used to build an x86 ROM which ends at 4GB (2^32)
+    - name-prefix: Adds a prefix to the name of every entry in the section
+        when writing out the map
+
+A section is an entry which can contain other entries, thus allowing
+hierarchical images to be created. See 'Sections and hierarchical images'
+in the binman README for more information.
+
+
+
+Entry: text: An entry which contains text
+-----------------------------------------
+
+The text can be provided either in the node itself or by a command-line
+argument. There is a level of indirection to allow multiple text strings
+and sharing of text.
+
+Properties / Entry arguments:
+    text-label: The value of this string indicates the property / entry-arg
+        that contains the string to place in the entry
+    <xxx> (actual name is the value of text-label): contains the string to
+        place in the entry.
+
+Example node:
+
+    text {
+        size = <50>;
+        text-label = "message";
+    };
+
+You can then use:
+
+    binman -amessage="this is my message"
+
+and binman will insert that string into the entry.
+
+It is also possible to put the string directly in the node:
+
+    text {
+        size = <8>;
+        text-label = "message";
+        message = "a message directly in the node"
+    };
+
+The text is not itself nul-terminated. This can be achieved, if required,
+by setting the size of the entry to something larger than the text.
+
+
+
+Entry: u-boot: U-Boot flat binary
+---------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot.bin (default 'u-boot.bin')
+
+This is the U-Boot binary, containing relocation information to allow it
+to relocate itself at runtime. The binary typically includes a device tree
+blob at the end of it. Use u_boot_nodtb if you want to package the device
+tree separately.
+
+U-Boot can access binman symbols at runtime. See:
+
+    'Access to binman entry offsets at run time (fdt)'
+
+in the binman README for more information.
+
+
+
+Entry: u-boot-dtb: U-Boot device tree
+-------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
+
+This is the U-Boot device tree, containing configuration information for
+U-Boot. U-Boot needs this to know what devices are present and which drivers
+to activate.
+
+
+
+Entry: u-boot-dtb-with-ucode: A U-Boot device tree file, with the microcode removed
+-----------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
+
+See Entry_u_boot_ucode for full details of the three entries involved in
+this process. This entry provides the U-Boot device-tree file, which
+contains the microcode. If the microcode is not being collated into one
+place then the offset and size of the microcode is recorded by this entry,
+for use by u_boot_with_ucode_ptr. If it is being collated, then this
+entry deletes the microcode from the device tree (to save space) and makes
+it available to u_boot_ucode.
+
+
+
+Entry: u-boot-img: U-Boot legacy image
+--------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot.img (default 'u-boot.img')
+
+This is the U-Boot binary as a packaged image, in legacy format. It has a
+header which allows it to be loaded at the correct address for execution.
+
+You should use FIT (Flat Image Tree) instead of the legacy image for new
+applications.
+
+
+
+Entry: u-boot-nodtb: U-Boot flat binary without device tree appended
+--------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot.bin (default 'u-boot-nodtb.bin')
+
+This is the U-Boot binary, containing relocation information to allow it
+to relocate itself at runtime. It does not include a device tree blob at
+the end of it so normally cannot work without it. You can add a u_boot_dtb
+entry after this one, or use a u_boot entry instead (which contains both
+U-Boot and the device tree).
+
+
+
+Entry: u-boot-spl: U-Boot SPL binary
+------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot-spl.bin (default 'spl/u-boot-spl.bin')
+
+This is the U-Boot SPL (Secondary Program Loader) binary. This is a small
+binary which loads before U-Boot proper, typically into on-chip SRAM. It is
+responsible for locating, loading and jumping to U-Boot. Note that SPL is
+not relocatable so must be loaded to the correct address in SRAM, or written
+to run from the correct address if direct flash execution is possible (e.g.
+on x86 devices).
+
+SPL can access binman symbols at runtime. See:
+
+    'Access to binman entry offsets at run time (symbols)'
+
+in the binman README for more information.
+
+The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+binman uses that to look up symbols to write into the SPL binary.
+
+
+
+Entry: u-boot-spl-bss-pad: U-Boot SPL binary padded with a BSS region
+---------------------------------------------------------------------
+
+Properties / Entry arguments:
+    None
+
+This is similar to u_boot_spl except that padding is added after the SPL
+binary to cover the BSS (Block Started by Symbol) region. This region holds
+the various used by SPL. It is set to 0 by SPL when it starts up. If you
+want to append data to the SPL image (such as a device tree file), you must
+pad out the BSS region to avoid the data overlapping with U-Boot variables.
+This entry is useful in that case. It automatically pads out the entry size
+to cover both the code, data and BSS.
+
+The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+binman uses that to look up the BSS address.
+
+
+
+Entry: u-boot-spl-dtb: U-Boot SPL device tree
+---------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot.dtb (default 'spl/u-boot-spl.dtb')
+
+This is the SPL device tree, containing configuration information for
+SPL. SPL needs this to know what devices are present and which drivers
+to activate.
+
+
+
+Entry: u-boot-spl-nodtb: SPL binary without device tree appended
+----------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of spl/u-boot-spl-nodtb.bin (default
+        'spl/u-boot-spl-nodtb.bin')
+
+This is the U-Boot SPL binary, It does not include a device tree blob at
+the end of it so may not be able to work without it, assuming SPL needs
+a device tree to operation on your platform. You can add a u_boot_spl_dtb
+entry after this one, or use a u_boot_spl entry instead (which contains
+both SPL and the device tree).
+
+
+
+Entry: u-boot-spl-with-ucode-ptr: U-Boot SPL with embedded microcode pointer
+----------------------------------------------------------------------------
+
+See Entry_u_boot_ucode for full details of the entries involved in this
+process.
+
+
+
+Entry: u-boot-tpl: U-Boot TPL binary
+------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot-tpl.bin (default 'tpl/u-boot-tpl.bin')
+
+This is the U-Boot TPL (Tertiary Program Loader) binary. This is a small
+binary which loads before SPL, typically into on-chip SRAM. It is
+responsible for locating, loading and jumping to SPL, the next-stage
+loader. Note that SPL is not relocatable so must be loaded to the correct
+address in SRAM, or written to run from the correct address if direct
+flash execution is possible (e.g. on x86 devices).
+
+SPL can access binman symbols at runtime. See:
+
+    'Access to binman entry offsets at run time (symbols)'
+
+in the binman README for more information.
+
+The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+binman uses that to look up symbols to write into the TPL binary.
+
+
+
+Entry: u-boot-tpl-dtb: U-Boot TPL device tree
+---------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot.dtb (default 'tpl/u-boot-tpl.dtb')
+
+This is the TPL device tree, containing configuration information for
+TPL. TPL needs this to know what devices are present and which drivers
+to activate.
+
+
+
+Entry: u-boot-ucode: U-Boot microcode block
+-------------------------------------------
+
+Properties / Entry arguments:
+    None
+
+The contents of this entry are filled in automatically by other entries
+which must also be in the image.
+
+U-Boot on x86 needs a single block of microcode. This is collected from
+the various microcode update nodes in the device tree. It is also unable
+to read the microcode from the device tree on platforms that use FSP
+(Firmware Support Package) binaries, because the API requires that the
+microcode is supplied before there is any SRAM available to use (i.e.
+the FSP sets up the SRAM / cache-as-RAM but does so in the call that
+requires the microcode!). To keep things simple, all x86 platforms handle
+microcode the same way in U-Boot (even non-FSP platforms). This is that
+a table is placed at _dt_ucode_base_size containing the base address and
+size of the microcode. This is either passed to the FSP (for FSP
+platforms), or used to set up the microcode (for non-FSP platforms).
+This all happens in the build system since it is the only way to get
+the microcode into a single blob and accessible without SRAM.
+
+There are two cases to handle. If there is only one microcode blob in
+the device tree, then the ucode pointer it set to point to that. This
+entry (u-boot-ucode) is empty. If there is more than one update, then
+this entry holds the concatenation of all updates, and the device tree
+entry (u-boot-dtb-with-ucode) is updated to remove the microcode. This
+last step ensures that that the microcode appears in one contiguous
+block in the image and is not unnecessarily duplicated in the device
+tree. It is referred to as 'collation' here.
+
+Entry types that have a part to play in handling microcode:
+
+    Entry_u_boot_with_ucode_ptr:
+        Contains u-boot-nodtb.bin (i.e. U-Boot without the device tree).
+        It updates it with the address and size of the microcode so that
+        U-Boot can find it early on start-up.
+    Entry_u_boot_dtb_with_ucode:
+        Contains u-boot.dtb. It stores the microcode in a
+        'self.ucode_data' property, which is then read by this class to
+        obtain the microcode if needed. If collation is performed, it
+        removes the microcode from the device tree.
+    Entry_u_boot_ucode:
+        This class. If collation is enabled it reads the microcode from
+        the Entry_u_boot_dtb_with_ucode entry, and uses it as the
+        contents of this entry.
+
+
+
+Entry: u-boot-with-ucode-ptr: U-Boot with embedded microcode pointer
+--------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot-nodtb.dtb (default 'u-boot-nodtb.dtb')
+
+See Entry_u_boot_ucode for full details of the three entries involved in
+this process. This entry updates U-Boot with the offset and size of the
+microcode, to allow early x86 boot code to find it without doing anything
+complicated. Otherwise it is the same as the u_boot entry.
+
+
+
+Entry: vblock: An entry which contains a Chromium OS verified boot block
+------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - keydir: Directory containing the public keys to use
+    - keyblock: Name of the key file to use (inside keydir)
+    - signprivate: Name of provide key file to use (inside keydir)
+    - version: Version number of the vblock (typically 1)
+    - kernelkey: Name of the kernel key to use (inside keydir)
+    - preamble-flags: Value of the vboot preamble flags (typically 0)
+
+Chromium OS  signs the read-write firmware and kernel, writing the signature
+in this block. This allows U-Boot to verify that the next firmware stage
+and kernel are genuine.
+
+
+
+Entry: x86-start16: x86 16-bit start-up code for U-Boot
+-------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot-x86-16bit.bin (default
+        'u-boot-x86-16bit.bin')
+
+x86 CPUs start up in 16-bit mode, even if they are 32-bit CPUs. This code
+must be placed at a particular address. This entry holds that code. It is
+typically placed at offset CONFIG_SYS_X86_START16. The code is responsible
+for changing to 32-bit mode and jumping to U-Boot's entry point, which
+requires 32-bit mode (for 32-bit U-Boot).
+
+For 64-bit U-Boot, the 'x86_start16_spl' entry type is used instead.
+
+
+
+Entry: x86-start16-spl: x86 16-bit start-up code for SPL
+--------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of spl/u-boot-x86-16bit-spl.bin (default
+        'spl/u-boot-x86-16bit-spl.bin')
+
+x86 CPUs start up in 16-bit mode, even if they are 64-bit CPUs. This code
+must be placed at a particular address. This entry holds that code. It is
+typically placed at offset CONFIG_SYS_X86_START16. The code is responsible
+for changing to 32-bit mode and starting SPL, which in turn changes to
+64-bit mode and jumps to U-Boot (for 64-bit U-Boot).
+
+For 32-bit U-Boot, the 'x86_start16' entry type is used instead.
+
+
+
index 52e02ed91b4f7de47b995adbbcc055ffb49b67b5..1536e95651755c506bbea85380c4e2efb30648ac 100755 (executable)
@@ -77,9 +77,20 @@ def RunTests(debug, args):
       return 1
     return 0
 
+def GetEntryModules(include_testing=True):
+    """Get a set of entry class implementations
+
+    Returns:
+        Set of paths to entry class filenames
+    """
+    glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
+    return set([os.path.splitext(os.path.basename(item))[0]
+                for item in glob_list
+                if include_testing or '_testing' not in item])
+
 def RunTestCoverage():
     """Run the tests and check that we get 100% coverage"""
-    glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
+    glob_list = GetEntryModules(False)
     all_set = set([os.path.splitext(os.path.basename(item))[0]
                    for item in glob_list if '_testing' not in item])
     test_util.RunTestCoverage('tools/binman/binman.py', None,
@@ -107,13 +118,8 @@ def RunBinman(options, args):
     elif options.test_coverage:
         RunTestCoverage()
 
-    elif options.full_help:
-        pager = os.getenv('PAGER')
-        if not pager:
-            pager = 'more'
-        fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
-                            'README')
-        command.Run(pager, fname)
+    elif options.entry_docs:
+        control.WriteEntryDocs(GetEntryModules())
 
     else:
         try:
index de439ef625fcb894f547e034be8510545aa60d40..a0bd1b6d34e2a6e2da2ea734061ef2d4976847f4 100644 (file)
@@ -25,22 +25,21 @@ class Section(object):
         _size: Section size in bytes, or None if not known yet
         _align_size: Section size alignment, or None
         _pad_before: Number of bytes before the first entry starts. This
-            effectively changes the place where entry position 0 starts
+            effectively changes the place where entry offset 0 starts
         _pad_after: Number of bytes after the last entry ends. The last
             entry will finish on or before this boundary
         _pad_byte: Byte to use to pad the section where there is no entry
-        _sort: True if entries should be sorted by position, False if they
+        _sort: True if entries should be sorted by offset, False if they
             must be in-order in the device tree description
         _skip_at_start: Number of bytes before the first entry starts. These
-            effectively adjust the starting position of entries. For example,
+            effectively adjust the starting offset of entries. For example,
             if _pad_before is 16, then the first entry would start at 16.
-            An entry with pos = 20 would in fact be written at position 4
+            An entry with offset = 20 would in fact be written at offset 4
             in the image file.
         _end_4gb: Indicates that the section ends at the 4GB boundary. This is
-            used for x86 images, which want to use positions such that a
-             memory address (like 0xff800000) is the first entry position.
-             This causes _skip_at_start to be set to the starting memory
-             address.
+            used for x86 images, which want to use offsets such that a memory
+            address (like 0xff800000) is the first entry offset. This causes
+            _skip_at_start to be set to the starting memory address.
         _name_prefix: Prefix to add to the name of all entries within this
             section
         _entries: OrderedDict() of entries
@@ -51,7 +50,9 @@ class Section(object):
         import entry
         from entry import Entry
 
+        self._name = name
         self._node = node
+        self._offset = 0
         self._size = None
         self._align_size = None
         self._pad_before = 0
@@ -76,7 +77,7 @@ class Section(object):
         self._pad_before = fdt_util.GetInt(self._node, 'pad-before', 0)
         self._pad_after = fdt_util.GetInt(self._node, 'pad-after', 0)
         self._pad_byte = fdt_util.GetInt(self._node, 'pad-byte', 0)
-        self._sort = fdt_util.GetBool(self._node, 'sort-by-pos')
+        self._sort = fdt_util.GetBool(self._node, 'sort-by-offset')
         self._end_4gb = fdt_util.GetBool(self._node, 'end-at-4gb')
         if self._end_4gb and not self._size:
             self._Raise("Section size must be provided when using end-at-4gb")
@@ -90,11 +91,21 @@ class Section(object):
             entry.SetPrefix(self._name_prefix)
             self._entries[node.name] = entry
 
+    def SetOffset(self, offset):
+        self._offset = offset
+
     def AddMissingProperties(self):
+        """Add new properties to the device tree as needed for this entry"""
+        for prop in ['offset', 'size', 'image-pos']:
+            if not prop in self._node.props:
+                self._node.AddZeroProp(prop)
         for entry in self._entries.values():
             entry.AddMissingProperties()
 
     def SetCalculatedProperties(self):
+        self._node.SetInt('offset', self._offset)
+        self._node.SetInt('size', self._size)
+        self._node.SetInt('image-pos', self._image_pos)
         for entry in self._entries.values():
             entry.SetCalculatedProperties()
 
@@ -117,7 +128,7 @@ class Section(object):
         """Check that the section contents does not exceed its size, etc."""
         contents_size = 0
         for entry in self._entries.values():
-            contents_size = max(contents_size, entry.pos + entry.size)
+            contents_size = max(contents_size, entry.offset + entry.size)
 
         contents_size -= self._skip_at_start
 
@@ -190,39 +201,41 @@ class Section(object):
                         'contents: remaining %s' % todo)
         return True
 
-    def _SetEntryPosSize(self, name, pos, size):
-        """Set the position and size of an entry
+    def _SetEntryOffsetSize(self, name, offset, size):
+        """Set the offset and size of an entry
 
         Args:
             name: Entry name to update
-            pos: New position
+            offset: New offset
             size: New size
         """
         entry = self._entries.get(name)
         if not entry:
-            self._Raise("Unable to set pos/size for unknown entry '%s'" % name)
-        entry.SetPositionSize(self._skip_at_start + pos, size)
+            self._Raise("Unable to set offset/size for unknown entry '%s'" %
+                        name)
+        entry.SetOffsetSize(self._skip_at_start + offset, size)
 
-    def GetEntryPositions(self):
-        """Handle entries that want to set the position/size of other entries
+    def GetEntryOffsets(self):
+        """Handle entries that want to set the offset/size of other entries
 
-        This calls each entry's GetPositions() method. If it returns a list
+        This calls each entry's GetOffsets() method. If it returns a list
         of entries to update, it updates them.
         """
         for entry in self._entries.values():
-            pos_dict = entry.GetPositions()
-            for name, info in pos_dict.iteritems():
-                self._SetEntryPosSize(name, *info)
+            offset_dict = entry.GetOffsets()
+            for name, info in offset_dict.iteritems():
+                self._SetEntryOffsetSize(name, *info)
 
     def PackEntries(self):
         """Pack all entries into the section"""
-        pos = self._skip_at_start
+        offset = self._skip_at_start
         for entry in self._entries.values():
-            pos = entry.Pack(pos)
+            offset = entry.Pack(offset)
+        self._size = self.CheckSize()
 
     def _SortEntries(self):
-        """Sort entries by position"""
-        entries = sorted(self._entries.values(), key=lambda entry: entry.pos)
+        """Sort entries by offset"""
+        entries = sorted(self._entries.values(), key=lambda entry: entry.offset)
         self._entries.clear()
         for entry in entries:
             self._entries[entry._node.name] = entry
@@ -231,23 +244,28 @@ class Section(object):
         """Check that entries do not overlap or extend outside the section"""
         if self._sort:
             self._SortEntries()
-        pos = 0
+        offset = 0
         prev_name = 'None'
         for entry in self._entries.values():
-            entry.CheckPosition()
-            if (entry.pos < self._skip_at_start or
-                entry.pos >= self._skip_at_start + self._size):
-                entry.Raise("Position %#x (%d) is outside the section starting "
+            entry.CheckOffset()
+            if (entry.offset < self._skip_at_start or
+                entry.offset >= self._skip_at_start + self._size):
+                entry.Raise("Offset %#x (%d) is outside the section starting "
                             "at %#x (%d)" %
-                            (entry.pos, entry.pos, self._skip_at_start,
+                            (entry.offset, entry.offset, self._skip_at_start,
                              self._skip_at_start))
-            if entry.pos < pos:
-                entry.Raise("Position %#x (%d) overlaps with previous entry '%s' "
+            if entry.offset < offset:
+                entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' "
                             "ending at %#x (%d)" %
-                            (entry.pos, entry.pos, prev_name, pos, pos))
-            pos = entry.pos + entry.size
+                            (entry.offset, entry.offset, prev_name, offset, offset))
+            offset = entry.offset + entry.size
             prev_name = entry.GetPath()
 
+    def SetImagePos(self, image_pos):
+        self._image_pos = image_pos
+        for entry in self._entries.values():
+            entry.SetImagePos(image_pos)
+
     def ProcessEntryContents(self):
         """Call the ProcessContents() method for each entry
 
@@ -261,18 +279,18 @@ class Section(object):
         for entry in self._entries.values():
             entry.WriteSymbols(self)
 
-    def BuildSection(self, fd, base_pos):
+    def BuildSection(self, fd, base_offset):
         """Write the section to a file"""
-        fd.seek(base_pos)
+        fd.seek(base_offset)
         fd.write(self.GetData())
 
     def GetData(self):
-        """Write the section to a file"""
+        """Get the contents of the section"""
         section_data = chr(self._pad_byte) * self._size
 
         for entry in self._entries.values():
             data = entry.GetData()
-            base = self._pad_before + entry.pos - self._skip_at_start
+            base = self._pad_before + entry.offset - self._skip_at_start
             section_data = (section_data[:base] + data +
                             section_data[base + len(data):])
         return section_data
@@ -283,15 +301,15 @@ class Section(object):
         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.
+        At present the only entry property supported is offset.
 
         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
+                _binman_u_boot_prop_offset). 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,
+                _binman_u_boot_any_prop_offset 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
@@ -327,19 +345,64 @@ class Section(object):
                 print('Warning: %s' % err, file=sys.stderr)
                 return None
             raise ValueError(err)
-        if prop_name == 'pos':
-            return entry.pos
+        if prop_name == 'offset':
+            return entry.offset
+        elif prop_name == 'image_pos':
+            return entry.image_pos
         else:
             raise ValueError("%s: No such property '%s'" % (msg, prop_name))
 
     def GetEntries(self):
+        """Get the number of entries in a section
+
+        Returns:
+            Number of entries in a section
+        """
         return self._entries
 
+    def GetSize(self):
+        """Get the size of a section in bytes
+
+        This is only meaningful if the section has a pre-defined size, or the
+        entries within it have been packed, so that the size has been
+        calculated.
+
+        Returns:
+            Entry size in bytes
+        """
+        return self._size
+
     def WriteMap(self, fd, indent):
         """Write a map of the section to a .map file
 
         Args:
             fd: File to write the map to
         """
+        Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size,
+                           self._image_pos)
+        for entry in self._entries.values():
+            entry.WriteMap(fd, indent + 1)
+
+    def GetContentsByPhandle(self, phandle, source_entry):
+        """Get the data contents of an entry specified by a phandle
+
+        This uses a phandle to look up a node and and find the entry
+        associated with it. Then it returnst he contents of that entry.
+
+        Args:
+            phandle: Phandle to look up (integer)
+            source_entry: Entry containing that phandle (used for error
+                reporting)
+
+        Returns:
+            data from associated entry (as a string), or None if not found
+        """
+        node = self._node.GetFdt().LookupPhandle(phandle)
+        if not node:
+            source_entry.Raise("Cannot find node for phandle %d" % phandle)
         for entry in self._entries.values():
-            entry.WriteMap(fd, indent)
+            if entry._node == node:
+                if entry.data is None:
+                    return None
+                return entry.data
+        source_entry.Raise("Cannot find entry for node '%s'" % node.name)
index ae2d1670f9a61508e914fb26d4edb9b2fdd5d8c5..f0de4ded4433e944f3cd3dbf563d38596fb72257 100644 (file)
@@ -18,6 +18,8 @@ def ParseArgs(argv):
             args is a list of string arguments
     """
     parser = OptionParser()
+    parser.add_option('-a', '--entry-arg', type='string', action='append',
+            help='Set argument value arg=value')
     parser.add_option('-b', '--board', type='string',
             help='Board name to build')
     parser.add_option('-B', '--build-dir', type='string', default='b',
@@ -26,6 +28,8 @@ def ParseArgs(argv):
             help='Configuration file (.dtb) to use')
     parser.add_option('-D', '--debug', action='store_true',
             help='Enabling debugging (provides a full traceback on error)')
+    parser.add_option('-E', '--entry-docs', action='store_true',
+            help='Write out entry documentation (see README.entries)')
     parser.add_option('-I', '--indir', action='append',
             help='Add a path to a directory to use for input files')
     parser.add_option('-H', '--full-help', action='store_true',
@@ -43,7 +47,7 @@ def ParseArgs(argv):
     parser.add_option('-T', '--test-coverage', action='store_true',
                     default=False, help='run tests and check for 100% coverage')
     parser.add_option('-u', '--update-fdt', action='store_true',
-        default=False, help='Update the binman node with position/size info')
+        default=False, help='Update the binman node with offset/size info')
     parser.add_option('-v', '--verbosity', default=1,
         type='int', help='Control verbosity: 0=silent, 1=progress, 3=full, '
         '4=debug')
index a40b300fdacba2f105942aa1c7ff93b3d3012ee4..2de1c86ecfeb90c8383464481721cbbe7f8a2a6b 100644 (file)
@@ -7,13 +7,12 @@
 
 from collections import OrderedDict
 import os
+import re
 import sys
 import tools
 
 import command
 import elf
-import fdt
-import fdt_util
 from image import Image
 import tout
 
@@ -25,6 +24,9 @@ images = OrderedDict()
 # 'u-boot-spl.dtb')
 fdt_files = {}
 
+# Arguments passed to binman to provide arguments to entries
+entry_args = {}
+
 
 def _ReadImageDesc(binman_node):
     """Read the image descriptions from the /binman node
@@ -76,6 +78,24 @@ def GetFdt(fname):
 def GetFdtPath(fname):
     return fdt_files[fname]._fname
 
+def SetEntryArgs(args):
+    global entry_args
+
+    entry_args = {}
+    if args:
+        for arg in args:
+            m = re.match('([^=]*)=(.*)', arg)
+            if not m:
+                raise ValueError("Invalid entry arguemnt '%s'" % arg)
+            entry_args[m.group(1)] = m.group(2)
+
+def GetEntryArg(name):
+    return entry_args.get(name)
+
+def WriteEntryDocs(modules, test_missing=None):
+    from entry import Entry
+    Entry.WriteDocs(modules, test_missing)
+
 def Binman(options, args):
     """The main control code for binman
 
@@ -111,11 +131,17 @@ def Binman(options, args):
         options.indir.append(board_pathname)
 
     try:
+        # Import these here in case libfdt.py is not available, in which case
+        # the above help option still works.
+        import fdt
+        import fdt_util
+
         tout.Init(options.verbosity)
         elf.debug = options.debug
         try:
             tools.SetInputDirs(options.indir)
             tools.PrepareOutputDir(options.outdir, options.preserve)
+            SetEntryArgs(options.entry_arg)
 
             # Get the device tree ready by compiling it and copying the compiled
             # output into a file in our output directly. Then scan it for use
@@ -142,7 +168,7 @@ def Binman(options, args):
             # size of the device tree is correct. Later, in
             # SetCalculatedProperties() we will insert the correct values
             # without changing the device-tree size, thus ensuring that our
-            # entry positions remain the same.
+            # entry offsets remain the same.
             for image in images.values():
                 if options.update_fdt:
                     image.AddMissingProperties()
@@ -157,10 +183,11 @@ def Binman(options, args):
                 # image will be reported after earlier images are already
                 # completed and written, but that does not seem important.
                 image.GetEntryContents()
-                image.GetEntryPositions()
+                image.GetEntryOffsets()
                 image.PackEntries()
                 image.CheckSize()
                 image.CheckEntries()
+                image.SetImagePos()
                 if options.update_fdt:
                     image.SetCalculatedProperties()
                 image.ProcessEntryContents()
index 0ae3b611bae6bee6fa5bf160ddbf16335d5cbdb3..97df8e32c5d8d60271051874c4b81a53b16914c7 100644 (file)
@@ -57,7 +57,9 @@ def GetSymbols(fname, patterns):
             name = parts[2]
             syms[name] = Symbol(section, int(value, 16), int(size,16),
                                 flags[1] == 'w')
-    return syms
+
+    # Sort dict by address
+    return OrderedDict(sorted(syms.iteritems(), key=lambda x: x[1].address))
 
 def GetSymbolAddress(fname, sym_name):
     """Get a value of a symbol from an ELF file
@@ -79,9 +81,9 @@ def LookupAndWriteSymbols(elf_fname, entry, section):
     """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.
+    visible at run time. This is done by finding out the symbols offsets 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
index 9c8f1feca8596d4f901fd762c09f544acbf0aeda..c16f71401d1c92be88e0d53979e5b2ba16b1fffc 100644 (file)
@@ -15,6 +15,10 @@ binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
 
 
 class FakeEntry:
+    """A fake Entry object, usedfor testing
+
+    This supports an entry with a given size.
+    """
     def __init__(self, contents_size):
         self.contents_size = contents_size
         self.data = 'a' * contents_size
@@ -22,7 +26,14 @@ class FakeEntry:
     def GetPath(self):
         return 'entry_path'
 
+
 class FakeSection:
+    """A fake Section object, used for testing
+
+    This has the minimum feature set needed to support testing elf functions.
+    A LookupSymbol() function is provided which returns a fake value for amu
+    symbol requested.
+    """
     def __init__(self, sym_value=1):
         self.sym_value = sym_value
 
@@ -30,15 +41,19 @@ class FakeSection:
         return 'section_path'
 
     def LookupSymbol(self, name, weak, msg):
+        """Fake implementation which returns the same value for all symbols"""
         return self.sym_value
 
+
 class TestElf(unittest.TestCase):
     def testAllSymbols(self):
+        """Test that we can obtain a symbol from the ELF file"""
         fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
         syms = elf.GetSymbols(fname, [])
         self.assertIn('.ucode', syms)
 
     def testRegexSymbols(self):
+        """Test that we can obtain from the ELF file by regular expression"""
         fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
         syms = elf.GetSymbols(fname, ['ucode'])
         self.assertIn('.ucode', syms)
@@ -48,6 +63,7 @@ class TestElf(unittest.TestCase):
         self.assertIn('.ucode', syms)
 
     def testMissingFile(self):
+        """Test that a missing file is detected"""
         entry = FakeEntry(10)
         section = FakeSection()
         with self.assertRaises(ValueError) as e:
@@ -56,6 +72,7 @@ class TestElf(unittest.TestCase):
                       str(e.exception))
 
     def testOutsideFile(self):
+        """Test a symbol which extends outside the entry area is detected"""
         entry = FakeEntry(10)
         section = FakeSection()
         elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
@@ -65,6 +82,11 @@ class TestElf(unittest.TestCase):
                       'is a', str(e.exception))
 
     def testMissingImageStart(self):
+        """Test that we detect a missing __image_copy_start symbol
+
+        This is needed to mark the start of the image. Without it we cannot
+        locate the offset of a binman symbol within the image.
+        """
         entry = FakeEntry(10)
         section = FakeSection()
         elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_bad')
@@ -72,6 +94,11 @@ class TestElf(unittest.TestCase):
                          None)
 
     def testBadSymbolSize(self):
+        """Test that an attempt to use an 8-bit symbol are detected
+
+        Only 32 and 64 bits are supported, since we need to store an offset
+        into the image.
+        """
         entry = FakeEntry(10)
         section = FakeSection()
         elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_size')
@@ -81,6 +108,11 @@ class TestElf(unittest.TestCase):
                       str(e.exception))
 
     def testNoValue(self):
+        """Test the case where we have no value for the symbol
+
+        This should produce -1 values for all thress symbols, taking up the
+        first 16 bytes of the image.
+        """
         entry = FakeEntry(20)
         section = FakeSection(sym_value=None)
         elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
@@ -88,6 +120,7 @@ class TestElf(unittest.TestCase):
         self.assertEqual(chr(255) * 16 + 'a' * 4, entry.data)
 
     def testDebug(self):
+        """Check that enabling debug in the elf module produced debug output"""
         elf.debug = True
         entry = FakeEntry(20)
         section = FakeSection()
index 6a173e663d0fcfc1505e570c8b37dc59ddf71c0f..77cfab9c5de0419d09c26aec272c2cb2252012a2 100644 (file)
@@ -6,6 +6,8 @@
 
 from __future__ import print_function
 
+from collections import namedtuple
+
 # importlib was introduced in Python 2.7 but there was a report of it not
 # working in 2.7.12, so we work around this:
 # http://lists.denx.de/pipermail/u-boot/2016-October/269729.html
@@ -16,6 +18,7 @@ except:
     have_importlib = False
 
 import fdt_util
+import control
 import os
 import sys
 import tools
@@ -24,6 +27,12 @@ modules = {}
 
 our_path = os.path.dirname(os.path.realpath(__file__))
 
+
+# An argument which can be passed to entries on the command line, in lieu of
+# device-tree properties.
+EntryArg = namedtuple('EntryArg', ['name', 'datatype'])
+
+
 class Entry(object):
     """An Entry in the section
 
@@ -36,14 +45,15 @@ class Entry(object):
     Entry.
 
     Attributes:
-        section: The section containing this entry
+        section: Section object containing this entry
         node: The node that created this entry
-        pos: Absolute position of entry within the section, None if not known
+        offset: Offset of entry within the section, None if not known yet (in
+            which case it will be calculated by Pack())
         size: Entry size in bytes, None if not known
         contents_size: Size of contents in bytes, 0 by default
-        align: Entry start position alignment, or None
+        align: Entry start offset alignment, or None
         align_size: Entry size alignment, or None
-        align_end: Entry end position alignment, or None
+        align_end: Entry end offset alignment, or None
         pad_before: Number of pad bytes before the contents, 0 if none
         pad_after: Number of pad bytes after the contents, 0 if none
         data: Contents of entry (string of bytes)
@@ -53,34 +63,33 @@ class Entry(object):
         self.etype = etype
         self._node = node
         self.name = node and (name_prefix + node.name) or 'none'
-        self.pos = None
+        self.offset = None
         self.size = None
-        self.data = ''
+        self.data = None
         self.contents_size = 0
         self.align = None
         self.align_size = None
         self.align_end = None
         self.pad_before = 0
         self.pad_after = 0
-        self.pos_unset = False
+        self.offset_unset = False
+        self.image_pos = None
         if read_node:
             self.ReadNode()
 
     @staticmethod
-    def Create(section, node, etype=None):
-        """Create a new entry for a node.
+    def Lookup(section, node_path, etype):
+        """Look up the entry class for a node.
 
         Args:
-            section:  Image object containing this node
-            node:   Node object containing information about the entry to create
-            etype:  Entry type to use, or None to work it out (used for tests)
+            section:   Section object containing this node
+            node_node: Path name of Node object containing information about
+                       the entry to create (used for errors)
+            etype:   Entry type to use
 
         Returns:
-            A new Entry object of the correct type (a subclass of Entry)
+            The entry class object if found, else None
         """
-        if not etype:
-            etype = fdt_util.GetString(node, 'type', node.name)
-
         # Convert something like 'u-boot@0' to 'u_boot' since we are only
         # interested in the type.
         module_name = etype.replace('-', '_')
@@ -99,15 +108,34 @@ class Entry(object):
                     module = importlib.import_module(module_name)
                 else:
                     module = __import__(module_name)
-            except ImportError:
-                raise ValueError("Unknown entry type '%s' in node '%s'" %
-                        (etype, node.path))
+            except ImportError as e:
+                raise ValueError("Unknown entry type '%s' in node '%s' (expected etype/%s.py, error '%s'" %
+                                 (etype, node_path, module_name, e))
             finally:
                 sys.path = old_path
             modules[module_name] = module
 
+        # Look up the expected class name
+        return getattr(module, 'Entry_%s' % module_name)
+
+    @staticmethod
+    def Create(section, node, etype=None):
+        """Create a new entry for a node.
+
+        Args:
+            section: Section object containing this node
+            node:    Node object containing information about the entry to
+                     create
+            etype:   Entry type to use, or None to work it out (used for tests)
+
+        Returns:
+            A new Entry object of the correct type (a subclass of Entry)
+        """
+        if not etype:
+            etype = fdt_util.GetString(node, 'type', node.name)
+        obj = Entry.Lookup(section, node.path, etype)
+
         # Call its constructor to get the object we want.
-        obj = getattr(module, 'Entry_%s' % module_name)
         return obj(section, etype, node)
 
     def ReadNode(self):
@@ -115,7 +143,9 @@ class Entry(object):
 
         This reads all the fields we recognise from the node, ready for use.
         """
-        self.pos = fdt_util.GetInt(self._node, 'pos')
+        if 'pos' in self._node.props:
+            self.Raise("Please use 'offset' instead of 'pos'")
+        self.offset = fdt_util.GetInt(self._node, 'offset')
         self.size = fdt_util.GetInt(self._node, 'size')
         self.align = fdt_util.GetInt(self._node, 'align')
         if tools.NotPowerOfTwo(self.align):
@@ -128,18 +158,19 @@ class Entry(object):
             raise ValueError("Node '%s': Alignment size %s must be a power "
                              "of two" % (self._node.path, self.align_size))
         self.align_end = fdt_util.GetInt(self._node, 'align-end')
-        self.pos_unset = fdt_util.GetBool(self._node, 'pos-unset')
+        self.offset_unset = fdt_util.GetBool(self._node, 'offset-unset')
 
     def AddMissingProperties(self):
         """Add new properties to the device tree as needed for this entry"""
-        for prop in ['pos', 'size']:
+        for prop in ['offset', 'size', 'image-pos']:
             if not prop in self._node.props:
                 self._node.AddZeroProp(prop)
 
     def SetCalculatedProperties(self):
         """Set the value of device-tree properties calculated by binman"""
-        self._node.SetInt('pos', self.pos)
+        self._node.SetInt('offset', self.offset)
         self._node.SetInt('size', self.size)
+        self._node.SetInt('image-pos', self.image_pos)
 
     def ProcessFdt(self, fdt):
         return True
@@ -190,39 +221,39 @@ class Entry(object):
         # No contents by default: subclasses can implement this
         return True
 
-    def Pack(self, pos):
+    def Pack(self, offset):
         """Figure out how to pack the entry into the section
 
         Most of the time the entries are not fully specified. There may be
         an alignment but no size. In that case we take the size from the
         contents of the entry.
 
-        If an entry has no hard-coded position, it will be placed at @pos.
+        If an entry has no hard-coded offset, it will be placed at @offset.
 
-        Once this function is complete, both the position and size of the
+        Once this function is complete, both the offset and size of the
         entry will be know.
 
         Args:
-            Current section position pointer
+            Current section offset pointer
 
         Returns:
-            New section position pointer (after this entry)
+            New section offset pointer (after this entry)
         """
-        if self.pos is None:
-            if self.pos_unset:
-                self.Raise('No position set with pos-unset: should another '
-                           'entry provide this correct position?')
-            self.pos = tools.Align(pos, self.align)
+        if self.offset is None:
+            if self.offset_unset:
+                self.Raise('No offset set with offset-unset: should another '
+                           'entry provide this correct offset?')
+            self.offset = tools.Align(offset, self.align)
         needed = self.pad_before + self.contents_size + self.pad_after
         needed = tools.Align(needed, self.align_size)
         size = self.size
         if not size:
             size = needed
-        new_pos = self.pos + size
-        aligned_pos = tools.Align(new_pos, self.align_end)
-        if aligned_pos != new_pos:
-            size = aligned_pos - self.pos
-            new_pos = aligned_pos
+        new_offset = self.offset + size
+        aligned_offset = tools.Align(new_offset, self.align_end)
+        if aligned_offset != new_offset:
+            size = aligned_offset - self.offset
+            new_offset = aligned_offset
 
         if not self.size:
             self.size = size
@@ -231,21 +262,48 @@ class Entry(object):
             self.Raise("Entry contents size is %#x (%d) but entry size is "
                        "%#x (%d)" % (needed, needed, self.size, self.size))
         # Check that the alignment is correct. It could be wrong if the
-        # and pos or size values were provided (i.e. not calculated), but
+        # and offset or size values were provided (i.e. not calculated), but
         # conflict with the provided alignment values
         if self.size != tools.Align(self.size, self.align_size):
             self.Raise("Size %#x (%d) does not match align-size %#x (%d)" %
                   (self.size, self.size, self.align_size, self.align_size))
-        if self.pos != tools.Align(self.pos, self.align):
-            self.Raise("Position %#x (%d) does not match align %#x (%d)" %
-                  (self.pos, self.pos, self.align, self.align))
+        if self.offset != tools.Align(self.offset, self.align):
+            self.Raise("Offset %#x (%d) does not match align %#x (%d)" %
+                  (self.offset, self.offset, self.align, self.align))
 
-        return new_pos
+        return new_offset
 
     def Raise(self, msg):
         """Convenience function to raise an error referencing a node"""
         raise ValueError("Node '%s': %s" % (self._node.path, msg))
 
+    def GetEntryArgsOrProps(self, props, required=False):
+        """Return the values of a set of properties
+
+        Args:
+            props: List of EntryArg objects
+
+        Raises:
+            ValueError if a property is not found
+        """
+        values = []
+        missing = []
+        for prop in props:
+            python_prop = prop.name.replace('-', '_')
+            if hasattr(self, python_prop):
+                value = getattr(self, python_prop)
+            else:
+                value = None
+            if value is None:
+                value = self.GetArg(prop.name, prop.datatype)
+            if value is None and required:
+                missing.append(prop.name)
+            values.append(value)
+        if missing:
+            self.Raise('Missing required properties/entry args: %s' %
+                       (', '.join(missing)))
+        return values
+
     def GetPath(self):
         """Get the path of a node
 
@@ -257,13 +315,21 @@ class Entry(object):
     def GetData(self):
         return self.data
 
-    def GetPositions(self):
+    def GetOffsets(self):
         return {}
 
-    def SetPositionSize(self, pos, size):
-        self.pos = pos
+    def SetOffsetSize(self, pos, size):
+        self.offset = pos
         self.size = size
 
+    def SetImagePos(self, image_pos):
+        """Set the position in the image
+
+        Args:
+            image_pos: Position of this entry in the image
+        """
+        self.image_pos = image_pos + self.offset
+
     def ProcessContents(self):
         pass
 
@@ -275,15 +341,20 @@ class Entry(object):
         """
         pass
 
-    def CheckPosition(self):
-        """Check that the entry positions are correct
+    def CheckOffset(self):
+        """Check that the entry offsets are correct
 
-        This is used for entries which have extra position requirements (other
+        This is used for entries which have extra offset requirements (other
         than having to be fully inside their section). Sub-classes can implement
         this function and raise if there is a problem.
         """
         pass
 
+    @staticmethod
+    def WriteMapLine(fd, indent, name, offset, size, image_pos):
+        print('%08x  %s%08x  %08x  %s' % (image_pos, ' ' * indent, offset,
+                                          size, name), file=fd)
+
     def WriteMap(self, fd, indent):
         """Write a map of the entry to a .map file
 
@@ -291,5 +362,97 @@ class Entry(object):
             fd: File to write the map to
             indent: Curent indent level of map (0=none, 1=one level, etc.)
         """
-        print('%s%08x  %08x  %s' % (' ' * indent, self.pos, self.size,
-                                    self.name), file=fd)
+        self.WriteMapLine(fd, indent, self.name, self.offset, self.size,
+                          self.image_pos)
+
+    def GetEntries(self):
+        """Return a list of entries contained by this entry
+
+        Returns:
+            List of entries, or None if none. A normal entry has no entries
+                within it so will return None
+        """
+        return None
+
+    def GetArg(self, name, datatype=str):
+        """Get the value of an entry argument or device-tree-node property
+
+        Some node properties can be provided as arguments to binman. First check
+        the entry arguments, and fall back to the device tree if not found
+
+        Args:
+            name: Argument name
+            datatype: Data type (str or int)
+
+        Returns:
+            Value of argument as a string or int, or None if no value
+
+        Raises:
+            ValueError if the argument cannot be converted to in
+        """
+        value = control.GetEntryArg(name)
+        if value is not None:
+            if datatype == int:
+                try:
+                    value = int(value)
+                except ValueError:
+                    self.Raise("Cannot convert entry arg '%s' (value '%s') to integer" %
+                               (name, value))
+            elif datatype == str:
+                pass
+            else:
+                raise ValueError("GetArg() internal error: Unknown data type '%s'" %
+                                 datatype)
+        else:
+            value = fdt_util.GetDatatype(self._node, name, datatype)
+        return value
+
+    @staticmethod
+    def WriteDocs(modules, test_missing=None):
+        """Write out documentation about the various entry types to stdout
+
+        Args:
+            modules: List of modules to include
+            test_missing: Used for testing. This is a module to report
+                as missing
+        """
+        print('''Binman Entry Documentation
+===========================
+
+This file describes the entry types supported by binman. These entry types can
+be placed in an image one by one to build up a final firmware image. It is
+fairly easy to create new entry types. Just add a new file to the 'etype'
+directory. You can use the existing entries as examples.
+
+Note that some entries are subclasses of others, using and extending their
+features to produce new behaviours.
+
+
+''')
+        modules = sorted(modules)
+
+        # Don't show the test entry
+        if '_testing' in modules:
+            modules.remove('_testing')
+        missing = []
+        for name in modules:
+            module = Entry.Lookup(name, name, name)
+            docs = getattr(module, '__doc__')
+            if test_missing == name:
+                docs = None
+            if docs:
+                lines = docs.splitlines()
+                first_line = lines[0]
+                rest = [line[4:] for line in lines[1:]]
+                hdr = 'Entry: %s: %s' % (name.replace('_', '-'), first_line)
+                print(hdr)
+                print('-' * len(hdr))
+                print('\n'.join(rest))
+                print()
+                print()
+            else:
+                missing.append(name)
+
+        if missing:
+            raise ValueError('Documentation is missing for modules: %s' %
+                             ', '.join(missing))
index 6a1af577988981392860b35acffd2c05b8188913..02c165c0c3e5e95146131ca67616181bfeea0bc0 100644 (file)
@@ -5,7 +5,9 @@
 # Entry-type module for testing purposes. Not used in real images.
 #
 
-from entry import Entry
+from collections import OrderedDict
+
+from entry import Entry, EntryArg
 import fdt_util
 import tools
 
@@ -13,8 +15,30 @@ import tools
 class Entry__testing(Entry):
     """A fake entry used for testing
 
+    This entry should not be used in normal images. It is a special entry with
+    strange features used for testing.
+
+    Properties / Entry arguments
+        test-str-fdt: Test string, normally in the node
+        test-int-fdt: Test integer, normally in the node
+        test-str-arg: Test string, normally in the entry arguments
+        test-int-arg: Test integer, normally in the entry arguments
+
+    The entry has a single 'a' byte as its contents. Operation is controlled by
+    a number of properties in the node, as follows:
+
     Properties:
-        return_invalid_entry: Return an invalid entry from GetPositions()
+        return-invalid-entry: Return an invalid entry from GetOffsets()
+        return-unknown-contents: Refuse to provide any contents (to cause a
+            failure)
+        bad-update-contents: Implement ProcessContents() incorrectly so as to
+            cause a failure
+        never-complete-process-fdt: Refund to process the FDT (to cause a
+            failure)
+        require-args: Require that all used args are present (generating an
+            error if not)
+        force-bad-datatype: Force a call to GetEntryArgsOrProps() with a bad
+            data type (generating an error)
     """
     def __init__(self, section, etype, node):
         Entry.__init__(self, section, etype, node)
@@ -24,9 +48,26 @@ class Entry__testing(Entry):
                                                      'return-unknown-contents')
         self.bad_update_contents = fdt_util.GetBool(self._node,
                                                     'bad-update-contents')
+
+        # Set to True when the entry is ready to process the FDT.
         self.process_fdt_ready = False
         self.never_complete_process_fdt = fdt_util.GetBool(self._node,
                                                 'never-complete-process-fdt')
+        self.require_args = fdt_util.GetBool(self._node, 'require-args')
+
+        # This should be picked up by GetEntryArgsOrProps()
+        self.test_existing_prop = 'existing'
+        self.force_bad_datatype = fdt_util.GetBool(self._node,
+                                                   'force-bad-datatype')
+        (self.test_str_fdt, self.test_str_arg, self.test_int_fdt,
+         self.test_int_arg, existing) = self.GetEntryArgsOrProps([
+            EntryArg('test-str-fdt', str),
+            EntryArg('test-str-arg', str),
+            EntryArg('test-int-fdt', int),
+            EntryArg('test-int-arg', int),
+            EntryArg('test-existing-prop', str)], self.require_args)
+        if self.force_bad_datatype:
+            self.GetEntryArgsOrProps([EntryArg('test-bad-datatype-arg', bool)])
 
     def ObtainContents(self):
         if self.return_unknown_contents:
@@ -35,7 +76,7 @@ class Entry__testing(Entry):
         self.contents_size = len(self.data)
         return True
 
-    def GetPositions(self):
+    def GetOffsets(self):
         if self.return_invalid_entry :
             return {'invalid-entry': [1, 2]}
         return {}
index 28e6651a935e4c171b2e26c7ada812128919b031..3f46eecf308f5cc0b2e7d6e2e6e8bdf587748e07 100644 (file)
@@ -10,6 +10,18 @@ import fdt_util
 import tools
 
 class Entry_blob(Entry):
+    """Entry containing an arbitrary binary blob
+
+    Note: This should not be used by itself. It is normally used as a parent
+    class by other entry types.
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This entry reads data from a file and places it in the entry. The
+    default filename is often specified specified by the subclass. See for
+    example the 'u_boot' entry which provides the filename 'u-boot.bin'.
+    """
     def __init__(self, section, etype, node):
         Entry.__init__(self, section, etype, node)
         self._filename = fdt_util.GetString(self._node, "filename", self.etype)
@@ -17,10 +29,10 @@ class Entry_blob(Entry):
     def ObtainContents(self):
         self._filename = self.GetDefaultFilename()
         self._pathname = tools.GetInputFilename(self._filename)
-        self.ReadContents()
+        self.ReadBlobContents()
         return True
 
-    def ReadContents(self):
+    def ReadBlobContents(self):
         with open(self._pathname) as fd:
             # We assume the data is small enough to fit into memory. If this
             # is used for large filesystem image that might not be true.
diff --git a/tools/binman/etype/blob_named_by_arg.py b/tools/binman/etype/blob_named_by_arg.py
new file mode 100644 (file)
index 0000000..344112b
--- /dev/null
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for a blob where the filename comes from a property in the
+# node or an entry argument. The property is called '<blob_fname>-path' where
+# <blob_fname> is provided by the subclass using this entry type.
+
+from collections import OrderedDict
+
+from blob import Entry_blob
+from entry import EntryArg
+
+
+class Entry_blob_named_by_arg(Entry_blob):
+    """A blob entry which gets its filename property from its subclass
+
+    Properties / Entry arguments:
+        - <xxx>-path: Filename containing the contents of this entry (optional,
+            defaults to 0)
+
+    where <xxx> is the blob_fname argument to the constructor.
+
+    This entry cannot be used directly. Instead, it is used as a parent class
+    for another entry, which defined blob_fname. This parameter is used to
+    set the entry-arg or property containing the filename. The entry-arg or
+    property is in turn used to set the actual filename.
+
+    See cros_ec_rw for an example of this.
+    """
+    def __init__(self, section, etype, node, blob_fname):
+        Entry_blob.__init__(self, section, etype, node)
+        self._filename, = self.GetEntryArgsOrProps(
+            [EntryArg('%s-path' % blob_fname, str)])
diff --git a/tools/binman/etype/cros_ec_rw.py b/tools/binman/etype/cros_ec_rw.py
new file mode 100644 (file)
index 0000000..261f865
--- /dev/null
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for a Chromium OS EC image (read-write section)
+#
+
+from blob_named_by_arg import Entry_blob_named_by_arg
+
+
+class Entry_cros_ec_rw(Entry_blob_named_by_arg):
+    """A blob entry which contains a Chromium OS read-write EC image
+
+    Properties / Entry arguments:
+        - cros-ec-rw-path: Filename containing the EC image
+
+    This entry holds a Chromium OS EC (embedded controller) image, for use in
+    updating the EC on startup via software sync.
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob_named_by_arg.__init__(self, section, etype, node,
+                                         'cros-ec-rw')
diff --git a/tools/binman/etype/fill.py b/tools/binman/etype/fill.py
new file mode 100644 (file)
index 0000000..7210a83
--- /dev/null
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+from entry import Entry
+import fdt_util
+
+
+class Entry_fill(Entry):
+    """An entry which is filled to a particular byte value
+
+    Properties / Entry arguments:
+        - fill-byte: Byte to use to fill the entry
+
+    Note that the size property must be set since otherwise this entry does not
+    know how large it should be.
+
+    You can often achieve the same effect using the pad-byte property of the
+    overall image, in that the space between entries will then be padded with
+    that byte. But this entry is sometimes useful for explicitly setting the
+    byte value of a region.
+    """
+    def __init__(self, section, etype, node):
+        Entry.__init__(self, section, etype, node)
+        if not self.size:
+            self.Raise("'fill' entry must have a size property")
+        self.fill_value = fdt_util.GetByte(self._node, 'fill-byte', 0)
+
+    def ObtainContents(self):
+        self.SetContents(chr(self.fill_value) * self.size)
+        return True
diff --git a/tools/binman/etype/fmap.py b/tools/binman/etype/fmap.py
new file mode 100644 (file)
index 0000000..f1dd81e
--- /dev/null
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for a Flash map, as used by the flashrom SPI flash tool
+#
+
+from entry import Entry
+import fmap_util
+
+
+class Entry_fmap(Entry):
+    """An entry which contains an Fmap section
+
+    Properties / Entry arguments:
+        None
+
+    FMAP is a simple format used by flashrom, an open-source utility for
+    reading and writing the SPI flash, typically on x86 CPUs. The format
+    provides flashrom with a list of areas, so it knows what it in the flash.
+    It can then read or write just a single area, instead of the whole flash.
+
+    The format is defined by the flashrom project, in the file lib/fmap.h -
+    see www.flashrom.org/Flashrom for more information.
+
+    When used, this entry will be populated with an FMAP which reflects the
+    entries in the current image. Note that any hierarchy is squashed, since
+    FMAP does not support this.
+    """
+    def __init__(self, section, etype, node):
+        Entry.__init__(self, section, etype, node)
+
+    def _GetFmap(self):
+        """Build an FMAP from the entries in the current image
+
+        Returns:
+            FMAP binary data
+        """
+        def _AddEntries(areas, entry):
+            entries = entry.GetEntries()
+            if entries:
+                for subentry in entries.values():
+                    _AddEntries(areas, subentry)
+            else:
+                areas.append(fmap_util.FmapArea(entry.image_pos or 0,
+                                                entry.size or 0, entry.name, 0))
+
+        entries = self.section.GetEntries()
+        areas = []
+        for entry in entries.values():
+            _AddEntries(areas, entry)
+        return fmap_util.EncodeFmap(self.section.GetSize() or 0, self.name,
+                                    areas)
+
+    def ObtainContents(self):
+        """Obtain a placeholder for the fmap contents"""
+        self.SetContents(self._GetFmap())
+        return True
+
+    def ProcessContents(self):
+        self.SetContents(self._GetFmap())
diff --git a/tools/binman/etype/gbb.py b/tools/binman/etype/gbb.py
new file mode 100644 (file)
index 0000000..8fe10f4
--- /dev/null
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+# Support for a Chromium OS Google Binary Block, used to record read-only
+# information mostly used by firmware.
+
+from collections import OrderedDict
+
+import command
+from entry import Entry, EntryArg
+
+import fdt_util
+import tools
+
+# Build GBB flags.
+# (src/platform/vboot_reference/firmware/include/gbb_header.h)
+gbb_flag_properties = {
+  'dev-screen-short-delay': 0x1,
+  'load-option-roms': 0x2,
+  'enable-alternate-os': 0x4,
+  'force-dev-switch-on': 0x8,
+  'force-dev-boot-usb': 0x10,
+  'disable-fw-rollback-check': 0x20,
+  'enter-triggers-tonorm': 0x40,
+  'force-dev-boot-legacy': 0x80,
+  'faft-key-override': 0x100,
+  'disable-ec-software-sync': 0x200,
+  'default-dev-boot-legacy': 0x400,
+  'disable-pd-software-sync': 0x800,
+  'disable-lid-shutdown': 0x1000,
+  'force-dev-boot-fastboot-full-cap': 0x2000,
+  'enable-serial': 0x4000,
+  'disable-dwmp': 0x8000,
+}
+
+
+class Entry_gbb(Entry):
+    """An entry which contains a Chromium OS Google Binary Block
+
+    Properties / Entry arguments:
+        - hardware-id: Hardware ID to use for this build (a string)
+        - keydir: Directory containing the public keys to use
+        - bmpblk: Filename containing images used by recovery
+
+    Chromium OS uses a GBB to store various pieces of information, in particular
+    the root and recovery keys that are used to verify the boot process. Some
+    more details are here:
+
+        https://www.chromium.org/chromium-os/firmware-porting-guide/2-concepts
+
+    but note that the page dates from 2013 so is quite out of date. See
+    README.chromium for how to obtain the required keys and tools.
+    """
+    def __init__(self, section, etype, node):
+        Entry.__init__(self, section, etype, node)
+        self.hardware_id, self.keydir, self.bmpblk = self.GetEntryArgsOrProps(
+            [EntryArg('hardware-id', str),
+             EntryArg('keydir', str),
+             EntryArg('bmpblk', str)])
+
+        # Read in the GBB flags from the config
+        self.gbb_flags = 0
+        flags_node = node.FindNode('flags')
+        if flags_node:
+            for flag, value in gbb_flag_properties.iteritems():
+                if fdt_util.GetBool(flags_node, flag):
+                    self.gbb_flags |= value
+
+    def ObtainContents(self):
+        gbb = 'gbb.bin'
+        fname = tools.GetOutputFilename(gbb)
+        if not self.size:
+            self.Raise('GBB must have a fixed size')
+        gbb_size = self.size
+        bmpfv_size = gbb_size - 0x2180
+        if bmpfv_size < 0:
+            self.Raise('GBB is too small (minimum 0x2180 bytes)')
+        sizes = [0x100, 0x1000, bmpfv_size, 0x1000]
+        sizes = ['%#x' % size for size in sizes]
+        keydir = tools.GetInputFilename(self.keydir)
+        gbb_set_command = [
+            'gbb_utility', '-s',
+            '--hwid=%s' % self.hardware_id,
+            '--rootkey=%s/root_key.vbpubk' % keydir,
+            '--recoverykey=%s/recovery_key.vbpubk' % keydir,
+            '--flags=%d' % self.gbb_flags,
+            '--bmpfv=%s' % tools.GetInputFilename(self.bmpblk),
+            fname]
+
+        tools.Run('futility', 'gbb_utility', '-c', ','.join(sizes), fname)
+        tools.Run('futility', *gbb_set_command)
+
+        self.SetContents(tools.ReadFile(fname))
+        return True
index b8621e0cc5ece75201bdd6b84faefb76f6acd880..fa6f7793c64ab22805ae365fe0b0ed4ec18b5da4 100644 (file)
@@ -9,5 +9,15 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_cmc(Entry_blob):
+    """Entry containing an Intel Chipset Micro Code (CMC) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains microcode for some devices in a special format. An
+    example filename is 'Microcode/C0_22211.BIN'.
+
+    See README.x86 for information about x86 binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
index 0e7865521e10c4bc7c58a681dc4fb9664aa8b985..6acbbd8b7a5ad17d5c97b1652f355e7061e1620e 100644 (file)
@@ -13,6 +13,7 @@ from blob import Entry_blob
 FD_SIGNATURE   = struct.pack('<L', 0x0ff0a55a)
 MAX_REGIONS    = 5
 
+# Region numbers supported by the Intel firmware format
 (REGION_DESCRIPTOR, REGION_BIOS, REGION_ME, REGION_GBE,
         REGION_PDATA) = range(5)
 
@@ -27,21 +28,32 @@ class Region:
 class Entry_intel_descriptor(Entry_blob):
     """Intel flash descriptor block (4KB)
 
-    This is placed at the start of flash and provides information about
+    Properties / Entry arguments:
+        filename: Filename of file containing the descriptor. This is typically
+            a 4KB binary file, sometimes called 'descriptor.bin'
+
+    This entry is placed at the start of flash and provides information about
     the SPI flash regions. In particular it provides the base address and
-    size of the ME region, allowing us to place the ME binary in the right
-    place.
+    size of the ME (Management Engine) region, allowing us to place the ME
+    binary in the right place.
+
+    With this entry in your image, the position of the 'intel-me' entry will be
+    fixed in the image, which avoids you needed to specify an offset for that
+    region. This is useful, because it is not possible to change the position
+    of the ME region without updating the descriptor.
+
+    See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
         self._regions = []
 
-    def GetPositions(self):
-        pos = self.data.find(FD_SIGNATURE)
-        if pos == -1:
+    def GetOffsets(self):
+        offset = self.data.find(FD_SIGNATURE)
+        if offset == -1:
             self.Raise('Cannot find FD signature')
         flvalsig, flmap0, flmap1, flmap2 = struct.unpack('<LLLL',
-                                                    self.data[pos:pos + 16])
+                                                self.data[offset:offset + 16])
         frba = ((flmap0 >> 16) & 0xff) << 4
         for i in range(MAX_REGIONS):
             self._regions.append(Region(self.data, frba, i))
index cb80a617c32fa39160ede109c723baa9a06467ea..00a78e7083221113ebf0ab7d48dffa63228d2993 100644 (file)
@@ -9,5 +9,19 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_fsp(Entry_blob):
+    """Entry containing an Intel Firmware Support Package (FSP) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains binary blobs which are used on some devices to make the
+    platform work. U-Boot executes this code since it is not possible to set up
+    the hardware using U-Boot open-source code. Documentation is typically not
+    available in sufficient detail to allow this.
+
+    An example filename is 'FSP/QUEENSBAY_FSP_GOLD_001_20-DECEMBER-2013.fd'
+
+    See README.x86 for information about x86 binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
index 0682ead943963cf44a8a45fe0ccb6be2b6d7c517..247c5b33866df7c82248be22bdfb9768e074bdc3 100644 (file)
@@ -9,5 +9,20 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_me(Entry_blob):
+    """Entry containing an Intel Management Engine (ME) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains code used by the SoC that is required to make it work.
+    The Management Engine is like a background task that runs things that are
+    not clearly documented, but may include keyboard, deplay and network
+    access. For platform that use ME it is not possible to disable it. U-Boot
+    does not directly execute code in the ME binary.
+
+    A typical filename is 'me.bin'.
+
+    See README.x86 for information about x86 binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
index 305ac98888bf3be3230cc608185d1d727b00be16..4dbc99a04f2ac346b6e4c9e1c8b81eb2d0be5529 100644 (file)
@@ -9,6 +9,17 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_mrc(Entry_blob):
+    """Entry containing an Intel Memory Reference Code (MRC) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains code for setting up the SDRAM on some Intel systems. This
+    is executed by U-Boot when needed early during startup. A typical filename
+    is 'mrc.bin'.
+
+    See README.x86 for information about x86 binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
index d4e8c3f797da379b690e2b2f7a5e68013997365b..d93dd19634146e5d514260df0802599113d9054d 100644 (file)
@@ -8,5 +8,15 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_vbt(Entry_blob):
+    """Entry containing an Intel Video BIOS Table (VBT) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains code that sets up the integrated graphics subsystem on
+    some Intel SoCs. U-Boot executes this when the display is started up.
+
+    See README.x86 for information about Intel binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
index 140dd40dda628aa2d95c4b0559948dc11264ec61..40982c8665680990d7e7e7bf91352b6c6792c51f 100644 (file)
@@ -9,5 +9,17 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_vga(Entry_blob):
+    """Entry containing an Intel Video Graphics Adaptor (VGA) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains code that sets up the integrated graphics subsystem on
+    some Intel SoCs. U-Boot executes this when the display is started up.
+
+    This is similar to the VBT file but in a different format.
+
+    See README.x86 for information about Intel binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
index 787257d3ec17790506b2a75aa100dc3514d1cdc6..f5b2ed67cf8fa46706b541da48b0bbcc69525e82 100644 (file)
@@ -13,8 +13,25 @@ import tools
 import bsection
 
 class Entry_section(Entry):
-    def __init__(self, image, etype, node):
-        Entry.__init__(self, image, etype, node)
+    """Entry that contains other entries
+
+    Properties / Entry arguments: (see binman README for more information)
+        - size: Size of section in bytes
+        - align-size: Align size to a particular power of two
+        - pad-before: Add padding before the entry
+        - pad-after: Add padding after the entry
+        - pad-byte: Pad byte to use when padding
+        - sort-by-offset: Reorder the entries by offset
+        - end-at-4gb: Used to build an x86 ROM which ends at 4GB (2^32)
+        - name-prefix: Adds a prefix to the name of every entry in the section
+            when writing out the map
+
+    A section is an entry which can contain other entries, thus allowing
+    hierarchical images to be created. See 'Sections and hierarchical images'
+    in the binman README for more information.
+    """
+    def __init__(self, section, etype, node):
+        Entry.__init__(self, section, etype, node)
         self._section = bsection.Section(node.name, node)
 
     def ProcessFdt(self, fdt):
@@ -30,20 +47,25 @@ class Entry_section(Entry):
     def GetData(self):
         return self._section.GetData()
 
-    def GetPositions(self):
-        """Handle entries that want to set the position/size of other entries
+    def GetOffsets(self):
+        """Handle entries that want to set the offset/size of other entries
 
-        This calls each entry's GetPositions() method. If it returns a list
+        This calls each entry's GetOffsets() method. If it returns a list
         of entries to update, it updates them.
         """
-        self._section.GetEntryPositions()
+        self._section.GetEntryOffsets()
         return {}
 
-    def Pack(self, pos):
+    def Pack(self, offset):
         """Pack all entries into the section"""
         self._section.PackEntries()
-        self.size = self._section.CheckSize()
-        return super(Entry_section, self).Pack(pos)
+        self._section.SetOffset(offset)
+        self.size = self._section.GetSize()
+        return super(Entry_section, self).Pack(offset)
+
+    def SetImagePos(self, image_pos):
+        Entry.SetImagePos(self, image_pos)
+        self._section.SetImagePos(image_pos + self.offset)
 
     def WriteSymbols(self, section):
         """Write symbol values into binary files for access at run time"""
@@ -57,7 +79,7 @@ class Entry_section(Entry):
         self._section.ProcessEntryContents()
         super(Entry_section, self).ProcessContents()
 
-    def CheckPosition(self):
+    def CheckOffset(self):
         self._section.CheckEntries()
 
     def WriteMap(self, fd, indent):
@@ -66,5 +88,7 @@ class Entry_section(Entry):
         Args:
             fd: File to write the map to
         """
-        super(Entry_section, self).WriteMap(fd, indent)
-        self._section.WriteMap(fd, indent + 1)
+        self._section.WriteMap(fd, indent)
+
+    def GetEntries(self):
+        return self._section.GetEntries()
diff --git a/tools/binman/etype/text.py b/tools/binman/etype/text.py
new file mode 100644 (file)
index 0000000..7a1cddf
--- /dev/null
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+from collections import OrderedDict
+
+from entry import Entry, EntryArg
+import fdt_util
+
+
+class Entry_text(Entry):
+    """An entry which contains text
+
+    The text can be provided either in the node itself or by a command-line
+    argument. There is a level of indirection to allow multiple text strings
+    and sharing of text.
+
+    Properties / Entry arguments:
+        text-label: The value of this string indicates the property / entry-arg
+            that contains the string to place in the entry
+        <xxx> (actual name is the value of text-label): contains the string to
+            place in the entry.
+
+    Example node:
+
+        text {
+            size = <50>;
+            text-label = "message";
+        };
+
+    You can then use:
+
+        binman -amessage="this is my message"
+
+    and binman will insert that string into the entry.
+
+    It is also possible to put the string directly in the node:
+
+        text {
+            size = <8>;
+            text-label = "message";
+            message = "a message directly in the node"
+        };
+
+    The text is not itself nul-terminated. This can be achieved, if required,
+    by setting the size of the entry to something larger than the text.
+    """
+    def __init__(self, section, etype, node):
+        Entry.__init__(self, section, etype, node)
+        self.text_label, = self.GetEntryArgsOrProps(
+            [EntryArg('text-label', str)])
+        self.value, = self.GetEntryArgsOrProps([EntryArg(self.text_label, str)])
+
+    def ObtainContents(self):
+        self.SetContents(self.value)
+        return True
index b6058bf6b52aae89d983d7277e76c7b321217632..23dd12ce43594bf359532d86ce99f266178097a8 100644 (file)
@@ -9,6 +9,22 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot(Entry_blob):
+    """U-Boot flat binary
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.bin (default 'u-boot.bin')
+
+    This is the U-Boot binary, containing relocation information to allow it
+    to relocate itself at runtime. The binary typically includes a device tree
+    blob at the end of it. Use u_boot_nodtb if you want to package the device
+    tree separately.
+
+    U-Boot can access binman symbols at runtime. See:
+
+        'Access to binman entry offsets at run time (fdt)'
+
+    in the binman README for more information.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
index dd3c5b2790139f2934dae160b097cc7ed77065cc..fb3dd1cf6425217a4af5928b5df60c730fcd44c2 100644 (file)
@@ -9,6 +9,15 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_dtb(Entry_blob):
+    """U-Boot device tree
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
+
+    This is the U-Boot device tree, containing configuration information for
+    U-Boot. U-Boot needs this to know what devices are present and which drivers
+    to activate.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
index 3808d6d27802ff0be845363bef0cab8137e6ece7..285a28dd1e7437c5cf0ae574687b227a96124983 100644 (file)
@@ -6,7 +6,6 @@
 #
 
 import control
-import fdt
 from entry import Entry
 from blob import Entry_blob
 import tools
@@ -14,8 +13,16 @@ import tools
 class Entry_u_boot_dtb_with_ucode(Entry_blob):
     """A U-Boot device tree file, with the microcode removed
 
-    See Entry_u_boot_ucode for full details of the 3 entries involved in this
-    process.
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
+
+    See Entry_u_boot_ucode for full details of the three entries involved in
+    this process. This entry provides the U-Boot device-tree file, which
+    contains the microcode. If the microcode is not being collated into one
+    place then the offset and size of the microcode is recorded by this entry,
+    for use by u_boot_with_ucode_ptr. If it is being collated, then this
+    entry deletes the microcode from the device tree (to save space) and makes
+    it available to u_boot_ucode.
     """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
@@ -30,13 +37,16 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
         return 'u-boot.dtb'
 
     def ProcessFdt(self, fdt):
+        # So the module can be loaded without it
+        import fdt
+
         # If the section does not need microcode, there is nothing to do
         ucode_dest_entry = self.section.FindEntryType(
             'u-boot-spl-with-ucode-ptr')
-        if not ucode_dest_entry or not ucode_dest_entry.target_pos:
+        if not ucode_dest_entry or not ucode_dest_entry.target_offset:
             ucode_dest_entry = self.section.FindEntryType(
                 'u-boot-with-ucode-ptr')
-        if not ucode_dest_entry or not ucode_dest_entry.target_pos:
+        if not ucode_dest_entry or not ucode_dest_entry.target_offset:
             return True
 
         # Remove the microcode
@@ -61,7 +71,7 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
         # Call the base class just in case it does something important.
         Entry_blob.ObtainContents(self)
         self._pathname = control.GetFdtPath(self._filename)
-        self.ReadContents()
+        self.ReadBlobContents()
         if self.ucode:
             for node in self.ucode.subnodes:
                 data_prop = node.props.get('data')
index 6e0b736af148faf248f8acf047cf348467a6aad5..1ec0757c7f8d10b19fc6de33a82b46b4491b14c7 100644 (file)
@@ -9,6 +9,17 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_img(Entry_blob):
+    """U-Boot legacy image
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.img (default 'u-boot.img')
+
+    This is the U-Boot binary as a packaged image, in legacy format. It has a
+    header which allows it to be loaded at the correct address for execution.
+
+    You should use FIT (Flat Image Tree) instead of the legacy image for new
+    applications.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
index ca9e53a094777dac848c3cb170391f4fc1784f79..a4b95a4390a7a698e5779fe385e4bf409e4fb652 100644 (file)
@@ -9,6 +9,17 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_nodtb(Entry_blob):
+    """U-Boot flat binary without device tree appended
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.bin (default 'u-boot-nodtb.bin')
+
+    This is the U-Boot binary, containing relocation information to allow it
+    to relocate itself at runtime. It does not include a device tree blob at
+    the end of it so normally cannot work without it. You can add a u_boot_dtb
+    entry after this one, or use a u_boot entry instead (which contains both
+    U-Boot and the device tree).
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
index 9edd2dad0306601dea7dc15d56300262f502f67d..ab78714c8d6781125fa2f6c11099ef22dd350c90 100644 (file)
@@ -11,6 +11,27 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_spl(Entry_blob):
+    """U-Boot SPL binary
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot-spl.bin (default 'spl/u-boot-spl.bin')
+
+    This is the U-Boot SPL (Secondary Program Loader) binary. This is a small
+    binary which loads before U-Boot proper, typically into on-chip SRAM. It is
+    responsible for locating, loading and jumping to U-Boot. Note that SPL is
+    not relocatable so must be loaded to the correct address in SRAM, or written
+    to run from the correct address if direct flash execution is possible (e.g.
+    on x86 devices).
+
+    SPL can access binman symbols at runtime. See:
+
+        'Access to binman entry offsets at run time (symbols)'
+
+    in the binman README for more information.
+
+    The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+    binman uses that to look up symbols to write into the SPL binary.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
         self.elf_fname = 'spl/u-boot-spl'
index 65f631d3c5e4d6080ade38ec877252b161a12002..00b7ac50040ef752a11f9705bbc493690e167127 100644 (file)
@@ -14,6 +14,22 @@ from blob import Entry_blob
 import tools
 
 class Entry_u_boot_spl_bss_pad(Entry_blob):
+    """U-Boot SPL binary padded with a BSS region
+
+    Properties / Entry arguments:
+        None
+
+    This is similar to u_boot_spl except that padding is added after the SPL
+    binary to cover the BSS (Block Started by Symbol) region. This region holds
+    the various used by SPL. It is set to 0 by SPL when it starts up. If you
+    want to append data to the SPL image (such as a device tree file), you must
+    pad out the BSS region to avoid the data overlapping with U-Boot variables.
+    This entry is useful in that case. It automatically pads out the entry size
+    to cover both the code, data and BSS.
+
+    The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+    binman uses that to look up the BSS address.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
index eefa1ff53a4ad9c69215f1e67eb2cfc9f369e413..cb29ba3fd87222437839ce4e1e825e85e2bc5fb7 100644 (file)
@@ -2,13 +2,22 @@
 # Copyright (c) 2016 Google, Inc
 # Written by Simon Glass <sjg@chromium.org>
 #
-# Entry-type module for U-Boot device tree
+# Entry-type module for U-Boot device tree in SPL (Secondary Program Loader)
 #
 
 from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_spl_dtb(Entry_blob):
+    """U-Boot SPL device tree
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.dtb (default 'spl/u-boot-spl.dtb')
+
+    This is the SPL device tree, containing configuration information for
+    SPL. SPL needs this to know what devices are present and which drivers
+    to activate.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
index 99e56ebe3bfd29674b1b5139905afb211d739d3e..41c17366b1d6df488cd3a369000eeda9c278fca6 100644 (file)
@@ -9,6 +9,18 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_spl_nodtb(Entry_blob):
+    """SPL binary without device tree appended
+
+    Properties / Entry arguments:
+        - filename: Filename of spl/u-boot-spl-nodtb.bin (default
+            'spl/u-boot-spl-nodtb.bin')
+
+    This is the U-Boot SPL binary, It does not include a device tree blob at
+    the end of it so may not be able to work without it, assuming SPL needs
+    a device tree to operation on your platform. You can add a u_boot_spl_dtb
+    entry after this one, or use a u_boot_spl entry instead (which contains
+    both SPL and the device tree).
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
diff --git a/tools/binman/etype/u_boot_tpl.py b/tools/binman/etype/u_boot_tpl.py
new file mode 100644 (file)
index 0000000..4d4bb92
--- /dev/null
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for tpl/u-boot-tpl.bin
+#
+
+import elf
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_tpl(Entry_blob):
+    """U-Boot TPL binary
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot-tpl.bin (default 'tpl/u-boot-tpl.bin')
+
+    This is the U-Boot TPL (Tertiary Program Loader) binary. This is a small
+    binary which loads before SPL, typically into on-chip SRAM. It is
+    responsible for locating, loading and jumping to SPL, the next-stage
+    loader. Note that SPL is not relocatable so must be loaded to the correct
+    address in SRAM, or written to run from the correct address if direct
+    flash execution is possible (e.g. on x86 devices).
+
+    SPL can access binman symbols at runtime. See:
+
+        'Access to binman entry offsets at run time (symbols)'
+
+    in the binman README for more information.
+
+    The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+    binman uses that to look up symbols to write into the TPL binary.
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob.__init__(self, section, etype, node)
+        self.elf_fname = 'tpl/u-boot-tpl'
+
+    def GetDefaultFilename(self):
+        return 'tpl/u-boot-tpl.bin'
+
+    def WriteSymbols(self, section):
+        elf.LookupAndWriteSymbols(self.elf_fname, self, section)
diff --git a/tools/binman/etype/u_boot_tpl_dtb.py b/tools/binman/etype/u_boot_tpl_dtb.py
new file mode 100644 (file)
index 0000000..9c4e668
--- /dev/null
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for U-Boot device tree in TPL (Tertiary Program Loader)
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_tpl_dtb(Entry_blob):
+    """U-Boot TPL device tree
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.dtb (default 'tpl/u-boot-tpl.dtb')
+
+    This is the TPL device tree, containing configuration information for
+    TPL. TPL needs this to know what devices are present and which drivers
+    to activate.
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob.__init__(self, section, etype, node)
+
+    def GetDefaultFilename(self):
+        return 'tpl/u-boot-tpl.dtb'
index ea0c85cc5c7871be95970054768b33b5553f8f56..6acf94d8cbc557ae0136c1157c518eb1408bf903 100644 (file)
@@ -12,6 +12,12 @@ import tools
 class Entry_u_boot_ucode(Entry_blob):
     """U-Boot microcode block
 
+    Properties / Entry arguments:
+        None
+
+    The contents of this entry are filled in automatically by other entries
+    which must also be in the image.
+
     U-Boot on x86 needs a single block of microcode. This is collected from
     the various microcode update nodes in the device tree. It is also unable
     to read the microcode from the device tree on platforms that use FSP
@@ -59,8 +65,8 @@ class Entry_u_boot_ucode(Entry_blob):
         ucode_dest_entry = self.section.FindEntryType('u-boot-with-ucode-ptr')
         ucode_dest_entry_spl = self.section.FindEntryType(
             'u-boot-spl-with-ucode-ptr')
-        if ((not ucode_dest_entry or not ucode_dest_entry.target_pos) and
-            (not ucode_dest_entry_spl or not ucode_dest_entry_spl.target_pos)):
+        if ((not ucode_dest_entry or not ucode_dest_entry.target_offset) and
+            (not ucode_dest_entry_spl or not ucode_dest_entry_spl.target_offset)):
             self.data = ''
             return True
 
@@ -86,6 +92,6 @@ class Entry_u_boot_ucode(Entry_blob):
             fd.write(fdt_entry.ucode_data)
 
         self._pathname = fname
-        self.ReadContents()
+        self.ReadBlobContents()
 
         return True
index 8b1e41152e31f8f2ecd8193f613909c147ed7765..51e7ba48f597557d5a208942ae08eb6992627f48 100644 (file)
@@ -17,13 +17,18 @@ import tools
 class Entry_u_boot_with_ucode_ptr(Entry_blob):
     """U-Boot with embedded microcode pointer
 
-    See Entry_u_boot_ucode for full details of the 3 entries involved in this
-    process.
+    Properties / Entry arguments:
+        - filename: Filename of u-boot-nodtb.dtb (default 'u-boot-nodtb.dtb')
+
+    See Entry_u_boot_ucode for full details of the three entries involved in
+    this process. This entry updates U-Boot with the offset and size of the
+    microcode, to allow early x86 boot code to find it without doing anything
+    complicated. Otherwise it is the same as the u_boot entry.
     """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
         self.elf_fname = 'u-boot'
-        self.target_pos = None
+        self.target_offset = None
 
     def GetDefaultFilename(self):
         return 'u-boot-nodtb.bin'
@@ -33,52 +38,53 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob):
         fname = tools.GetInputFilename(self.elf_fname)
         sym = elf.GetSymbolAddress(fname, '_dt_ucode_base_size')
         if sym:
-           self.target_pos = sym
+           self.target_offset = sym
         elif not fdt_util.GetBool(self._node, 'optional-ucode'):
             self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot')
         return True
 
     def ProcessContents(self):
         # If the image does not need microcode, there is nothing to do
-        if not self.target_pos:
+        if not self.target_offset:
             return
 
-        # Get the position of the microcode
+        # Get the offset of the microcode
         ucode_entry = self.section.FindEntryType('u-boot-ucode')
         if not ucode_entry:
             self.Raise('Cannot find microcode region u-boot-ucode')
 
         # Check the target pos is in the section. If it is not, then U-Boot is
-        # being linked incorrectly, or is being placed at the wrong position
+        # being linked incorrectly, or is being placed at the wrong offset
         # in the section.
         #
         # The section must be set up so that U-Boot is placed at the
         # flash address to which it is linked. For example, if
         # CONFIG_SYS_TEXT_BASE is 0xfff00000, and the ROM is 8MB, then
-        # the U-Boot region must start at position 7MB in the section. In this
-        # case the ROM starts at 0xff800000, so the position of the first
+        # the U-Boot region must start at offset 7MB in the section. In this
+        # case the ROM starts at 0xff800000, so the offset of the first
         # entry in the section corresponds to that.
-        if (self.target_pos < self.pos or
-                self.target_pos >= self.pos + self.size):
+        if (self.target_offset < self.offset or
+                self.target_offset >= self.offset + self.size):
             self.Raise('Microcode pointer _dt_ucode_base_size at %08x is '
                 'outside the section ranging from %08x to %08x' %
-                (self.target_pos, self.pos, self.pos + self.size))
+                (self.target_offset, self.offset, self.offset + self.size))
 
         # Get the microcode, either from u-boot-ucode or u-boot-dtb-with-ucode.
         # If we have left the microcode in the device tree, then it will be
         # in the former. If we extracted the microcode from the device tree
         # and collated it in one place, it will be in the latter.
         if ucode_entry.size:
-            pos, size = ucode_entry.pos, ucode_entry.size
+            offset, size = ucode_entry.offset, ucode_entry.size
         else:
             dtb_entry = self.section.FindEntryType('u-boot-dtb-with-ucode')
             if not dtb_entry or not dtb_entry.ready:
                 self.Raise('Cannot find microcode region u-boot-dtb-with-ucode')
-            pos = dtb_entry.pos + dtb_entry.ucode_offset
+            offset = dtb_entry.offset + dtb_entry.ucode_offset
             size = dtb_entry.ucode_size
 
-        # Write the microcode position and size into the entry
-        pos_and_size = struct.pack('<2L', pos, size)
-        self.target_pos -= self.pos
-        self.ProcessContentsUpdate(self.data[:self.target_pos] + pos_and_size +
-                                   self.data[self.target_pos + 8:])
+        # Write the microcode offset and size into the entry
+        offset_and_size = struct.pack('<2L', offset, size)
+        self.target_offset -= self.offset
+        self.ProcessContentsUpdate(self.data[:self.target_offset] +
+                                   offset_and_size +
+                                   self.data[self.target_offset + 8:])
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py
new file mode 100644 (file)
index 0000000..595af54
--- /dev/null
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+# Support for a Chromium OS verified boot block, used to sign a read-write
+# section of the image.
+
+from collections import OrderedDict
+import os
+
+from entry import Entry, EntryArg
+
+import fdt_util
+import tools
+
+class Entry_vblock(Entry):
+    """An entry which contains a Chromium OS verified boot block
+
+    Properties / Entry arguments:
+        - keydir: Directory containing the public keys to use
+        - keyblock: Name of the key file to use (inside keydir)
+        - signprivate: Name of provide key file to use (inside keydir)
+        - version: Version number of the vblock (typically 1)
+        - kernelkey: Name of the kernel key to use (inside keydir)
+        - preamble-flags: Value of the vboot preamble flags (typically 0)
+
+    Chromium OS signs the read-write firmware and kernel, writing the signature
+    in this block. This allows U-Boot to verify that the next firmware stage
+    and kernel are genuine.
+    """
+    def __init__(self, section, etype, node):
+        Entry.__init__(self, section, etype, node)
+        self.content = fdt_util.GetPhandleList(self._node, 'content')
+        if not self.content:
+            self.Raise("Vblock must have a 'content' property")
+        (self.keydir, self.keyblock, self.signprivate, self.version,
+         self.kernelkey, self.preamble_flags) = self.GetEntryArgsOrProps([
+            EntryArg('keydir', str),
+            EntryArg('keyblock', str),
+            EntryArg('signprivate', str),
+            EntryArg('version', int),
+            EntryArg('kernelkey', str),
+            EntryArg('preamble-flags', int)])
+
+    def ObtainContents(self):
+        # Join up the data files to be signed
+        input_data = ''
+        for entry_phandle in self.content:
+            data = self.section.GetContentsByPhandle(entry_phandle, self)
+            if data is None:
+                # Data not available yet
+                return False
+            input_data += data
+
+        output_fname = tools.GetOutputFilename('vblock.%s' % self.name)
+        input_fname = tools.GetOutputFilename('input.%s' % self.name)
+        tools.WriteFile(input_fname, input_data)
+        prefix = self.keydir + '/'
+        args = [
+            'vbutil_firmware',
+            '--vblock', output_fname,
+            '--keyblock', prefix + self.keyblock,
+            '--signprivate', prefix + self.signprivate,
+            '--version', '%d' % self.version,
+            '--fv', input_fname,
+            '--kernelkey', prefix + self.kernelkey,
+            '--flags', '%d' % self.preamble_flags,
+        ]
+        #out.Notice("Sign '%s' into %s" % (', '.join(self.value), self.label))
+        stdout = tools.Run('futility', *args)
+        #out.Debug(stdout)
+        self.SetContents(tools.ReadFile(output_fname))
+        return True
index 23d27f0704094b8ab6ff361bf9e0a4e35a0f74c7..7d32ecd321b0935d13f6cc38af376f09bebc7d06 100644 (file)
@@ -9,6 +9,20 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_x86_start16(Entry_blob):
+    """x86 16-bit start-up code for U-Boot
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot-x86-16bit.bin (default
+            'u-boot-x86-16bit.bin')
+
+    x86 CPUs start up in 16-bit mode, even if they are 32-bit CPUs. This code
+    must be placed at a particular address. This entry holds that code. It is
+    typically placed at offset CONFIG_SYS_X86_START16. The code is responsible
+    for changing to 32-bit mode and jumping to U-Boot's entry point, which
+    requires 32-bit mode (for 32-bit U-Boot).
+
+    For 64-bit U-Boot, the 'x86_start16_spl' entry type is used instead.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
index 176420ba88cb790a2873bdd7fb4afe5848d5fb4a..d85909e7ae8e7ac765352971e2cb52837cf08262 100644 (file)
@@ -9,6 +9,20 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_x86_start16_spl(Entry_blob):
+    """x86 16-bit start-up code for SPL
+
+    Properties / Entry arguments:
+        - filename: Filename of spl/u-boot-x86-16bit-spl.bin (default
+            'spl/u-boot-x86-16bit-spl.bin')
+
+    x86 CPUs start up in 16-bit mode, even if they are 64-bit CPUs. This code
+    must be placed at a particular address. This entry holds that code. It is
+    typically placed at offset CONFIG_SYS_X86_START16. The code is responsible
+    for changing to 32-bit mode and starting SPL, which in turn changes to
+    64-bit mode and jumps to U-Boot (for 64-bit U-Boot).
+
+    For 32-bit U-Boot, the 'x86_start16' entry type is used instead.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
diff --git a/tools/binman/fmap_util.py b/tools/binman/fmap_util.py
new file mode 100644 (file)
index 0000000..7d520e3
--- /dev/null
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Support for flashrom's FMAP format. This supports a header followed by a
+# number of 'areas', describing regions of a firmware storage device,
+# generally SPI flash.
+
+import collections
+import struct
+
+# constants imported from lib/fmap.h
+FMAP_SIGNATURE = '__FMAP__'
+FMAP_VER_MAJOR = 1
+FMAP_VER_MINOR = 0
+FMAP_STRLEN = 32
+
+FMAP_AREA_STATIC = 1 << 0
+FMAP_AREA_COMPRESSED = 1 << 1
+FMAP_AREA_RO = 1 << 2
+
+FMAP_HEADER_LEN = 56
+FMAP_AREA_LEN = 42
+
+FMAP_HEADER_FORMAT = '<8sBBQI%dsH'% (FMAP_STRLEN)
+FMAP_AREA_FORMAT = '<II%dsH' % (FMAP_STRLEN)
+
+FMAP_HEADER_NAMES = (
+    'signature',
+    'ver_major',
+    'ver_minor',
+    'base',
+    'image_size',
+    'name',
+    'nareas',
+)
+
+FMAP_AREA_NAMES = (
+    'offset',
+    'size',
+    'name',
+    'flags',
+)
+
+# These are the two data structures supported by flashrom, a header (which
+# appears once at the start) and an area (which is repeated until the end of
+# the list of areas)
+FmapHeader = collections.namedtuple('FmapHeader', FMAP_HEADER_NAMES)
+FmapArea = collections.namedtuple('FmapArea', FMAP_AREA_NAMES)
+
+
+def ConvertName(field_names, fields):
+    """Convert a name to something flashrom likes
+
+    Flashrom requires upper case, underscores instead of hyphens. We remove any
+    null characters as well. This updates the 'name' value in fields.
+
+    Args:
+        field_names: List of field names for this struct
+        fields: Dict:
+            key: Field name
+            value: value of that field (string for the ones we support)
+    """
+    name_index = field_names.index('name')
+    fields[name_index] = fields[name_index].replace('\0', '').replace('-', '_').upper()
+
+def DecodeFmap(data):
+    """Decode a flashmap into a header and list of areas
+
+    Args:
+        data: Data block containing the FMAP
+
+    Returns:
+        Tuple:
+            header: FmapHeader object
+            List of FmapArea objects
+    """
+    fields = list(struct.unpack(FMAP_HEADER_FORMAT, data[:FMAP_HEADER_LEN]))
+    ConvertName(FMAP_HEADER_NAMES, fields)
+    header = FmapHeader(*fields)
+    areas = []
+    data = data[FMAP_HEADER_LEN:]
+    for area in range(header.nareas):
+        fields = list(struct.unpack(FMAP_AREA_FORMAT, data[:FMAP_AREA_LEN]))
+        ConvertName(FMAP_AREA_NAMES, fields)
+        areas.append(FmapArea(*fields))
+        data = data[FMAP_AREA_LEN:]
+    return header, areas
+
+def EncodeFmap(image_size, name, areas):
+    """Create a new FMAP from a list of areas
+
+    Args:
+        image_size: Size of image, to put in the header
+        name: Name of image, to put in the header
+        areas: List of FmapArea objects
+
+    Returns:
+        String containing the FMAP created
+    """
+    def _FormatBlob(fmt, names, obj):
+        params = [getattr(obj, name) for name in names]
+        return struct.pack(fmt, *params)
+
+    values = FmapHeader(FMAP_SIGNATURE, 1, 0, 0, image_size, name, len(areas))
+    blob = _FormatBlob(FMAP_HEADER_FORMAT, FMAP_HEADER_NAMES, values)
+    for area in areas:
+        blob += _FormatBlob(FMAP_AREA_FORMAT, FMAP_AREA_NAMES, area)
+    return blob
index 12164a85b4d0c3b58ac780cea436be11b21b3123..a8456c261570a70d37a6238f5883416e0e2ca26f 100644 (file)
@@ -21,6 +21,8 @@ import control
 import elf
 import fdt
 import fdt_util
+import fmap_util
+import test_util
 import tools
 import tout
 
@@ -28,11 +30,13 @@ import tout
 U_BOOT_DATA           = '1234'
 U_BOOT_IMG_DATA       = 'img'
 U_BOOT_SPL_DATA       = '56780123456789abcde'
+U_BOOT_TPL_DATA       = 'tpl'
 BLOB_DATA             = '89'
 ME_DATA               = '0abcd'
 VGA_DATA              = 'vga'
 U_BOOT_DTB_DATA       = 'udtb'
 U_BOOT_SPL_DTB_DATA   = 'spldtb'
+U_BOOT_TPL_DTB_DATA   = 'tpldtb'
 X86_START16_DATA      = 'start16'
 X86_START16_SPL_DATA  = 'start16spl'
 U_BOOT_NODTB_DATA     = 'nodtb with microcode pointer somewhere in here'
@@ -41,6 +45,14 @@ FSP_DATA              = 'fsp'
 CMC_DATA              = 'cmc'
 VBT_DATA              = 'vbt'
 MRC_DATA              = 'mrc'
+TEXT_DATA             = 'text'
+TEXT_DATA2            = 'text2'
+TEXT_DATA3            = 'text3'
+CROS_EC_RW_DATA       = 'ecrw'
+GBB_DATA              = 'gbbd'
+BMPBLK_DATA           = 'bmp'
+VBLOCK_DATA           = 'vblk'
+
 
 class TestFunctional(unittest.TestCase):
     """Functional tests for binman
@@ -72,11 +84,11 @@ class TestFunctional(unittest.TestCase):
         TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
         TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
         TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
+        TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
         TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
         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)
+        self._ResetDtbs()
         TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
         TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
                                       X86_START16_SPL_DATA)
@@ -87,6 +99,9 @@ class TestFunctional(unittest.TestCase):
         TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
         TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
         TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
+        TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
+        TestFunctional._MakeInputDir('devkeys')
+        TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
         self._output_setup = False
 
         # ELF file with a '_dt_ucode_base_size' symbol
@@ -113,6 +128,12 @@ class TestFunctional(unittest.TestCase):
         """Remove the temporary output directory"""
         tools._FinaliseForTest()
 
+    @classmethod
+    def _ResetDtbs(self):
+        TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
+        TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
+        TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
+
     def _RunBinman(self, *args, **kwargs):
         """Run binman using the command line
 
@@ -146,14 +167,15 @@ class TestFunctional(unittest.TestCase):
         # options.verbosity = tout.DEBUG
         return control.Binman(options, args)
 
-    def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False):
+    def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
+                    entry_args=None):
         """Run binman with a given test file
 
         Args:
             fname: Device-tree source filename to use (e.g. 05_simple.dts)
             debug: True to enable debugging output
             map: True to output map files for the images
-            update_dtb: Update the position and size of each entry in the device
+            update_dtb: Update the offset and size of each entry in the device
                 tree before packing it into the image
         """
         args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
@@ -163,6 +185,9 @@ class TestFunctional(unittest.TestCase):
             args.append('-m')
         if update_dtb:
             args.append('-up')
+        if entry_args:
+            for arg, value in entry_args.iteritems():
+                args.append('-a%s=%s' % (arg, value))
         return self._DoBinman(*args)
 
     def _SetupDtb(self, fname, outfile='u-boot.dtb'):
@@ -188,7 +213,7 @@ class TestFunctional(unittest.TestCase):
             return data
 
     def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
-                       update_dtb=False):
+                       update_dtb=False, entry_args=None):
         """Run binman and return the resulting image
 
         This runs binman with a given test file and then reads the resulting
@@ -204,7 +229,7 @@ class TestFunctional(unittest.TestCase):
                 test contents (the U_BOOT_DTB_DATA string) can be used.
                 But in some test we need the real contents.
             map: True to output map files for the images
-            update_dtb: Update the position and size of each entry in the device
+            update_dtb: Update the offset and size of each entry in the device
                 tree before packing it into the image
 
         Returns:
@@ -212,6 +237,7 @@ class TestFunctional(unittest.TestCase):
                 Resulting image contents
                 Device tree contents
                 Map data showing contents of image (or None if none)
+                Output device tree binary filename ('u-boot.dtb' path)
         """
         dtb_data = None
         # Use the compiled test file as the u-boot-dtb input
@@ -219,7 +245,8 @@ class TestFunctional(unittest.TestCase):
             dtb_data = self._SetupDtb(fname)
 
         try:
-            retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb)
+            retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
+                                       entry_args=entry_args)
             self.assertEqual(0, retcode)
             out_dtb_fname = control.GetFdtPath('u-boot.dtb')
 
@@ -238,7 +265,7 @@ class TestFunctional(unittest.TestCase):
         finally:
             # Put the test file back
             if use_real_dtb:
-                TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
+                self._ResetDtbs()
 
     def _DoReadFile(self, fname, use_real_dtb=False):
         """Helper function which discards the device-tree binary
@@ -249,6 +276,9 @@ class TestFunctional(unittest.TestCase):
                 the u-boot-dtb entry. Normally this is not needed and the
                 test contents (the U_BOOT_DTB_DATA string) can be used.
                 But in some test we need the real contents.
+
+        Returns:
+            Resulting image contents
         """
         return self._DoReadFileDtb(fname, use_real_dtb)[0]
 
@@ -257,7 +287,7 @@ class TestFunctional(unittest.TestCase):
         """Create a new test input file, creating directories as needed
 
         Args:
-            fname: Filenaem to create
+            fname: Filename to create
             contents: File contents to write in to the file
         Returns:
             Full pathname of file created
@@ -270,6 +300,21 @@ class TestFunctional(unittest.TestCase):
             fd.write(contents)
         return pathname
 
+    @classmethod
+    def _MakeInputDir(self, dirname):
+        """Create a new test input directory, creating directories as needed
+
+        Args:
+            dirname: Directory name to create
+
+        Returns:
+            Full pathname of directory created
+        """
+        pathname = os.path.join(self._indir, dirname)
+        if not os.path.exists(pathname):
+            os.makedirs(pathname)
+        return pathname
+
     @classmethod
     def TestFile(self, fname):
         return os.path.join(self._binman_dir, 'test', fname)
@@ -292,10 +337,10 @@ class TestFunctional(unittest.TestCase):
         Args:
             entries: List of entries to check
         """
-        pos = 0
+        offset = 0
         for entry in entries.values():
-            self.assertEqual(pos, entry.pos)
-            pos += entry.size
+            self.assertEqual(offset, entry.offset)
+            offset += entry.size
 
     def GetFdtLen(self, dtb):
         """Get the totalsize field from a device-tree binary
@@ -308,23 +353,19 @@ class TestFunctional(unittest.TestCase):
         """
         return struct.unpack('>L', dtb[4:8])[0]
 
-    def _GetPropTree(self, dtb_data, node_names):
+    def _GetPropTree(self, dtb, prop_names):
         def AddNode(node, path):
             if node.name != '/':
                 path += '/' + node.name
-            #print 'path', path
             for subnode in node.subnodes:
                 for prop in subnode.props.values():
-                    if prop.name in node_names:
+                    if prop.name in prop_names:
                         prop_path = path + '/' + subnode.name + ':' + prop.name
                         tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
                             prop.value)
-                    #print '   ', prop.name
                 AddNode(subnode, path)
 
         tree = {}
-        dtb = fdt.Fdt(dtb_data)
-        dtb.Scan()
         AddNode(dtb.GetRoot(), '')
         return tree
 
@@ -409,7 +450,6 @@ class TestFunctional(unittest.TestCase):
         with self.assertRaises(Exception) as e:
             result = self._RunBinman('-d',
                                      self.TestFile('04_invalid_entry.dts'))
-        #print e.exception
         self.assertIn("Unknown entry type 'not-a-valid-type' in node "
                 "'/binman/not-a-valid-type'", str(e.exception))
 
@@ -467,32 +507,32 @@ class TestFunctional(unittest.TestCase):
         # First u-boot
         self.assertIn('u-boot', entries)
         entry = entries['u-boot']
-        self.assertEqual(0, entry.pos)
+        self.assertEqual(0, entry.offset)
         self.assertEqual(len(U_BOOT_DATA), entry.size)
 
         # Second u-boot, aligned to 16-byte boundary
         self.assertIn('u-boot-align', entries)
         entry = entries['u-boot-align']
-        self.assertEqual(16, entry.pos)
+        self.assertEqual(16, entry.offset)
         self.assertEqual(len(U_BOOT_DATA), entry.size)
 
         # Third u-boot, size 23 bytes
         self.assertIn('u-boot-size', entries)
         entry = entries['u-boot-size']
-        self.assertEqual(20, entry.pos)
+        self.assertEqual(20, entry.offset)
         self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
         self.assertEqual(23, entry.size)
 
         # Fourth u-boot, placed immediate after the above
         self.assertIn('u-boot-next', entries)
         entry = entries['u-boot-next']
-        self.assertEqual(43, entry.pos)
+        self.assertEqual(43, entry.offset)
         self.assertEqual(len(U_BOOT_DATA), entry.size)
 
-        # Fifth u-boot, placed at a fixed position
+        # Fifth u-boot, placed at a fixed offset
         self.assertIn('u-boot-fixed', entries)
         entry = entries['u-boot-fixed']
-        self.assertEqual(61, entry.pos)
+        self.assertEqual(61, entry.offset)
         self.assertEqual(len(U_BOOT_DATA), entry.size)
 
         self.assertEqual(65, image._size)
@@ -510,32 +550,32 @@ class TestFunctional(unittest.TestCase):
         # First u-boot with padding before and after
         self.assertIn('u-boot', entries)
         entry = entries['u-boot']
-        self.assertEqual(0, entry.pos)
+        self.assertEqual(0, entry.offset)
         self.assertEqual(3, entry.pad_before)
         self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
 
         # Second u-boot has an aligned size, but it has no effect
         self.assertIn('u-boot-align-size-nop', entries)
         entry = entries['u-boot-align-size-nop']
-        self.assertEqual(12, entry.pos)
+        self.assertEqual(12, entry.offset)
         self.assertEqual(4, entry.size)
 
         # Third u-boot has an aligned size too
         self.assertIn('u-boot-align-size', entries)
         entry = entries['u-boot-align-size']
-        self.assertEqual(16, entry.pos)
+        self.assertEqual(16, entry.offset)
         self.assertEqual(32, entry.size)
 
         # Fourth u-boot has an aligned end
         self.assertIn('u-boot-align-end', entries)
         entry = entries['u-boot-align-end']
-        self.assertEqual(48, entry.pos)
+        self.assertEqual(48, entry.offset)
         self.assertEqual(16, entry.size)
 
         # Fifth u-boot immediately afterwards
         self.assertIn('u-boot-align-both', entries)
         entry = entries['u-boot-align-both']
-        self.assertEqual(64, entry.pos)
+        self.assertEqual(64, entry.offset)
         self.assertEqual(64, entry.size)
 
         self.CheckNoGaps(entries)
@@ -556,10 +596,10 @@ class TestFunctional(unittest.TestCase):
                       "power of two", str(e.exception))
 
     def testPackInvalidAlign(self):
-        """Test detection of an position that does not match its alignment"""
+        """Test detection of an offset that does not match its alignment"""
         with self.assertRaises(ValueError) as e:
             self._DoTestFile('12_pack_inv_align.dts')
-        self.assertIn("Node '/binman/u-boot': Position 0x5 (5) does not match "
+        self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
                       "align 0x4 (4)", str(e.exception))
 
     def testPackInvalidSizeAlign(self):
@@ -573,7 +613,7 @@ class TestFunctional(unittest.TestCase):
         """Test that overlapping regions are detected"""
         with self.assertRaises(ValueError) as e:
             self._DoTestFile('14_pack_overlap.dts')
-        self.assertIn("Node '/binman/u-boot-align': Position 0x3 (3) overlaps "
+        self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
                       "with previous entry '/binman/u-boot' ending at 0x4 (4)",
                       str(e.exception))
 
@@ -651,11 +691,11 @@ class TestFunctional(unittest.TestCase):
         self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
                          U_BOOT_DATA, data)
 
-    def testPackZeroPosition(self):
-        """Test that an entry at position 0 is not given a new position"""
+    def testPackZeroOffset(self):
+        """Test that an entry at offset 0 is not given a new offset"""
         with self.assertRaises(ValueError) as e:
             self._DoTestFile('25_pack_zero_size.dts')
-        self.assertIn("Node '/binman/u-boot-spl': Position 0x0 (0) overlaps "
+        self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
                       "with previous entry '/binman/u-boot' ending at 0x4 (4)",
                       str(e.exception))
 
@@ -672,10 +712,10 @@ class TestFunctional(unittest.TestCase):
                       "using end-at-4gb", str(e.exception))
 
     def testPackX86RomOutside(self):
-        """Test that the end-at-4gb property checks for position boundaries"""
+        """Test that the end-at-4gb property checks for offset boundaries"""
         with self.assertRaises(ValueError) as e:
             self._DoTestFile('28_pack_4gb_outside.dts')
-        self.assertIn("Node '/binman/u-boot': Position 0x0 (0) is outside "
+        self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
                       "the section starting at 0xffffffe0 (4294967264)",
                       str(e.exception))
 
@@ -697,9 +737,9 @@ class TestFunctional(unittest.TestCase):
         """Test that the Intel requires a descriptor entry"""
         with self.assertRaises(ValueError) as e:
             self._DoTestFile('30_x86-rom-me-no-desc.dts')
-        self.assertIn("Node '/binman/intel-me': No position set with "
-                      "pos-unset: should another entry provide this correct "
-                      "position?", str(e.exception))
+        self.assertIn("Node '/binman/intel-me': No offset set with "
+                      "offset-unset: should another entry provide this correct "
+                      "offset?", str(e.exception))
 
     def testPackX86RomMe(self):
         """Test that an x86 ROM with an ME region can be created"""
@@ -728,7 +768,7 @@ class TestFunctional(unittest.TestCase):
         Returns:
             Tuple:
                 Contents of first region (U-Boot or SPL)
-                Position and size components of microcode pointer, as inserted
+                Offset and size components of microcode pointer, as inserted
                     in the above (two 4-byte words)
         """
         data = self._DoReadFile(dts_fname, True)
@@ -761,7 +801,7 @@ class TestFunctional(unittest.TestCase):
         self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
 
         # Check that the microcode pointer was inserted. It should match the
-        # expected position and size
+        # expected offset and size
         pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
                                    len(ucode_data))
         u_boot = data[:len(nodtb_data)]
@@ -806,7 +846,7 @@ class TestFunctional(unittest.TestCase):
         ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
 
         # Check that the microcode pointer was inserted. It should match the
-        # expected position and size
+        # expected offset and size
         pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
                                    len(ucode_data))
         first = data[:len(U_BOOT_NODTB_DATA)]
@@ -890,7 +930,7 @@ class TestFunctional(unittest.TestCase):
         """Test that microcode must be placed within the image"""
         with self.assertRaises(ValueError) as e:
             self._DoReadFile('41_unknown_pos_size.dts', True)
-        self.assertIn("Section '/binman': Unable to set pos/size for unknown "
+        self.assertIn("Section '/binman': Unable to set offset/size for unknown "
                 "entry 'invalid-entry'", str(e.exception))
 
     def testPackFsp(self):
@@ -984,7 +1024,7 @@ class TestFunctional(unittest.TestCase):
         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)
+        self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
 
         with open(self.TestFile('u_boot_binman_syms')) as fd:
             TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
@@ -1003,27 +1043,32 @@ class TestFunctional(unittest.TestCase):
     def testSections(self):
         """Basic test of sections"""
         data = self._DoReadFile('55_sections.dts')
-        expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 + '&' * 8
+        expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
+                    U_BOOT_DATA + '&' * 4)
         self.assertEqual(expected, data)
 
     def testMap(self):
         """Tests outputting a map of the images"""
         _, _, map_data, _ = self._DoReadFileDtb('55_sections.dts', map=True)
-        self.assertEqual('''Position      Size  Name
-00000000  00000010  section@0
- 00000000  00000004  u-boot
-00000010  00000010  section@1
- 00000000  00000004  u-boot
+        self.assertEqual('''ImagePos    Offset      Size  Name
+00000000  00000000  00000028  main-section
+00000000   00000000  00000010  section@0
+00000000    00000000  00000004  u-boot
+00000010   00000010  00000010  section@1
+00000010    00000000  00000004  u-boot
+00000020   00000020  00000004  section@2
+00000020    00000000  00000004  u-boot
 ''', map_data)
 
     def testNamePrefix(self):
         """Tests that name prefixes are used"""
         _, _, map_data, _ = self._DoReadFileDtb('56_name_prefix.dts', map=True)
-        self.assertEqual('''Position      Size  Name
-00000000  00000010  section@0
- 00000000  00000004  ro-u-boot
-00000010  00000010  section@1
- 00000000  00000004  rw-u-boot
+        self.assertEqual('''ImagePos    Offset      Size  Name
+00000000  00000000  00000028  main-section
+00000000   00000000  00000010  section@0
+00000000    00000000  00000004  ro-u-boot
+00000010   00000010  00000010  section@1
+00000010    00000000  00000004  rw-u-boot
 ''', map_data)
 
     def testUnknownContents(self):
@@ -1042,25 +1087,31 @@ class TestFunctional(unittest.TestCase):
                       '2 to 1', str(e.exception))
 
     def testUpdateFdt(self):
-        """Test that we can update the device tree with pos/size info"""
+        """Test that we can update the device tree with offset/size info"""
         _, _, _, out_dtb_fname = self._DoReadFileDtb('60_fdt_update.dts',
                                                      update_dtb=True)
-        props = self._GetPropTree(out_dtb_fname, ['pos', 'size'])
-        with open('/tmp/x.dtb', 'wb') as outf:
-            with open(out_dtb_fname) as inf:
-                outf.write(inf.read())
+        dtb = fdt.Fdt(out_dtb_fname)
+        dtb.Scan()
+        props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
         self.assertEqual({
-            '_testing:pos': 32,
+            'image-pos': 0,
+            'offset': 0,
+            '_testing:offset': 32,
             '_testing:size': 1,
-            'section@0/u-boot:pos': 0,
+            '_testing:image-pos': 32,
+            'section@0/u-boot:offset': 0,
             'section@0/u-boot:size': len(U_BOOT_DATA),
-            'section@0:pos': 0,
+            'section@0/u-boot:image-pos': 0,
+            'section@0:offset': 0,
             'section@0:size': 16,
+            'section@0:image-pos': 0,
 
-            'section@1/u-boot:pos': 0,
+            'section@1/u-boot:offset': 0,
             'section@1/u-boot:size': len(U_BOOT_DATA),
-            'section@1:pos': 16,
+            'section@1/u-boot:image-pos': 16,
+            'section@1:offset': 16,
             'section@1:size': 16,
+            'section@1:image-pos': 16,
             'size': 40
         }, props)
 
@@ -1071,5 +1122,248 @@ class TestFunctional(unittest.TestCase):
         self.assertIn('Could not complete processing of Fdt: remaining '
                       '[<_testing.Entry__testing', str(e.exception))
 
+    def testEntryArgs(self):
+        """Test passing arguments to entries from the command line"""
+        entry_args = {
+            'test-str-arg': 'test1',
+            'test-int-arg': '456',
+        }
+        self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
+        self.assertIn('image', control.images)
+        entry = control.images['image'].GetEntries()['_testing']
+        self.assertEqual('test0', entry.test_str_fdt)
+        self.assertEqual('test1', entry.test_str_arg)
+        self.assertEqual(123, entry.test_int_fdt)
+        self.assertEqual(456, entry.test_int_arg)
+
+    def testEntryArgsMissing(self):
+        """Test missing arguments and properties"""
+        entry_args = {
+            'test-int-arg': '456',
+        }
+        self._DoReadFileDtb('63_entry_args_missing.dts', entry_args=entry_args)
+        entry = control.images['image'].GetEntries()['_testing']
+        self.assertEqual('test0', entry.test_str_fdt)
+        self.assertEqual(None, entry.test_str_arg)
+        self.assertEqual(None, entry.test_int_fdt)
+        self.assertEqual(456, entry.test_int_arg)
+
+    def testEntryArgsRequired(self):
+        """Test missing arguments and properties"""
+        entry_args = {
+            'test-int-arg': '456',
+        }
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFileDtb('64_entry_args_required.dts')
+        self.assertIn("Node '/binman/_testing': Missing required "
+            'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
+            str(e.exception))
+
+    def testEntryArgsInvalidFormat(self):
+        """Test that an invalid entry-argument format is detected"""
+        args = ['-d', self.TestFile('64_entry_args_required.dts'), '-ano-value']
+        with self.assertRaises(ValueError) as e:
+            self._DoBinman(*args)
+        self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
+
+    def testEntryArgsInvalidInteger(self):
+        """Test that an invalid entry-argument integer is detected"""
+        entry_args = {
+            'test-int-arg': 'abc',
+        }
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
+        self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
+                      "'test-int-arg' (value 'abc') to integer",
+            str(e.exception))
+
+    def testEntryArgsInvalidDatatype(self):
+        """Test that an invalid entry-argument datatype is detected
+
+        This test could be written in entry_test.py except that it needs
+        access to control.entry_args, which seems more than that module should
+        be able to see.
+        """
+        entry_args = {
+            'test-bad-datatype-arg': '12',
+        }
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFileDtb('65_entry_args_unknown_datatype.dts',
+                                entry_args=entry_args)
+        self.assertIn('GetArg() internal error: Unknown data type ',
+                      str(e.exception))
+
+    def testText(self):
+        """Test for a text entry type"""
+        entry_args = {
+            'test-id': TEXT_DATA,
+            'test-id2': TEXT_DATA2,
+            'test-id3': TEXT_DATA3,
+        }
+        data, _, _, _ = self._DoReadFileDtb('66_text.dts',
+                                            entry_args=entry_args)
+        expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
+                    TEXT_DATA3 + 'some text')
+        self.assertEqual(expected, data)
+
+    def testEntryDocs(self):
+        """Test for creation of entry documentation"""
+        with test_util.capture_sys_output() as (stdout, stderr):
+            control.WriteEntryDocs(binman.GetEntryModules())
+        self.assertTrue(len(stdout.getvalue()) > 0)
+
+    def testEntryDocsMissing(self):
+        """Test handling of missing entry documentation"""
+        with self.assertRaises(ValueError) as e:
+            with test_util.capture_sys_output() as (stdout, stderr):
+                control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
+        self.assertIn('Documentation is missing for modules: u_boot',
+                      str(e.exception))
+
+    def testFmap(self):
+        """Basic test of generation of a flashrom fmap"""
+        data = self._DoReadFile('67_fmap.dts')
+        fhdr, fentries = fmap_util.DecodeFmap(data[32:])
+        expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
+        self.assertEqual(expected, data[:32])
+        self.assertEqual('__FMAP__', fhdr.signature)
+        self.assertEqual(1, fhdr.ver_major)
+        self.assertEqual(0, fhdr.ver_minor)
+        self.assertEqual(0, fhdr.base)
+        self.assertEqual(16 + 16 +
+                         fmap_util.FMAP_HEADER_LEN +
+                         fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
+        self.assertEqual('FMAP', fhdr.name)
+        self.assertEqual(3, fhdr.nareas)
+        for fentry in fentries:
+            self.assertEqual(0, fentry.flags)
+
+        self.assertEqual(0, fentries[0].offset)
+        self.assertEqual(4, fentries[0].size)
+        self.assertEqual('RO_U_BOOT', fentries[0].name)
+
+        self.assertEqual(16, fentries[1].offset)
+        self.assertEqual(4, fentries[1].size)
+        self.assertEqual('RW_U_BOOT', fentries[1].name)
+
+        self.assertEqual(32, fentries[2].offset)
+        self.assertEqual(fmap_util.FMAP_HEADER_LEN +
+                         fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
+        self.assertEqual('FMAP', fentries[2].name)
+
+    def testBlobNamedByArg(self):
+        """Test we can add a blob with the filename coming from an entry arg"""
+        entry_args = {
+            'cros-ec-rw-path': 'ecrw.bin',
+        }
+        data, _, _, _ = self._DoReadFileDtb('68_blob_named_by_arg.dts',
+                                            entry_args=entry_args)
+
+    def testFill(self):
+        """Test for an fill entry type"""
+        data = self._DoReadFile('69_fill.dts')
+        expected = 8 * chr(0xff) + 8 * chr(0)
+        self.assertEqual(expected, data)
+
+    def testFillNoSize(self):
+        """Test for an fill entry type with no size"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('70_fill_no_size.dts')
+        self.assertIn("'fill' entry must have a size property",
+                      str(e.exception))
+
+    def _HandleGbbCommand(self, pipe_list):
+        """Fake calls to the futility utility"""
+        if pipe_list[0][0] == 'futility':
+            fname = pipe_list[0][-1]
+            # Append our GBB data to the file, which will happen every time the
+            # futility command is called.
+            with open(fname, 'a') as fd:
+                fd.write(GBB_DATA)
+            return command.CommandResult()
+
+    def testGbb(self):
+        """Test for the Chromium OS Google Binary Block"""
+        command.test_result = self._HandleGbbCommand
+        entry_args = {
+            'keydir': 'devkeys',
+            'bmpblk': 'bmpblk.bin',
+        }
+        data, _, _, _ = self._DoReadFileDtb('71_gbb.dts', entry_args=entry_args)
+
+        # Since futility
+        expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
+        self.assertEqual(expected, data)
+
+    def testGbbTooSmall(self):
+        """Test for the Chromium OS Google Binary Block being large enough"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFileDtb('72_gbb_too_small.dts')
+        self.assertIn("Node '/binman/gbb': GBB is too small",
+                      str(e.exception))
+
+    def testGbbNoSize(self):
+        """Test for the Chromium OS Google Binary Block having a size"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFileDtb('73_gbb_no_size.dts')
+        self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
+                      str(e.exception))
+
+    def _HandleVblockCommand(self, pipe_list):
+        """Fake calls to the futility utility"""
+        if pipe_list[0][0] == 'futility':
+            fname = pipe_list[0][3]
+            with open(fname, 'w') as fd:
+                fd.write(VBLOCK_DATA)
+            return command.CommandResult()
+
+    def testVblock(self):
+        """Test for the Chromium OS Verified Boot Block"""
+        command.test_result = self._HandleVblockCommand
+        entry_args = {
+            'keydir': 'devkeys',
+        }
+        data, _, _, _ = self._DoReadFileDtb('74_vblock.dts',
+                                            entry_args=entry_args)
+        expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
+        self.assertEqual(expected, data)
+
+    def testVblockNoContent(self):
+        """Test we detect a vblock which has no content to sign"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('75_vblock_no_content.dts')
+        self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
+                      'property', str(e.exception))
+
+    def testVblockBadPhandle(self):
+        """Test that we detect a vblock with an invalid phandle in contents"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('76_vblock_bad_phandle.dts')
+        self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
+                      '1000', str(e.exception))
+
+    def testVblockBadEntry(self):
+        """Test that we detect an entry that points to a non-entry"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('77_vblock_bad_entry.dts')
+        self.assertIn("Node '/binman/vblock': Cannot find entry for node "
+                      "'other'", str(e.exception))
+
+    def testTpl(self):
+        """Test that an image with TPL and ots device tree can be created"""
+        # ELF file with a '__bss_size' symbol
+        with open(self.TestFile('bss_data')) as fd:
+            TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
+        data = self._DoReadFile('78_u_boot_tpl.dts')
+        self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
+
+    def testUsesPos(self):
+        """Test that the 'pos' property cannot be used anymore"""
+        with self.assertRaises(ValueError) as e:
+           data = self._DoReadFile('79_uses_pos.dts')
+        self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
+                      "'pos'", str(e.exception))
+
+
 if __name__ == "__main__":
     unittest.main()
index 94028f19a513926962640eae08f2eeb9f9fc331b..68126bc3e69ba486f01b103509f6b5867bcc07a7 100644 (file)
@@ -57,7 +57,7 @@ class Image:
     def AddMissingProperties(self):
         """Add properties that are not present in the device tree
 
-        When binman has completed packing the entries the position and size of
+        When binman has completed packing the entries the offset and size of
         each entry are known. But before this the device tree may not specify
         these. Add any missing properties, with a dummy value, so that the
         size of the entry is correct. That way we can insert the correct values
@@ -73,13 +73,13 @@ class Image:
         """
         self._section.GetEntryContents()
 
-    def GetEntryPositions(self):
-        """Handle entries that want to set the position/size of other entries
+    def GetEntryOffsets(self):
+        """Handle entries that want to set the offset/size of other entries
 
-        This calls each entry's GetPositions() method. If it returns a list
+        This calls each entry's GetOffsets() method. If it returns a list
         of entries to update, it updates them.
         """
-        self._section.GetEntryPositions()
+        self._section.GetEntryOffsets()
 
     def PackEntries(self):
         """Pack all entries into the image"""
@@ -96,6 +96,9 @@ class Image:
     def SetCalculatedProperties(self):
         self._section.SetCalculatedProperties()
 
+    def SetImagePos(self):
+        self._section.SetImagePos(0)
+
     def ProcessEntryContents(self):
         """Call the ProcessContents() method for each entry
 
@@ -121,5 +124,6 @@ class Image:
         filename = '%s.map' % self._name
         fname = tools.GetOutputFilename(filename)
         with open(fname, 'w') as fd:
-            print('%8s  %8s  %s' % ('Position', 'Size', 'Name'), file=fd)
+            print('%8s  %8s  %8s  %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
+                  file=fd)
             self._section.WriteMap(fd, 0)
index dc63d99dcb06438d0986c3cba7631f96f45d9b09..a88785d8352f9c2fbf10263681d6873a6b55444f 100644 (file)
@@ -24,7 +24,7 @@
 
                u-boot-fixed {
                        type = "u-boot";
-                       pos = <61>;
+                       offset = <61>;
                };
        };
 };
index 1d9d80a65ccc87cb0b77fdb2607ba8eeeec83cb7..d8dd600edb8ba7997295cae09e81bbe1c32558b8 100644 (file)
@@ -6,7 +6,7 @@
 
        binman {
                u-boot {
-                       pos = <5>;
+                       offset = <5>;
                        align = <4>;
                };
        };
index 611cfd97300597fea016552cc01682a9cdaa0d51..3895cba3bdb7b1577f5536f366cadedbf430341d 100644 (file)
@@ -10,7 +10,7 @@
 
                u-boot-align {
                        type = "u-boot";
-                       pos = <3>;
+                       offset = <3>;
                };
        };
 };
index bf39dc1b6f717397cac2ac98efb6f5375c1a2cec..c6516689d94c95e4e73b09a7c6ea5f7584cc9396 100644 (file)
@@ -10,7 +10,7 @@
                };
 
                u-boot {
-                       pos = <20>;
+                       offset = <20>;
                };
        };
 };
index 43a7831341ca79e44d15ca040c0d3dccc49e0ee5..d35d39f077d9825f3e03fc836512eedc7c8a4019 100644 (file)
@@ -5,13 +5,13 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                u-boot {
-                       pos = <22>;
+                       offset = <22>;
                };
 
                u-boot-spl {
-                       pos = <1>;
+                       offset = <1>;
                };
        };
 };
index 7d2baad3c6d456b1a89ba371de5774e0a00e13f3..e863c44e3fde5ca41709f37f7a9b0aac9440deaf 100644 (file)
@@ -9,7 +9,7 @@
                };
 
                u-boot-spl {
-                       pos = <0>;
+                       offset = <0>;
                };
        };
 };
index e0b6519e75bb7652dd83acb848788ebcb019a103..371cca10d587126bd0ce424eace0c4b5d9c69e72 100644 (file)
@@ -5,14 +5,14 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                u-boot {
-                       pos = <0xfffffff0>;
+                       offset = <0xfffffff0>;
                };
 
                u-boot-spl {
-                       pos = <0xfffffff7>;
+                       offset = <0xfffffff7>;
                };
        };
 };
index 18d6bb5b8af5fc513828e633672f5c3578538239..2216abfb70c1de8a16c297b11a8a99cb6ad01a14 100644 (file)
@@ -5,15 +5,15 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <32>;
                u-boot {
-                       pos = <0>;
+                       offset = <0>;
                };
 
                u-boot-spl {
-                       pos = <0xffffffeb>;
+                       offset = <0xffffffeb>;
                };
        };
 };
index d49078e19e2dfa83de87fc23b82f42718aa55e06..d5c69f9d4a9582608ec69b25e9c66fc8d06c0089 100644 (file)
@@ -5,15 +5,15 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <32>;
                u-boot {
-                       pos = <0xffffffe0>;
+                       offset = <0xffffffe0>;
                };
 
                u-boot-spl {
-                       pos = <0xffffffeb>;
+                       offset = <0xffffffeb>;
                };
        };
 };
index 68d3ce09ecd91084e0be11cb9a361a25453f00e4..796cb87afc7020430321a2e245d4cc95d5aaf155 100644 (file)
@@ -5,12 +5,12 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <16>;
                intel-me {
                        filename = "me.bin";
-                       pos-unset;
+                       offset-unset;
                };
        };
 };
index ee3dac875a613603e7e56a8b6c33338d61db83b0..b8b0a5a74bb18b5c262b1d14ac35581f6b06a046 100644 (file)
@@ -5,7 +5,7 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <0x800000>;
                intel-descriptor {
@@ -14,7 +14,7 @@
 
                intel-me {
                        filename = "me.bin";
-                       pos-unset;
+                       offset-unset;
                };
        };
 };
index 64a6c2c3d5d43f8d60cd3765937f6da21e5853f8..40725731cd3948e304feb6578b1c1e59b4f1dc7e 100644 (file)
@@ -5,7 +5,7 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <0x200>;
                u-boot-with-ucode-ptr {
index 973e97f8641dbe294e6aa7fe096ffb1963b60dac..2b1f086a41c1b7118440f2725fc32dff3d69b183 100644 (file)
@@ -5,7 +5,7 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <0x200>;
                u-boot-with-ucode-ptr {
index 9e12156ee2f07dff507264f178dde1ee2eb5a953..6da49c3da6dacc600fc332e11df532eab6c642f1 100644 (file)
@@ -5,7 +5,7 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <0x200>;
                u-boot-with-ucode-ptr {
index d6cf0d844ed7643c836dd5402ccef676f92b77fc..720677c9c1e9f7a44e40c570bf42a99be6abfc03 100644 (file)
@@ -5,7 +5,7 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <0x200>;
                u-boot-with-ucode-ptr {
index b7e26c5ae4150e17e90c4386d3871038ce859752..10ac086d5493b3593d8989d2c53f27459693f9d1 100644 (file)
@@ -5,7 +5,7 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <0x200>;
                u-boot-with-ucode-ptr {
index 67d17d392fdf305c9da674c4b4c3aa3459a21344..609725824a528c0080956ce0fd38bbedffb80335 100644 (file)
@@ -5,7 +5,7 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                size = <0x200>;
                u-boot-with-ucode-ptr {
                };
index abe1322798ed3b368baf6cf9942c28a15746bea7..24a7040d318365e2dd84af95706cdb8ca14f0253 100644 (file)
@@ -5,7 +5,7 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <0x200>;
                u-boot-with-ucode-ptr {
index d22e460d2998825b4c727bb63afea8ec19f46c08..064de2b3167c52127a7bcfabb36956af957b5b9b 100644 (file)
@@ -5,12 +5,12 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <16>;
                intel-me {
                        filename = "me.bin";
-                       pos-unset;
+                       offset-unset;
                        intval = <3>;
                        intarray = <5 6>;
                        byteval = [08];
index 67db93ad50275451ca15113634d0ef9015ff2413..350d2c4730bb43f51915a99eddfd3c10736fcdd2 100644 (file)
@@ -5,7 +5,7 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <0x200>;
                u-boot-spl-with-ucode-ptr {
index 980b066eb21d4b0b8dfdbc009ac9fdcd162ebab5..9f135676cb0743219a6598b44b43b89e6a3b7ad1 100644 (file)
@@ -10,7 +10,7 @@
                };
 
                u-boot {
-                       pos = <20>;
+                       offset = <20>;
                };
 
                u-boot-spl2 {
index 2ada395b036921ae9dcf8aa22d39dfbc05da58fe..6b306aeda4621c7d60038783376a4e173d07c03c 100644 (file)
@@ -24,5 +24,9 @@
                        u-boot {
                        };
                };
+               section@2 {
+                       u-boot {
+                       };
+               };
        };
 };
index e2cb80cf6e2ecd81c4af61805d50dfcc65b0c885..a04adaaf7ba36cf3e504d52cd7e048f848f9c86d 100644 (file)
@@ -7,7 +7,7 @@
        #size-cells = <1>;
 
        binman {
-               sort-by-pos;
+               sort-by-offset;
                end-at-4gb;
                size = <0x200>;
                u-boot-spl-with-ucode-ptr {
diff --git a/tools/binman/test/62_entry_args.dts b/tools/binman/test/62_entry_args.dts
new file mode 100644 (file)
index 0000000..4d4f102
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               _testing {
+                       test-str-fdt = "test0";
+                       test-int-fdt = <123>;
+               };
+       };
+};
diff --git a/tools/binman/test/63_entry_args_missing.dts b/tools/binman/test/63_entry_args_missing.dts
new file mode 100644 (file)
index 0000000..1644e2f
--- /dev/null
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               _testing {
+                       test-str-fdt = "test0";
+               };
+       };
+};
diff --git a/tools/binman/test/64_entry_args_required.dts b/tools/binman/test/64_entry_args_required.dts
new file mode 100644 (file)
index 0000000..705be10
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               _testing {
+                       require-args;
+                       test-str-fdt = "test0";
+               };
+       };
+};
diff --git a/tools/binman/test/65_entry_args_unknown_datatype.dts b/tools/binman/test/65_entry_args_unknown_datatype.dts
new file mode 100644 (file)
index 0000000..3e4838f
--- /dev/null
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               _testing {
+                       test-str-fdt = "test0";
+                       test-int-fdt = <123>;
+                       force-bad-datatype;
+               };
+       };
+};
diff --git a/tools/binman/test/66_text.dts b/tools/binman/test/66_text.dts
new file mode 100644 (file)
index 0000000..59b1fed
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               text {
+                       size = <8>;
+                       text-label = "test-id";
+               };
+               text2 {
+                       type = "text";
+                       text-label = "test-id2";
+               };
+               text3 {
+                       type = "text";
+                       text-label = "test-id3";
+               };
+               /* This one does not use command-line args */
+               text4 {
+                       type = "text";
+                       text-label = "test-id4";
+                       test-id4 = "some text";
+               };
+       };
+};
diff --git a/tools/binman/test/67_fmap.dts b/tools/binman/test/67_fmap.dts
new file mode 100644 (file)
index 0000000..9c0e293
--- /dev/null
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               section@0 {
+                       read-only;
+                       name-prefix = "ro-";
+                       size = <0x10>;
+                       pad-byte = <0x21>;
+
+                       u-boot {
+                       };
+               };
+               section@1 {
+                       name-prefix = "rw-";
+                       size = <0x10>;
+                       pad-byte = <0x61>;
+
+                       u-boot {
+                       };
+               };
+               fmap {
+               };
+       };
+};
diff --git a/tools/binman/test/68_blob_named_by_arg.dts b/tools/binman/test/68_blob_named_by_arg.dts
new file mode 100644 (file)
index 0000000..e129f84
--- /dev/null
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               cros-ec-rw {
+               };
+       };
+};
diff --git a/tools/binman/test/69_fill.dts b/tools/binman/test/69_fill.dts
new file mode 100644 (file)
index 0000000..e372ea3
--- /dev/null
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               size = <16>;
+               fill {
+                       size = <8>;
+                       fill-byte = [ff];
+               };
+       };
+};
diff --git a/tools/binman/test/70_fill_no_size.dts b/tools/binman/test/70_fill_no_size.dts
new file mode 100644 (file)
index 0000000..7b1fcf1
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               size = <16>;
+               fill {
+                       fill-byte = [ff];
+               };
+       };
+};
diff --git a/tools/binman/test/71_gbb.dts b/tools/binman/test/71_gbb.dts
new file mode 100644 (file)
index 0000000..5517563
--- /dev/null
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               gbb {
+                       size = <0x2180>;
+                       flags {
+                               dev-screen-short-delay;
+                               load-option-roms;
+                               enable-alternate-os;
+                               force-dev-switch-on;
+                               force-dev-boot-usb;
+                               disable-fw-rollback-check;
+                               enter-triggers-tonorm;
+                               force-dev-boot-legacy;
+                               faft-key-override;
+                               disable-ec-software-sync;
+                               default-dev-boot-legacy;
+                               disable-pd-software-sync;
+                               disable-lid-shutdown;
+                               force-dev-boot-fastboot-full-cap;
+                               enable-serial;
+                               disable-dwmp;
+                       };
+               };
+       };
+};
diff --git a/tools/binman/test/72_gbb_too_small.dts b/tools/binman/test/72_gbb_too_small.dts
new file mode 100644 (file)
index 0000000..c088f36
--- /dev/null
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       binman {
+               gbb {
+                       size = <0x200>;
+               };
+       };
+};
diff --git a/tools/binman/test/73_gbb_no_size.dts b/tools/binman/test/73_gbb_no_size.dts
new file mode 100644 (file)
index 0000000..83be403
--- /dev/null
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       binman {
+               gbb {
+               };
+       };
+};
diff --git a/tools/binman/test/74_vblock.dts b/tools/binman/test/74_vblock.dts
new file mode 100644 (file)
index 0000000..f0c21bf
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u_boot: u-boot {
+               };
+
+               vblock {
+                       content = <&u_boot &dtb>;
+                       keyblock = "firmware.keyblock";
+                       signprivate = "firmware_data_key.vbprivk";
+                       version = <1>;
+                       kernelkey = "kernel_subkey.vbpubk";
+                       preamble-flags = <1>;
+               };
+
+               /*
+                * Put this after the vblock so that its contents are not
+                * available when the vblock first tries to obtain its contents
+                */
+               dtb: u-boot-dtb {
+               };
+       };
+};
diff --git a/tools/binman/test/75_vblock_no_content.dts b/tools/binman/test/75_vblock_no_content.dts
new file mode 100644 (file)
index 0000000..676d947
--- /dev/null
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u_boot: u-boot {
+               };
+
+               vblock {
+                       keyblock = "firmware.keyblock";
+                       signprivate = "firmware_data_key.vbprivk";
+                       version = <1>;
+                       kernelkey = "kernel_subkey.vbpubk";
+                       preamble-flags = <1>;
+               };
+
+               dtb: u-boot-dtb {
+               };
+       };
+};
diff --git a/tools/binman/test/76_vblock_bad_phandle.dts b/tools/binman/test/76_vblock_bad_phandle.dts
new file mode 100644 (file)
index 0000000..ffbd0c3
--- /dev/null
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u_boot: u-boot {
+               };
+
+               vblock {
+                       content = <1000>;
+                       keyblock = "firmware.keyblock";
+                       signprivate = "firmware_data_key.vbprivk";
+                       version = <1>;
+                       kernelkey = "kernel_subkey.vbpubk";
+                       preamble-flags = <1>;
+               };
+
+               dtb: u-boot-dtb {
+               };
+       };
+};
diff --git a/tools/binman/test/77_vblock_bad_entry.dts b/tools/binman/test/77_vblock_bad_entry.dts
new file mode 100644 (file)
index 0000000..764c42a
--- /dev/null
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u_boot: u-boot {
+               };
+
+               vblock {
+                       content = <&u_boot &other>;
+                       keyblock = "firmware.keyblock";
+                       signprivate = "firmware_data_key.vbprivk";
+                       version = <1>;
+                       kernelkey = "kernel_subkey.vbpubk";
+                       preamble-flags = <1>;
+               };
+
+               dtb: u-boot-dtb {
+               };
+       };
+
+       other: other {
+       };
+};
diff --git a/tools/binman/test/78_u_boot_tpl.dts b/tools/binman/test/78_u_boot_tpl.dts
new file mode 100644 (file)
index 0000000..6c60b4c
--- /dev/null
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       binman {
+               u-boot-tpl {
+               };
+               u-boot-tpl-dtb {
+               };
+       };
+};
diff --git a/tools/binman/test/79_uses_pos.dts b/tools/binman/test/79_uses_pos.dts
new file mode 100644 (file)
index 0000000..7638b9b
--- /dev/null
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       binman {
+               u-boot {
+                       pos = <10>;
+               };
+       };
+};
index 2e02dc0ca9e2651bc12ac6d61d95dfa5ccee7a68..126a1a623092cbe25f7a24118d26d4a0e8d0e0fc 100755 (executable)
Binary files a/tools/binman/test/u_boot_binman_syms and b/tools/binman/test/u_boot_binman_syms differ
index d8371610a5bf332a8c0ddab449177121c4104623..4898f983e32ceb66564bae80a4b5c6b2a6eadb95 100644 (file)
@@ -8,6 +8,6 @@
 #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);
+binman_sym_declare(unsigned long, u_boot_spl, offset);
+binman_sym_declare(unsigned long long, u_boot_spl2, offset);
+binman_sym_declare(unsigned long, u_boot_any, image_pos);
index 9d69b426c14b9cbe1b1b6c6cacdd57694e10b329..d36179bad360df397955ddaa24113a8bd6697f76 100644 (file)
@@ -181,7 +181,15 @@ class Node:
         self.subnodes = []
         self.props = {}
 
-    def _FindNode(self, name):
+    def GetFdt(self):
+        """Get the Fdt object for this node
+
+        Returns:
+            Fdt object
+        """
+        return self._fdt
+
+    def FindNode(self, name):
         """Find a node given its name
 
         Args:
@@ -314,6 +322,17 @@ class Fdt:
             with open(self._fname) as fd:
                 self._fdt_obj = libfdt.Fdt(fd.read())
 
+    def LookupPhandle(self, phandle):
+        """Look up a phandle
+
+        Args:
+            phandle: Phandle to look up (int)
+
+        Returns:
+            Node object the phandle points to
+        """
+        return self.phandle_to_node.get(phandle)
+
     def Scan(self, root='/'):
         """Scan a device tree, building up a tree of Node objects
 
@@ -349,7 +368,7 @@ class Fdt:
         if len(parts) < 2:
             return None
         for part in parts[1:]:
-            node = node._FindNode(part)
+            node = node.FindNode(part)
             if not node:
                 return None
         return node
index 5b631419a921b323819fa092552140b6aa1fdd5f..5fbfc8877bd31777d2a8b68a45b05c59c0b0fd1d 100644 (file)
@@ -5,6 +5,9 @@
 # Written by Simon Glass <sjg@chromium.org>
 #
 
+# Utility functions for reading from a device tree. Once the upstream pylibfdt
+# implementation advances far enough, we should be able to drop these.
+
 import os
 import struct
 import sys
@@ -90,6 +93,16 @@ def EnsureCompiled(fname, capture_stderr=False):
     return dtb_output
 
 def GetInt(node, propname, default=None):
+    """Get an integer from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+        default: Default value to use if the node/property do not exist
+
+    Returns:
+        Integer value read, or default if none
+    """
     prop = node.props.get(propname)
     if not prop:
         return default
@@ -100,6 +113,16 @@ def GetInt(node, propname, default=None):
     return value
 
 def GetString(node, propname, default=None):
+    """Get a string from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+        default: Default value to use if the node/property do not exist
+
+    Returns:
+        String value read, or default if none
+    """
     prop = node.props.get(propname)
     if not prop:
         return default
@@ -110,6 +133,79 @@ def GetString(node, propname, default=None):
     return value
 
 def GetBool(node, propname, default=False):
+    """Get an boolean from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+        default: Default value to use if the node/property do not exist
+
+    Returns:
+        Boolean value read, or default if none (if you set this to True the
+            function will always return True)
+    """
     if propname in node.props:
         return True
     return default
+
+def GetByte(node, propname, default=None):
+    """Get an byte from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+        default: Default value to use if the node/property do not exist
+
+    Returns:
+        Byte value read, or default if none
+    """
+    prop = node.props.get(propname)
+    if not prop:
+        return default
+    value = prop.value
+    if isinstance(value, list):
+        raise ValueError("Node '%s' property '%s' has list value: expecting "
+                         "a single byte" % (node.name, propname))
+    if len(value) != 1:
+        raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
+                         (node.name, propname, len(value), 1))
+    return ord(value[0])
+
+def GetPhandleList(node, propname):
+    """Get a list of phandles from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+
+    Returns:
+        List of phandles read, each an integer
+    """
+    prop = node.props.get(propname)
+    if not prop:
+        return None
+    value = prop.value
+    if not isinstance(value, list):
+        value = [value]
+    return [fdt32_to_cpu(v) for v in value]
+
+def GetDatatype(node, propname, datatype):
+    """Get a value of a given type from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+        datatype: Type to read (str or int)
+
+    Returns:
+        value read, or None if none
+
+    Raises:
+        ValueError if datatype is not str or int
+    """
+    if datatype == str:
+        return GetString(node, propname)
+    elif datatype == int:
+        return GetInt(node, propname)
+    raise ValueError("fdt_util internal error: Unknown data type '%s'" %
+                     datatype)
index f085b1dd1a9f65d85a78ce1c1358295042f74908..6fe03ac53d03352c85ad8f10c8b32bce19bf1151 100755 (executable)
@@ -115,6 +115,9 @@ class TestFdt(unittest.TestCase):
             fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
         self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
 
+    def testGetFdt(self):
+        node = self.dtb.GetNode('/spl-test')
+        self.assertEqual(self.dtb, node.GetFdt())
 
 class TestNode(unittest.TestCase):
     """Test operation of the Node class"""
@@ -155,12 +158,12 @@ class TestNode(unittest.TestCase):
         self.assertEqual(prop.value, value)
 
     def testFindNode(self):
-        """Tests that we can find a node using the _FindNode() functoin"""
-        node = self.dtb.GetRoot()._FindNode('i2c@0')
+        """Tests that we can find a node using the FindNode() functoin"""
+        node = self.dtb.GetRoot().FindNode('i2c@0')
         self.assertEqual('i2c@0', node.name)
-        subnode = node._FindNode('pmic@9')
+        subnode = node.FindNode('pmic@9')
         self.assertEqual('pmic@9', subnode.name)
-        self.assertEqual(None, node._FindNode('missing'))
+        self.assertEqual(None, node.FindNode('missing'))
 
     def testRefreshMissingNode(self):
         """Test refreshing offsets when an extra node is present in dtb"""
@@ -188,6 +191,14 @@ class TestNode(unittest.TestCase):
         self.assertIn("Internal error, property 'notstring' missing, offset ",
                       str(e.exception))
 
+    def testLookupPhandle(self):
+        """Test looking up a single phandle"""
+        dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+        node = dtb.GetNode('/phandle-source2')
+        prop = node.props['clocks']
+        target = dtb.GetNode('/phandle-target')
+        self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
+
 
 class TestProp(unittest.TestCase):
     """Test operation of the Prop class"""
@@ -380,6 +391,36 @@ class TestFdtUtil(unittest.TestCase):
         self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
         self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
 
+    def testGetByte(self):
+        self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
+        self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
+
+        with self.assertRaises(ValueError) as e:
+            fdt_util.GetByte(self.node, 'longbytearray')
+        self.assertIn("property 'longbytearray' has list value: expecting a "
+                      'single byte', str(e.exception))
+
+        with self.assertRaises(ValueError) as e:
+            fdt_util.GetByte(self.node, 'intval')
+        self.assertIn("property 'intval' has length 4, expecting 1",
+                      str(e.exception))
+
+    def testGetPhandleList(self):
+        dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+        node = dtb.GetNode('/phandle-source2')
+        self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
+        node = dtb.GetNode('/phandle-source')
+        self.assertEqual([1, 2, 11, 3, 12, 13, 1],
+                         fdt_util.GetPhandleList(node, 'clocks'))
+        self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
+
+    def testGetDataType(self):
+        self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
+        self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
+                                                         str))
+        with self.assertRaises(ValueError) as e:
+            self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
+                                                     bool))
     def testFdtCellsToCpu(self):
         val = self.node.props['intarray'].value
         self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
index 598bfdcd90b6d2e3995db2f6fce9011ce2335c2d..14edcdaffd29cdc566ea8c70865443dac50170b3 100644 (file)
@@ -61,8 +61,12 @@ def RunPipe(pipe_list, infile=None, outfile=None,
     """
     if test_result:
         if hasattr(test_result, '__call__'):
-            return test_result(pipe_list=pipe_list)
-        return test_result
+            result = test_result(pipe_list=pipe_list)
+            if result:
+                return result
+        else:
+            return test_result
+        # No result: fall through to normal processing
     result = CommandResult()
     last_pipe = None
     pipeline = list(pipe_list)
index 700cb4505d41c498458037c78aa7edcd1a052443..e80481438b547b8dc9b2a80964e41d7232d7a5cd 100644 (file)
@@ -3,16 +3,26 @@
 # Copyright (c) 2016 Google, Inc
 #
 
+import command
 import os
 import shutil
 import tempfile
 
 import tout
 
+# Output directly (generally this is temporary)
 outdir = None
-indirs = None
+
+# True to keep the output directory around after exiting
 preserve_outdir = False
 
+# Path to the Chrome OS chroot, if we know it
+chroot_path = None
+
+# Search paths to use for Filename(), used to find files
+search_paths = []
+
+
 def PrepareOutputDir(dirname, preserve=False):
     """Select an output directory, ensuring it exists.
 
@@ -106,8 +116,8 @@ def GetInputFilename(fname):
         if os.path.exists(pathname):
             return pathname
 
-    raise ValueError("Filename '%s' not found in input path (%s)" %
-                     (fname, ','.join(indir)))
+    raise ValueError("Filename '%s' not found in input path (%s) (cwd='%s')" %
+                     (fname, ','.join(indir), os.getcwd()))
 
 def Align(pos, align):
     if align:
@@ -117,3 +127,67 @@ def Align(pos, align):
 
 def NotPowerOfTwo(num):
     return num and (num & (num - 1))
+
+def Run(name, *args):
+    command.Run(name, *args, cwd=outdir)
+
+def Filename(fname):
+    """Resolve a file path to an absolute path.
+
+    If fname starts with ##/ and chroot is available, ##/ gets replaced with
+    the chroot path. If chroot is not available, this file name can not be
+    resolved, `None' is returned.
+
+    If fname is not prepended with the above prefix, and is not an existing
+    file, the actual file name is retrieved from the passed in string and the
+    search_paths directories (if any) are searched to for the file. If found -
+    the path to the found file is returned, `None' is returned otherwise.
+
+    Args:
+      fname: a string,  the path to resolve.
+
+    Returns:
+      Absolute path to the file or None if not found.
+    """
+    if fname.startswith('##/'):
+      if chroot_path:
+        fname = os.path.join(chroot_path, fname[3:])
+      else:
+        return None
+
+    # Search for a pathname that exists, and return it if found
+    if fname and not os.path.exists(fname):
+        for path in search_paths:
+            pathname = os.path.join(path, os.path.basename(fname))
+            if os.path.exists(pathname):
+                return pathname
+
+    # If not found, just return the standard, unchanged path
+    return fname
+
+def ReadFile(fname):
+    """Read and return the contents of a file.
+
+    Args:
+      fname: path to filename to read, where ## signifiies the chroot.
+
+    Returns:
+      data read from file, as a string.
+    """
+    with open(Filename(fname), 'rb') as fd:
+        data = fd.read()
+    #self._out.Info("Read file '%s' size %d (%#0x)" %
+                   #(fname, len(data), len(data)))
+    return data
+
+def WriteFile(fname, data):
+    """Write data into a file.
+
+    Args:
+        fname: path to filename to write
+        data: data to write to file, as a string
+    """
+    #self._out.Info("Write file '%s' size %d (%#0x)" %
+                   #(fname, len(data), len(data)))
+    with open(Filename(fname), 'wb') as fd:
+        fd.write(data)