Merge branch 'next'
authorTom Rini <trini@konsulko.com>
Mon, 5 Apr 2021 15:29:57 +0000 (11:29 -0400)
committerTom Rini <trini@konsulko.com>
Mon, 5 Apr 2021 15:29:57 +0000 (11:29 -0400)
659 files changed:
.azure-pipelines.yml
.gitlab-ci.yml
Makefile
arch/Kconfig
arch/arc/lib/reset.c
arch/arm/cpu/arm920t/ep93xx/cpu.c
arch/arm/cpu/arm920t/imx/timer.c
arch/arm/cpu/arm926ejs/armada100/timer.c
arch/arm/cpu/arm926ejs/mx25/reset.c
arch/arm/cpu/arm926ejs/mx27/reset.c
arch/arm/cpu/arm926ejs/mxs/mxs.c
arch/arm/cpu/arm926ejs/spear/reset.c
arch/arm/cpu/arm946es/cpu.c
arch/arm/cpu/armv7/bcm281xx/reset.c
arch/arm/cpu/armv7/bcmcygnus/reset.c
arch/arm/cpu/armv7/bcmnsp/reset.c
arch/arm/cpu/armv7/cache_v7.c
arch/arm/cpu/armv7/ls102xa/cpu.c
arch/arm/cpu/armv7/s5p4418/cpu.c
arch/arm/cpu/armv7/stv0991/reset.c
arch/arm/cpu/armv7m/cpu.c
arch/arm/cpu/armv8/fsl-layerscape/cpu.c
arch/arm/cpu/armv8/s32v234/generic.c
arch/arm/cpu/pxa/pxa2xx.c
arch/arm/cpu/sa1100/cpu.c
arch/arm/dts/Makefile
arch/arm/dts/bitmain-antminer-s9.dts
arch/arm/dts/cat875.dtsi [new file with mode: 0644]
arch/arm/dts/mt7629-rfb-u-boot.dtsi
arch/arm/dts/mt7629-rfb.dts
arch/arm/dts/mt7629.dtsi
arch/arm/dts/mt8183-pumpkin.dts [new file with mode: 0644]
arch/arm/dts/mt8183.dtsi [new file with mode: 0644]
arch/arm/dts/r8a774b1-hihope-rzg2n-ex.dts [new file with mode: 0644]
arch/arm/dts/r8a774b1-hihope-rzg2n-u-boot.dts [new file with mode: 0644]
arch/arm/dts/r8a774b1-hihope-rzg2n.dts [new file with mode: 0644]
arch/arm/dts/r8a774b1-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/r8a774c0-cat874.dts [new file with mode: 0644]
arch/arm/dts/r8a774c0-ek874-u-boot.dts [new file with mode: 0644]
arch/arm/dts/r8a774c0-ek874.dts [new file with mode: 0644]
arch/arm/dts/r8a774c0-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/r8a774c0.dtsi
arch/arm/dts/r8a774e1-hihope-rzg2h-ex.dts [new file with mode: 0644]
arch/arm/dts/r8a774e1-hihope-rzg2h-u-boot.dts [new file with mode: 0644]
arch/arm/dts/r8a774e1-hihope-rzg2h.dts [new file with mode: 0644]
arch/arm/dts/r8a774e1-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/zynq-zc702.dts
arch/arm/dts/zynq-zturn-common.dtsi
arch/arm/dts/zynq-zybo-z7.dts
arch/arm/dts/zynqmp-clk-ccf.dtsi
arch/arm/dts/zynqmp-g-a2197-00-revA.dts
arch/arm/dts/zynqmp-m-a2197-01-revA.dts
arch/arm/dts/zynqmp-mini-emmc0.dts
arch/arm/dts/zynqmp-mini-emmc1.dts
arch/arm/dts/zynqmp-zc1232-revA.dts
arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts
arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts
arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts
arch/arm/dts/zynqmp-zcu100-revC.dts
arch/arm/dts/zynqmp-zcu102-revA.dts
arch/arm/dts/zynqmp-zcu104-revA.dts
arch/arm/dts/zynqmp-zcu104-revC.dts
arch/arm/dts/zynqmp-zcu106-revA.dts
arch/arm/dts/zynqmp-zcu111-revA.dts
arch/arm/dts/zynqmp-zcu208-revA.dts
arch/arm/dts/zynqmp-zcu216-revA.dts
arch/arm/dts/zynqmp.dtsi
arch/arm/include/asm/cache.h
arch/arm/include/asm/system.h
arch/arm/lib/cache-cp15.c
arch/arm/lib/interrupts.c
arch/arm/lib/interrupts_m.c
arch/arm/lib/reset.c
arch/arm/mach-at91/arm920t/reset.c
arch/arm/mach-at91/arm926ejs/lowlevel_init.S
arch/arm/mach-at91/arm926ejs/reset.c
arch/arm/mach-at91/armv7/reset.c
arch/arm/mach-at91/include/mach/atmel_pio4.h
arch/arm/mach-bcm283x/reset.c
arch/arm/mach-davinci/reset.c
arch/arm/mach-exynos/soc.c
arch/arm/mach-imx/imx8m/soc.c
arch/arm/mach-imx/mx7ulp/soc.c
arch/arm/mach-k3/common.c
arch/arm/mach-keystone/ddr3.c
arch/arm/mach-keystone/init.c
arch/arm/mach-kirkwood/cpu.c
arch/arm/mach-lpc32xx/cpu.c
arch/arm/mach-mediatek/Kconfig
arch/arm/mach-mediatek/Makefile
arch/arm/mach-mediatek/mt7622/init.c
arch/arm/mach-mediatek/mt8183/Makefile [moved from board/mediatek/pumpkin/Makefile with 65% similarity]
arch/arm/mach-mediatek/mt8183/init.c [new file with mode: 0644]
arch/arm/mach-mediatek/mt8512/init.c
arch/arm/mach-mediatek/mt8516/init.c
arch/arm/mach-mediatek/mt8518/init.c
arch/arm/mach-meson/board-common.c
arch/arm/mach-mvebu/armada3700/cpu.c
arch/arm/mach-mvebu/armada8k/cpu.c
arch/arm/mach-mvebu/cpu.c
arch/arm/mach-nexell/Makefile
arch/arm/mach-nexell/cmd_boot_linux.c [deleted file]
arch/arm/mach-octeontx/cpu.c
arch/arm/mach-octeontx2/cpu.c
arch/arm/mach-omap2/omap-cache.c
arch/arm/mach-omap2/omap5/hwinit.c
arch/arm/mach-omap2/reset.c
arch/arm/mach-orion5x/cpu.c
arch/arm/mach-owl/soc.c
arch/arm/mach-rmobile/Kconfig.64
arch/arm/mach-rmobile/Makefile
arch/arm/mach-socfpga/include/mach/reset_manager.h
arch/arm/mach-stm32mp/cpu.c
arch/arm/mach-stm32mp/dram_init.c
arch/arm/mach-sunxi/Kconfig
arch/arm/mach-sunxi/board.c
arch/arm/mach-tegra/cmd_enterrcm.c
arch/arm/mach-tegra/pmc.c
arch/arm/mach-uniphier/arm32/psci.c
arch/arm/mach-uniphier/reset.c
arch/arm/mach-zynq/cpu.c
arch/arm/mach-zynqmp-r5/cpu.c
arch/nds32/cpu/n1213/ag101/cpu.c
arch/nds32/cpu/n1213/start.S
arch/nds32/lib/interrupts.c
arch/riscv/cpu/ax25/Kconfig
arch/riscv/cpu/fu540/Kconfig
arch/riscv/cpu/generic/Kconfig
arch/sandbox/cpu/cpu.c
arch/sandbox/cpu/os.c
arch/sandbox/cpu/sdl.c
arch/sandbox/cpu/spl.c
arch/sandbox/cpu/start.c
arch/sandbox/cpu/state.c
arch/sandbox/cpu/u-boot-spl.lds
arch/sandbox/cpu/u-boot.lds
arch/sandbox/dts/sandbox.dtsi
arch/sandbox/dts/test.dts
arch/sandbox/include/asm/clk.h
arch/sandbox/include/asm/gpio.h
arch/sandbox/include/asm/i2c.h
arch/sandbox/include/asm/rtc.h
arch/sh/cpu/sh4/cpu.c
arch/sh/cpu/sh4/watchdog.c
arch/x86/Kconfig
arch/x86/cpu/apollolake/Kconfig
arch/x86/cpu/apollolake/cpu.c
arch/x86/cpu/apollolake/cpu_common.c
arch/x86/cpu/apollolake/cpu_spl.c
arch/x86/cpu/apollolake/pmc.c
arch/x86/cpu/apollolake/punit.c
arch/x86/cpu/coreboot/Makefile
arch/x86/cpu/coreboot/coreboot.c
arch/x86/cpu/coreboot/sdram.c
arch/x86/cpu/coreboot/tables.c [deleted file]
arch/x86/cpu/coreboot/timestamp.c
arch/x86/cpu/intel_common/itss.c
arch/x86/cpu/ivybridge/cpu.c
arch/x86/cpu/start_from_spl.S
arch/x86/cpu/u-boot-spl.lds
arch/x86/dts/chromebook_coral.dts
arch/x86/dts/reset.dtsi
arch/x86/dts/u-boot.dtsi
arch/x86/include/asm/arch-apollolake/uart.h
arch/x86/include/asm/arch-coreboot/sysinfo.h [deleted file]
arch/x86/include/asm/arch-coreboot/timestamp.h
arch/x86/include/asm/cb_sysinfo.h [new file with mode: 0644]
arch/x86/include/asm/coreboot_tables.h
arch/x86/include/asm/e820.h
arch/x86/include/asm/intel_pinctrl_defs.h
arch/x86/lib/Makefile
arch/x86/lib/bootm.c
arch/x86/lib/coreboot/Makefile [new file with mode: 0644]
arch/x86/lib/coreboot/cb_support.c [new file with mode: 0644]
arch/x86/lib/coreboot/cb_sysinfo.c [new file with mode: 0644]
arch/x86/lib/fsp/fsp_graphics.c
arch/x86/lib/fsp2/fsp_init.c
arch/x86/lib/fsp2/fsp_support.c
arch/x86/lib/init_helpers.c
arch/x86/lib/spl.c
arch/x86/lib/tpl.c
arch/x86/lib/zimage.c
board/BuR/brppt2/board.c
board/abilis/tb100/tb100.c
board/advantech/imx8qm_rom7720_a1/imx8qm_rom7720_a1.c
board/armltd/total_compute/total_compute.c
board/armltd/vexpress/vexpress_common.c
board/armltd/vexpress64/vexpress64.c
board/atmark-techno/armadillo-800eva/armadillo-800eva.c
board/beacon/beacon-rzg2m/beacon-rzg2m.c
board/bosch/shc/board.c
board/broadcom/bcmns2/northstar2.c
board/broadcom/bcmns3/ns3.c
board/broadcom/bcmstb/bcmstb.c
board/cavium/thunderx/thunderx.c
board/compulab/cm_t335/spl.c
board/coreboot/coreboot/coreboot.c
board/cortina/presidio-asic/presidio.c
board/freescale/imx8qm_mek/imx8qm_mek.c
board/freescale/imx8qxp_mek/imx8qxp_mek.c
board/freescale/mx6memcal/spl.c
board/gdsys/a38x/controlcenterdc.c
board/gdsys/a38x/hre.c
board/gdsys/a38x/keyprogram.c
board/gdsys/mpc8308/gazerbeam.c
board/gdsys/p1022/controlcenterd-id.c
board/ge/b1x5v2/spl.c
board/google/chromebook_coral/coral.c
board/google/chromebook_coral/variant_gpio.h
board/highbank/highbank.c
board/hisilicon/hikey/hikey.c
board/hisilicon/hikey960/hikey960.c
board/hisilicon/poplar/poplar.c
board/hoperun/hihope-rzg2/Kconfig [new file with mode: 0644]
board/hoperun/hihope-rzg2/MAINTAINERS [new file with mode: 0644]
board/hoperun/hihope-rzg2/Makefile [new file with mode: 0644]
board/hoperun/hihope-rzg2/hihope-rzg2.c [new file with mode: 0644]
board/kmc/kzm9g/kzm9g.c
board/liebherr/display5/spl.c
board/mediatek/mt8183/Kconfig [new file with mode: 0644]
board/mediatek/mt8183/MAINTAINERS [new file with mode: 0644]
board/mediatek/mt8183/Makefile [new file with mode: 0644]
board/mediatek/mt8183/mt8183_pumpkin.c [new file with mode: 0644]
board/mediatek/mt8516/Kconfig [moved from board/mediatek/pumpkin/Kconfig with 76% similarity]
board/mediatek/mt8516/MAINTAINERS [new file with mode: 0644]
board/mediatek/mt8516/Makefile [new file with mode: 0644]
board/mediatek/mt8516/mt8516_pumpkin.c [moved from board/mediatek/pumpkin/pumpkin.c with 85% similarity]
board/mediatek/pumpkin/MAINTAINERS [deleted file]
board/phytium/durian/durian.c
board/qualcomm/dragonboard410c/dragonboard410c.c
board/qualcomm/dragonboard820c/dragonboard820c.c
board/renesas/alt/alt.c
board/renesas/alt/alt_spl.c
board/renesas/blanche/blanche.c
board/renesas/condor/condor.c
board/renesas/draak/draak.c
board/renesas/eagle/eagle.c
board/renesas/ebisu/ebisu.c
board/renesas/gose/gose.c
board/renesas/gose/gose_spl.c
board/renesas/grpeach/grpeach.c
board/renesas/koelsch/koelsch.c
board/renesas/koelsch/koelsch_spl.c
board/renesas/lager/lager.c
board/renesas/lager/lager_spl.c
board/renesas/porter/porter.c
board/renesas/porter/porter_spl.c
board/renesas/rcar-common/gen3-spl.c
board/renesas/salvator-x/salvator-x.c
board/renesas/silk/silk.c
board/renesas/silk/silk_spl.c
board/renesas/stout/cpld.c
board/renesas/stout/stout_spl.c
board/sandbox/MAINTAINERS
board/sandbox/sandbox.c
board/siemens/capricorn/board.c
board/silinux/ek874/Kconfig [new file with mode: 0644]
board/silinux/ek874/MAINTAINERS [new file with mode: 0644]
board/silinux/ek874/Makefile [new file with mode: 0644]
board/silinux/ek874/ek874.c [new file with mode: 0644]
board/synopsys/emsdp/emsdp.c
board/synopsys/iot_devkit/iot_devkit.c
board/technexion/pico-imx6ul/spl.c
board/technexion/pico-imx7d/spl.c
board/toradex/apalis-imx8/apalis-imx8.c
board/toradex/apalis-imx8x/apalis-imx8x.c
board/toradex/apalis_imx6/apalis_imx6.c
board/toradex/colibri-imx8x/colibri-imx8x.c
board/toradex/colibri_imx6/colibri_imx6.c
board/toradex/colibri_imx7/colibri_imx7.c
board/xen/xenguest_arm64/xenguest_arm64.c
board/xilinx/versal/board.c
board/xilinx/zynqmp/zynqmp-zcu1275-revB/psu_init_gpl.c
board/xilinx/zynqmp/zynqmp-zcu208-revA/psu_init_gpl.c [new file with mode: 0644]
board/xilinx/zynqmp/zynqmp-zcu216-revA/psu_init_gpl.c [new file with mode: 0644]
board/xilinx/zynqmp/zynqmp.c
cmd/Kconfig
cmd/Makefile
cmd/acpi.c
cmd/bloblist.c
cmd/bootefi.c
cmd/efidebug.c
cmd/host.c
cmd/scp03.c [new file with mode: 0644]
cmd/tpm-v1.c
cmd/tpm_test.c
cmd/version.c
cmd/x86/Makefile
cmd/x86/cbsysinfo.c [new file with mode: 0644]
common/Kconfig
common/Makefile
common/board_info.c
common/bootm.c
common/bootstage.c
common/image-fit.c
common/log.c
common/log_console.c
common/scp03.c [new file with mode: 0644]
common/spl/Kconfig
common/spl/spl.c
common/spl/spl_fit.c
configs/bitmain_antminer_s9_defconfig
configs/chromebook_coral_defconfig
configs/chromebook_link64_defconfig
configs/hihope_rzg2_defconfig [new file with mode: 0644]
configs/mt7622_rfb_defconfig
configs/mt7629_rfb_defconfig
configs/mt8183_pumpkin_defconfig [new file with mode: 0644]
configs/mt8516_pumpkin_defconfig [moved from configs/pumpkin_defconfig with 100% similarity]
configs/qemu-x86_64_defconfig
configs/sandbox_noinst_defconfig [new file with mode: 0644]
configs/sandbox_spl_defconfig
configs/silinux_ek874_defconfig [new file with mode: 0644]
configs/xilinx_versal_virt_defconfig
configs/xilinx_zynq_virt_defconfig
configs/xilinx_zynqmp_mini_emmc0_defconfig
configs/xilinx_zynqmp_mini_emmc1_defconfig
configs/xilinx_zynqmp_virt_defconfig
doc/Makefile
doc/arch/sandbox.rst
doc/arch/x86.rst
doc/board/emulation/qemu_capsule_update.rst
doc/board/google/chromebook_coral.rst
doc/chromium/chainload.rst [moved from doc/README.chromium-chainload with 79% similarity]
doc/chromium/files/chromebook_jerry.its [moved from doc/chromium/chromebook_jerry.its with 100% similarity]
doc/chromium/files/devkeys/kernel.keyblock [moved from doc/chromium/devkeys/kernel.keyblock with 100% similarity]
doc/chromium/files/devkeys/kernel_data_key.vbprivk [moved from doc/chromium/devkeys/kernel_data_key.vbprivk with 100% similarity]
doc/chromium/files/nyan-big.its [moved from doc/chromium/nyan-big.its with 100% similarity]
doc/chromium/index.rst [new file with mode: 0644]
doc/chromium/overview.rst [new file with mode: 0644]
doc/chromium/run_vboot.rst [moved from doc/README.chromium with 68% similarity]
doc/develop/driver-model/bind.rst [moved from doc/driver-model/bind.rst with 100% similarity]
doc/develop/driver-model/debugging.rst [moved from doc/driver-model/debugging.rst with 100% similarity]
doc/develop/driver-model/design.rst [moved from doc/driver-model/design.rst with 100% similarity]
doc/develop/driver-model/ethernet.rst [moved from doc/driver-model/ethernet.rst with 100% similarity]
doc/develop/driver-model/fdt-fixup.rst [moved from doc/driver-model/fdt-fixup.rst with 100% similarity]
doc/develop/driver-model/fs_firmware_loader.rst [moved from doc/driver-model/fs_firmware_loader.rst with 100% similarity]
doc/develop/driver-model/i2c-howto.rst [moved from doc/driver-model/i2c-howto.rst with 100% similarity]
doc/develop/driver-model/index.rst [moved from doc/driver-model/index.rst with 68% similarity]
doc/develop/driver-model/livetree.rst [moved from doc/driver-model/livetree.rst with 100% similarity]
doc/develop/driver-model/migration.rst [moved from doc/driver-model/migration.rst with 100% similarity]
doc/develop/driver-model/of-plat.rst [new file with mode: 0644]
doc/develop/driver-model/pci-info.rst [moved from doc/driver-model/pci-info.rst with 99% similarity]
doc/develop/driver-model/pmic-framework.rst [moved from doc/driver-model/pmic-framework.rst with 100% similarity]
doc/develop/driver-model/remoteproc-framework.rst [moved from doc/driver-model/remoteproc-framework.rst with 100% similarity]
doc/develop/driver-model/serial-howto.rst [moved from doc/driver-model/serial-howto.rst with 100% similarity]
doc/develop/driver-model/soc-framework.rst [moved from doc/driver-model/soc-framework.rst with 100% similarity]
doc/develop/driver-model/spi-howto.rst [moved from doc/driver-model/spi-howto.rst with 100% similarity]
doc/develop/driver-model/usb-info.rst [moved from doc/driver-model/usb-info.rst with 100% similarity]
doc/develop/index.rst
doc/develop/logging.rst
doc/develop/package/binman.rst [new symlink]
doc/develop/package/entries.rst [new symlink]
doc/develop/package/index.rst [new file with mode: 0644]
doc/develop/py_testing.rst
doc/develop/testing.rst
doc/develop/tests_sandbox.rst [new file with mode: 0644]
doc/develop/tests_writing.rst [new file with mode: 0644]
doc/develop/uefi/index.rst [moved from doc/uefi/index.rst with 51% similarity]
doc/develop/uefi/iscsi.rst [moved from doc/uefi/iscsi.rst with 100% similarity]
doc/develop/uefi/u-boot_on_efi.rst [moved from doc/uefi/u-boot_on_efi.rst with 100% similarity]
doc/develop/uefi/uefi.rst [moved from doc/uefi/uefi.rst with 99% similarity]
doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
doc/device-tree-bindings/sysinfo/google,coral.txt [new file with mode: 0644]
doc/driver-model/of-plat.rst [deleted file]
doc/index.rst
doc/usage/fit.rst [new file with mode: 0644]
doc/usage/index.rst
doc/usage/md.rst [new file with mode: 0644]
doc/usage/scp03.rst [new file with mode: 0644]
doc/usage/x86/cbsysinfo.rst [new file with mode: 0644]
drivers/Makefile
drivers/block/sandbox.c
drivers/clk/clk-uclass.c
drivers/clk/clk_fixed_rate.c
drivers/clk/clk_sandbox.c
drivers/clk/clk_sandbox_test.c
drivers/clk/clk_zynqmp.c
drivers/core/device.c
drivers/core/of_addr.c
drivers/core/root.c
drivers/core/uclass.c
drivers/dfu/dfu_sf.c
drivers/gpio/gpio-uclass.c
drivers/gpio/intel_gpio.c
drivers/gpio/sandbox.c
drivers/gpio/stm32_gpio.c
drivers/i2c/Makefile
drivers/i2c/i2c-emul-uclass.c
drivers/misc/cbmem_console.c
drivers/misc/cros_ec_sandbox.c
drivers/misc/irq-uclass.c
drivers/misc/p2sb_emul.c
drivers/misc/test_drv.c
drivers/mmc/Kconfig
drivers/mmc/fsl_esdhc_imx.c
drivers/mmc/pci_mmc.c
drivers/mtd/spi/sf-uclass.c
drivers/mtd/spi/sf_internal.h
drivers/mtd/spi/sf_probe.c
drivers/mtd/spi/spi-nor-core.c
drivers/mtd/spi/spi-nor-tiny.c
drivers/net/zynq_gem.c
drivers/pci/pci_rom.c
drivers/pinctrl/mediatek/pinctrl-mt7629.c
drivers/pinctrl/mediatek/pinctrl-mtk-common.c
drivers/pinctrl/pinctrl-at91-pio4.c
drivers/pinctrl/pinctrl-stmfx.c
drivers/pinctrl/renesas/Kconfig
drivers/pinctrl/renesas/Makefile
drivers/pinctrl/renesas/pfc-r8a77990.c
drivers/pinctrl/renesas/pfc.c
drivers/pinctrl/renesas/sh_pfc.h
drivers/rtc/i2c_rtc_emul.c
drivers/rtc/sandbox_rtc.c
drivers/serial/serial_coreboot.c
drivers/serial/serial_mtk.c
drivers/sound/tegra_i2s.c
drivers/spi/spi-uclass.c
drivers/spi/xilinx_spi.c
drivers/sysreset/sysreset-uclass.c
drivers/tee/optee/Kconfig
drivers/tee/sandbox.c
drivers/timer/sandbox_timer.c
drivers/timer/timer-uclass.c
drivers/tpm/Makefile
drivers/tpm/cr50_i2c.c
drivers/tpm/tpm-uclass.c
drivers/tpm/tpm2_tis_sandbox.c
drivers/video/Kconfig
drivers/video/coreboot.c
drivers/video/sunxi/sunxi_display.c
drivers/watchdog/imx_watchdog.c
drivers/watchdog/ulp_wdog.c
dts/Kconfig
fs/cbfs/cbfs.c
include/asm-generic/global_data.h
include/asm-generic/gpio.h
include/asm-generic/sections.h
include/cbfs.h
include/command.h
include/configs/chromebook_coral.h
include/configs/hihope-rzg2.h [new file with mode: 0644]
include/configs/mt8183.h [new file with mode: 0644]
include/configs/mt8516.h [moved from include/configs/pumpkin.h with 55% similarity]
include/configs/silinux-ek874.h [new file with mode: 0644]
include/configs/sunxi-common.h
include/cpu_func.h
include/dm/device-internal.h
include/dm/device.h
include/dm/of_extra.h
include/dm/platdata.h
include/dm/root.h
include/dm/test.h
include/dm/uclass-internal.h
include/dm/uclass.h
include/dm/util.h
include/dt-bindings/display/tda998x.h [new file with mode: 0644]
include/dt-bindings/dma/xlnx-zynqmp-dpdma.h [new file with mode: 0644]
include/dt-structs.h
include/efi_api.h
include/efi_loader.h
include/efi_selftest.h
include/i2c.h
include/image.h
include/linker_lists.h
include/linux/clk-provider.h
include/log.h
include/malloc.h
include/os.h
include/sandboxblockdev.h
include/scp03.h [new file with mode: 0644]
include/smbios.h
include/spi_flash.h
include/spl.h
include/sysinfo.h
include/sysreset.h
include/tee/optee_ta_scp03.h [new file with mode: 0644]
include/test/test.h
include/test/ut.h
include/tpm-common.h
include/tpm-v1.h
include/tpm-v2.h
include/tpm_api.h [new file with mode: 0644]
lib/Kconfig
lib/Makefile
lib/binman.c
lib/efi_loader/Kconfig
lib/efi_loader/Makefile
lib/efi_loader/efi_bootmgr.c
lib/efi_loader/efi_boottime.c
lib/efi_loader/efi_capsule.c
lib/efi_loader/efi_device_path.c
lib/efi_loader/efi_esrt.c [new file with mode: 0644]
lib/efi_loader/efi_file.c
lib/efi_loader/efi_helper.c [new file with mode: 0644]
lib/efi_loader/efi_load_initrd.c
lib/efi_loader/efi_setup.c
lib/efi_loader/efi_tcg2.c
lib/efi_loader/efi_var_common.c
lib/efi_selftest/Makefile
lib/efi_selftest/efi_selftest.c
lib/efi_selftest/efi_selftest_esrt.c [new file with mode: 0644]
lib/efi_selftest/efi_selftest_set_virtual_address_map.c
lib/smbios-parser.c
lib/smbios.c
lib/tpm-common.c
lib/tpm-v1.c
lib/tpm-v2.c
lib/tpm_api.c [new file with mode: 0644]
scripts/Makefile.spl
scripts/config_whitelist.txt
scripts/dtc/pylibfdt/Makefile
test/Makefile
test/bloblist.c
test/bootm.c
test/cmd/mem.c
test/cmd/setexpr.c
test/cmd/test_echo.c
test/cmd_ut.c
test/compression.c
test/dm/Makefile
test/dm/acpi.c
test/dm/core.c
test/dm/gpio.c
test/dm/of_platdata.c
test/dm/sf.c
test/dm/test-dm.c [new file with mode: 0644]
test/dm/test-driver.c
test/dm/test-fdt.c
test/dm/test-main.c [deleted file]
test/dm/test-uclass.c
test/env/cmd_ut_env.c
test/image/Makefile [new file with mode: 0644]
test/image/spl_load.c [new file with mode: 0644]
test/lib/cmd_ut_lib.c
test/lib/test_print.c
test/log/Makefile
test/log/cont_test.c
test/log/log_ut.c [moved from test/log/test-main.c with 75% similarity]
test/optee/cmd_ut_optee.c
test/overlay/cmd_ut_overlay.c
test/py/conftest.py
test/py/tests/test_efi_capsule/test_capsule_firmware.py
test/py/tests/test_efi_secboot/test_signed.py
test/py/tests/test_efi_secboot/test_signed_intca.py
test/py/tests/test_efi_secboot/test_unsigned.py
test/py/tests/test_log.py
test/py/tests/test_ofplatdata.py
test/py/tests/test_scp03.py [new file with mode: 0644]
test/run
test/str_ut.c
test/test-main.c [new file with mode: 0644]
test/unicode_ut.c
test/ut.c
tools/binman/README.rst [new symlink]
tools/binman/binman.rst [moved from tools/binman/README with 63% similarity]
tools/binman/cmdline.py
tools/binman/control.py
tools/binman/entries.rst [moved from tools/binman/README.entries with 80% similarity]
tools/binman/entry.py
tools/binman/entry_test.py
tools/binman/etype/atf_bl31.py
tools/binman/etype/blob.py
tools/binman/etype/blob_dtb.py
tools/binman/etype/blob_ext.py
tools/binman/etype/blob_phase.py [new file with mode: 0644]
tools/binman/etype/cbfs.py
tools/binman/etype/collection.py [new file with mode: 0644]
tools/binman/etype/fdtmap.py
tools/binman/etype/files.py
tools/binman/etype/fit.py
tools/binman/etype/intel_cmc.py
tools/binman/etype/intel_fsp.py
tools/binman/etype/intel_fsp_m.py
tools/binman/etype/intel_fsp_s.py
tools/binman/etype/intel_fsp_t.py
tools/binman/etype/intel_ifwi.py
tools/binman/etype/intel_me.py
tools/binman/etype/intel_mrc.py
tools/binman/etype/intel_refcode.py
tools/binman/etype/intel_vbt.py
tools/binman/etype/intel_vga.py
tools/binman/etype/mkimage.py
tools/binman/etype/scp.py
tools/binman/etype/section.py
tools/binman/etype/text.py
tools/binman/etype/u_boot.py
tools/binman/etype/u_boot_dtb_with_ucode.py
tools/binman/etype/u_boot_expanded.py [new file with mode: 0644]
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_expanded.py [new file with mode: 0644]
tools/binman/etype/u_boot_spl_nodtb.py
tools/binman/etype/u_boot_tpl.py
tools/binman/etype/u_boot_tpl_bss_pad.py [new file with mode: 0644]
tools/binman/etype/u_boot_tpl_expanded.py [new file with mode: 0644]
tools/binman/etype/u_boot_tpl_nodtb.py [new file with mode: 0644]
tools/binman/etype/u_boot_with_ucode_ptr.py
tools/binman/etype/vblock.py
tools/binman/ftest.py
tools/binman/image.py
tools/binman/index.rst [new file with mode: 0644]
tools/binman/setup.py
tools/binman/state.py
tools/binman/test/053_symbols.dts
tools/binman/test/149_symbols_tpl.dts
tools/binman/test/155_symbols_tpl_x86.dts
tools/binman/test/192_u_boot_tpl_nodtb.dts [new file with mode: 0644]
tools/binman/test/193_tpl_bss_pad.dts [new file with mode: 0644]
tools/binman/test/194_fdt_incl.dts [new file with mode: 0644]
tools/binman/test/195_fdt_incl_tpl.dts [new file with mode: 0644]
tools/binman/test/196_symbols_nodtb.dts [new file with mode: 0644]
tools/binman/test/197_symbols_expand.dts [new file with mode: 0644]
tools/binman/test/198_collection.dts [new file with mode: 0644]
tools/binman/test/199_collection_section.dts [new file with mode: 0644]
tools/binman/test/200_align_default.dts [new file with mode: 0644]
tools/binman/test/u_boot_binman_syms.c
tools/dtoc/dtb_platdata.py
tools/dtoc/dtoc_test_scan_drivers.cxx [deleted file]
tools/dtoc/fdt.py
tools/dtoc/main.py
tools/dtoc/src_scan.py
tools/dtoc/test/dtoc_test.dts [moved from tools/dtoc/dtoc_test.dts with 100% similarity]
tools/dtoc/test/dtoc_test_add_prop.dts [moved from tools/dtoc/dtoc_test_add_prop.dts with 100% similarity]
tools/dtoc/test/dtoc_test_addr32.dts [moved from tools/dtoc/dtoc_test_addr32.dts with 100% similarity]
tools/dtoc/test/dtoc_test_addr32_64.dts [moved from tools/dtoc/dtoc_test_addr32_64.dts with 100% similarity]
tools/dtoc/test/dtoc_test_addr64.dts [moved from tools/dtoc/dtoc_test_addr64.dts with 100% similarity]
tools/dtoc/test/dtoc_test_addr64_32.dts [moved from tools/dtoc/dtoc_test_addr64_32.dts with 100% similarity]
tools/dtoc/test/dtoc_test_alias_bad.dts [new file with mode: 0644]
tools/dtoc/test/dtoc_test_alias_bad_path.dts [new file with mode: 0644]
tools/dtoc/test/dtoc_test_alias_bad_uc.dts [new file with mode: 0644]
tools/dtoc/test/dtoc_test_aliases.dts [moved from tools/dtoc/dtoc_test_aliases.dts with 100% similarity]
tools/dtoc/test/dtoc_test_bad_reg.dts [moved from tools/dtoc/dtoc_test_bad_reg.dts with 100% similarity]
tools/dtoc/test/dtoc_test_bad_reg2.dts [moved from tools/dtoc/dtoc_test_bad_reg2.dts with 100% similarity]
tools/dtoc/test/dtoc_test_driver_alias.dts [moved from tools/dtoc/dtoc_test_driver_alias.dts with 100% similarity]
tools/dtoc/test/dtoc_test_empty.dts [moved from tools/dtoc/dtoc_test_empty.dts with 100% similarity]
tools/dtoc/test/dtoc_test_inst.dts [new file with mode: 0644]
tools/dtoc/test/dtoc_test_invalid_driver.dts [moved from tools/dtoc/dtoc_test_invalid_driver.dts with 100% similarity]
tools/dtoc/test/dtoc_test_phandle.dts [moved from tools/dtoc/dtoc_test_phandle.dts with 100% similarity]
tools/dtoc/test/dtoc_test_phandle_bad.dts [moved from tools/dtoc/dtoc_test_phandle_bad.dts with 100% similarity]
tools/dtoc/test/dtoc_test_phandle_bad2.dts [moved from tools/dtoc/dtoc_test_phandle_bad2.dts with 100% similarity]
tools/dtoc/test/dtoc_test_phandle_cd_gpios.dts [moved from tools/dtoc/dtoc_test_phandle_cd_gpios.dts with 100% similarity]
tools/dtoc/test/dtoc_test_phandle_reorder.dts [moved from tools/dtoc/dtoc_test_phandle_reorder.dts with 100% similarity]
tools/dtoc/test/dtoc_test_phandle_single.dts [moved from tools/dtoc/dtoc_test_phandle_single.dts with 100% similarity]
tools/dtoc/test/dtoc_test_scan_drivers.cxx [new file with mode: 0644]
tools/dtoc/test/dtoc_test_simple.dts [moved from tools/dtoc/dtoc_test_simple.dts with 91% similarity]
tools/dtoc/test_dtoc.py
tools/dtoc/test_fdt.py
tools/dtoc/test_src_scan.py
tools/fdtgrep.c
tools/mtk_image.c
tools/patman/README
tools/patman/func_test.py
tools/patman/gitutil.py
tools/patman/main.py
tools/patman/series.py
tools/patman/tools.py

index a7e27fa..f358e46 100644 (file)
@@ -148,7 +148,7 @@ jobs:
           export UBOOT_TRAVIS_BUILD_DIR=/tmp/sandbox_spl
           export PYTHONPATH=${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt
           export PATH=${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}
-          ./tools/buildman/buildman -T0 -o ${UBOOT_TRAVIS_BUILD_DIR} -w sandbox_spl
+          ./tools/buildman/buildman -T0 -o ${UBOOT_TRAVIS_BUILD_DIR} -w --board sandbox_spl
           ./tools/binman/binman --toolpath ${UBOOT_TRAVIS_BUILD_DIR}/tools test
           ./tools/buildman/buildman -t
           ./tools/dtoc/dtoc -t
@@ -187,6 +187,9 @@ jobs:
         sandbox_spl:
           TEST_PY_BD: "sandbox_spl"
           TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
+        sandbox_noinst:
+          TEST_PY_BD: "sandbox_noinst"
+          TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
         sandbox_flattree:
           TEST_PY_BD: "sandbox_flattree"
         evb_ast2500:
index 4fb9aa1..64e341c 100644 (file)
@@ -168,7 +168,8 @@ Run binman, buildman, dtoc, Kconfig and patman testsuites:
       export UBOOT_TRAVIS_BUILD_DIR=/tmp/sandbox_spl;
       export PYTHONPATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt";
       export PATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}";
-      ./tools/buildman/buildman -T0 -o ${UBOOT_TRAVIS_BUILD_DIR} -w sandbox_spl;
+      ./tools/buildman/buildman -T0 -o ${UBOOT_TRAVIS_BUILD_DIR} -w
+        --board sandbox_spl;
       ./tools/binman/binman --toolpath ${UBOOT_TRAVIS_BUILD_DIR}/tools test;
       ./tools/buildman/buildman -t;
       ./tools/dtoc/dtoc -t;
@@ -204,6 +205,13 @@ sandbox_spl test.py:
     TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
   <<: *buildman_and_testpy_dfn
 
+sandbox_noinst_test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "sandbox_noinst"
+    TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
+  <<: *buildman_and_testpy_dfn
+
 evb-ast2500 test.py:
   tags: [ 'all' ]
   variables:
index 7b526f4..193aa4d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -17,9 +17,13 @@ NAME =
 # o Look for make include files relative to root of kernel src
 MAKEFLAGS += -rR --include-dir=$(CURDIR)
 
-# Determine host architecture
+# Determine target architecture for the sandbox
 include include/host_arch.h
-MK_ARCH="${shell uname -m}"
+ifeq ("", "$(CROSS_COMPILE)")
+  MK_ARCH="${shell uname -m}"
+else
+  MK_ARCH="${shell echo $(CROSS_COMPILE) | sed -n 's/^\s*\([^\/]*\/\)*\([^-]*\)-\S*/\2/p'}"
+endif
 unexport HOST_ARCH
 ifeq ("x86_64", $(MK_ARCH))
   export HOST_ARCH=$(HOST_ARCH_X86_64)
@@ -27,7 +31,7 @@ else ifneq (,$(findstring $(MK_ARCH), "i386" "i486" "i586" "i686"))
   export HOST_ARCH=$(HOST_ARCH_X86)
 else ifneq (,$(findstring $(MK_ARCH), "aarch64" "armv8l"))
   export HOST_ARCH=$(HOST_ARCH_AARCH64)
-else ifeq ("armv7l", $(MK_ARCH))
+else ifneq (,$(findstring $(MK_ARCH), "arm" "armv7" "armv7l"))
   export HOST_ARCH=$(HOST_ARCH_ARM)
 else ifeq ("riscv32", $(MK_ARCH))
   export HOST_ARCH=$(HOST_ARCH_RISCV32)
@@ -1265,7 +1269,13 @@ u-boot.ldr:      u-boot
 # binman
 # ---------------------------------------------------------------------------
 # Use 'make BINMAN_DEBUG=1' to enable debugging
+# Use 'make BINMAN_VERBOSE=3' to set vebosity level
 default_dt := $(if $(DEVICE_TREE),$(DEVICE_TREE),$(CONFIG_DEFAULT_DEVICE_TREE))
+
+# Tell binman whether we have a devicetree for SPL and TPL
+have_spl_dt := $(if $(CONFIG_SPL_OF_PLATDATA),,$(CONFIG_SPL_OF_CONTROL))
+have_tpl_dt := $(if $(CONFIG_TPL_OF_PLATDATA),,$(CONFIG_TPL_OF_CONTROL))
+
 quiet_cmd_binman = BINMAN  $@
 cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \
                 --toolpath $(objtree)/tools \
@@ -1276,6 +1286,9 @@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \
                -a atf-bl31-path=${BL31} \
                -a default-dt=$(default_dt) \
                -a scp-path=$(SCP) \
+               -a spl-bss-pad=$(if $(CONFIG_SPL_SEPARATE_BSS),,1) \
+               -a tpl-bss-pad=$(if $(CONFIG_TPL_SEPARATE_BSS),,1) \
+               -a spl-dtb=$(have_spl_dt) -a tpl-dtb=$(have_tpl_dt) \
                $(BINMAN_$(@F))
 
 OBJCOPYFLAGS_u-boot.ldr.hex := -I binary -O ihex
@@ -1666,6 +1679,9 @@ u-boot-elf.lds: arch/u-boot-elf.lds prepare FORCE
 
 ifeq ($(CONFIG_SPL),y)
 spl/u-boot-spl-mtk.bin: spl/u-boot-spl
+
+u-boot-mtk.bin: u-boot-with-spl.bin
+       $(call if_changed,copy)
 else
 MKIMAGEFLAGS_u-boot-mtk.bin = -T mtk_image \
        -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) \
index 27843cd..7023223 100644 (file)
@@ -142,6 +142,8 @@ config SANDBOX
        imply AVB_VERIFY
        imply LIBAVB
        imply CMD_AVB
+       imply SCP03
+       imply CMD_SCP03
        imply UDP_FUNCTION_FASTBOOT
        imply VIRTIO_MMIO
        imply VIRTIO_PCI
index fbb56ec..b8589d0 100644 (file)
@@ -7,7 +7,7 @@
 #include <common.h>
 #include <cpu_func.h>
 
-__weak void reset_cpu(ulong addr)
+__weak void reset_cpu(void)
 {
        /* Stop debug session here */
        __builtin_arc_brk();
@@ -17,7 +17,7 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
        printf("Resetting the board...\n");
 
-       reset_cpu(0);
+       reset_cpu();
 
        return 0;
 }
index c9ea4e4..3435bdc 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/io.h>
 
 /* We reset the CPU by generating a 1-->0 transition on DeviceCfg bit 31. */
-extern void reset_cpu(ulong addr)
+extern void reset_cpu(void)
 {
        struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
        uint32_t value;
index e9d5577..0cd3a03 100644 (file)
@@ -81,7 +81,7 @@ ulong get_tbclk(void)
 /*
  * Reset the cpu by setting up the watchdog timer and let him time out
  */
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        /* Disable watchdog and set Time-Out field to 0 */
        WCR = 0x00000000;
index ec73393..6d77ad3 100644 (file)
@@ -142,7 +142,7 @@ int timer_init(void)
  * 2. Write key value to TMP_WSAR reg.
  * 3. Perform write operation.
  */
-void reset_cpu(unsigned long ignored)
+void reset_cpu(void)
 {
        struct armd1mpmu_registers *mpmu =
                (struct armd1mpmu_registers *) ARMD1_MPMU_BASE;
index 38df1c9..7844a99 100644 (file)
@@ -23,7 +23,7 @@
 /*
  * Reset the cpu by setting up the watchdog timer and let it time out
  */
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE;
        /* Disable watchdog and set Time-Out field to 0 */
index 320b0a6..496fb30 100644 (file)
@@ -23,7 +23,7 @@
 /*
  * Reset the cpu by setting up the watchdog timer and let it time out
  */
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE;
        /* Disable watchdog and set Time-Out field to 0 */
index c936213..344b9b4 100644 (file)
@@ -32,9 +32,9 @@ DECLARE_GLOBAL_DATA_PTR;
 /* Lowlevel init isn't used on i.MX28, so just have a dummy here */
 __weak void lowlevel_init(void) {}
 
-void reset_cpu(ulong ignored) __attribute__((noreturn));
+void reset_cpu(void) __attribute__((noreturn));
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        struct mxs_rtc_regs *rtc_regs =
                (struct mxs_rtc_regs *)MXS_RTC_BASE;
index a316540..97a624e 100644 (file)
@@ -11,7 +11,7 @@
 #include <asm/arch/spr_syscntl.h>
 #include <linux/delay.h>
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        struct syscntl_regs *syscntl_regs_p =
            (struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE;
index fb0ea5e..334bb54 100644 (file)
@@ -56,7 +56,7 @@ static void cache_flush (void)
 
 #ifndef CONFIG_ARCH_INTEGRATOR
 
-__attribute__((noreturn)) void reset_cpu(ulong addr __attribute__((unused)))
+__attribute__((noreturn)) void reset_cpu(void)
 {
        writew(0x0, 0xfffece10);
        writew(0x8, 0xfffece10);
index fda5a95..1491e5c 100644 (file)
@@ -13,7 +13,7 @@
 #define CLKS_SHIFT     20              /* Clock period shift */
 #define LD_SHIFT       0               /* Reload value shift */
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        /*
         * Set WD enable, RST enable,
index 3bfed34..63992fd 100644 (file)
@@ -10,7 +10,7 @@
 #define CRMU_MAIL_BOX1         0x03024028
 #define CRMU_SOFT_RESET_CMD    0xFFFFFFFF
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        /* Send soft reset command via Mailbox. */
        writel(CRMU_SOFT_RESET_CMD, CRMU_MAIL_BOX1);
index 675f99f..a313775 100644 (file)
@@ -9,7 +9,7 @@
 
 #define CRU_RESET_OFFSET       0x1803F184
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        /* Reset the cpu by setting software reset request bit */
        writel(0x1, CRU_RESET_OFFSET);
index 146cf52..19ff432 100644 (file)
@@ -176,9 +176,6 @@ void mmu_page_table_flush(unsigned long start, unsigned long stop)
 {
 }
 
-void arm_init_domains(void)
-{
-}
 #endif /* #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) */
 
 #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
index f26a5b2..d863c96 100644 (file)
@@ -375,7 +375,7 @@ void smp_kick_all_cpus(void)
 }
 #endif
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
 
index 3c71a37..3baa761 100644 (file)
@@ -88,7 +88,7 @@ int print_cpuinfo(void)
 }
 #endif
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        void *clkpwr_reg = (void *)PHY_BASEADDR_CLKPWR;
        const u32 sw_rst_enb_bitpos = 3;
index fb67de1..77d4477 100644 (file)
@@ -9,7 +9,7 @@
 #include <asm/io.h>
 #include <asm/arch/stv0991_wdru.h>
 #include <linux/delay.h>
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        puts("System is going to reboot ...\n");
        /*
index 7f827da..6372101 100644 (file)
@@ -47,7 +47,7 @@ int cleanup_before_linux(void)
 /*
  * Perform the low-level reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        /*
         * Perform reset but keep priority group unchanged.
index 3a5bf77..270a72e 100644 (file)
@@ -1231,7 +1231,7 @@ int timer_init(void)
 
 __efi_runtime_data u32 __iomem *rstcr = (u32 *)CONFIG_SYS_FSL_RST_ADDR;
 
-void __efi_runtime reset_cpu(ulong addr)
+void __efi_runtime reset_cpu(void)
 {
 #if defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LX2162A)
        /* clear the RST_REQ_MSK and SW_RST_REQ */
@@ -1260,7 +1260,7 @@ void __efi_runtime EFIAPI efi_reset_system(
        case EFI_RESET_COLD:
        case EFI_RESET_WARM:
        case EFI_RESET_PLATFORM_SPECIFIC:
-               reset_cpu(0);
+               reset_cpu();
                break;
        case EFI_RESET_SHUTDOWN:
                /* Nothing we can do */
index 0fc9885..d1ae10b 100644 (file)
@@ -319,7 +319,7 @@ static char *get_reset_cause(void)
 
 #define SRC_SCR_SW_RST                                 (1<<12)
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        printf("Feature not supported.\n");
 };
index ea91d8a..c7efb67 100644 (file)
@@ -267,9 +267,9 @@ void i2c_clk_enable(void)
        writel(readl(CKEN) | CKEN14_I2C, CKEN);
 }
 
-void __attribute__((weak)) reset_cpu(ulong ignored) __attribute__((noreturn));
+void __attribute__((weak)) reset_cpu(void) __attribute__((noreturn));
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        uint32_t tmp;
 
index 91e100a..6f67f7f 100644 (file)
@@ -55,7 +55,7 @@ static void cache_flush (void)
 #define RSRR   0x00
 #define RCSR   0x04
 
-__attribute__((noreturn)) void reset_cpu(ulong addr __attribute__((unused)))
+__attribute__((noreturn)) void reset_cpu(void)
 {
        /* repeat endlessly */
        while (1) {
index c671082..9a8de46 100644 (file)
@@ -822,6 +822,10 @@ dtb-$(CONFIG_RCAR_GEN3) += \
        r8a774a1-beacon-rzg2m-kit.dtb \
        r8a774b1-beacon-rzg2n-kit.dtb \
        r8a774e1-beacon-rzg2h-kit.dtb \
+       r8a774a1-hihope-rzg2m-u-boot.dtb \
+       r8a774b1-hihope-rzg2n-u-boot.dtb \
+       r8a774c0-ek874-u-boot.dtb \
+       r8a774e1-hihope-rzg2h-u-boot.dtb \
        r8a77950-ulcb-u-boot.dtb \
        r8a77950-salvator-x-u-boot.dtb \
        r8a77960-ulcb-u-boot.dtb \
@@ -1009,6 +1013,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
        mt7622-bananapi-bpi-r64.dtb \
        mt7623n-bananapi-bpi-r2.dtb \
        mt7629-rfb.dtb \
+       mt8183-pumpkin.dtb \
        mt8512-bm1-emmc.dtb \
        mt8516-pumpkin.dtb \
        mt8518-ap1-emmc.dtb
index 7362ad4..0694350 100644 (file)
        ps-clk-frequency = <33333333>;
 };
 
+&nand0 {
+       status = "okay";
+};
+
+&smcc {
+       status = "okay";
+};
+
 &gem0 {
        status = "okay";
        phy-mode = "rgmii-id";
diff --git a/arch/arm/dts/cat875.dtsi b/arch/arm/dts/cat875.dtsi
new file mode 100644 (file)
index 0000000..4a2f6fa
--- /dev/null
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the Silicon Linux sub board for CAT874 (CAT875)
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+/ {
+       model = "Silicon Linux sub board for CAT874 (CAT875)";
+
+       aliases {
+               ethernet0 = &avb;
+       };
+};
+
+&avb {
+       pinctrl-0 = <&avb_pins>;
+       pinctrl-names = "default";
+       renesas,no-ether-link;
+       phy-handle = <&phy0>;
+       status = "okay";
+
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+               interrupt-parent = <&gpio2>;
+               interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+               reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+       };
+};
+
+&can0 {
+       pinctrl-0 = <&can0_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
+&can1 {
+       pinctrl-0 = <&can1_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
+&pciec0 {
+       status = "okay";
+};
+
+&pfc {
+       avb_pins: avb {
+               mux {
+                       groups = "avb_mii";
+                       function = "avb";
+               };
+       };
+
+       can0_pins: can0 {
+               groups = "can0_data";
+               function = "can0";
+       };
+
+       can1_pins: can1 {
+               groups = "can1_data";
+               function = "can1";
+       };
+};
index 164afd6..c17e82a 100644 (file)
@@ -5,24 +5,6 @@
  * Author: Weijie Gao <weijie.gao@mediatek.com>
  */
 
-#include <config.h>
-/ {
-       binman {
-               filename = "u-boot-mtk.bin";
-               pad-byte = <0xff>;
-
-#ifdef CONFIG_SPL
-               blob {
-                       filename = "spl/u-boot-spl-mtk.bin";
-                       size = <CONFIG_SPL_PAD_TO>;
-               };
-
-               u-boot-img {
-               };
-#endif
-       };
-};
-
 &infracfg {
        u-boot,dm-pre-reloc;
 };
index df43cc4..f2e4e95 100644 (file)
 };
 
 &pinctrl {
+       state_default: pinmux_conf {
+               u-boot,dm-pre-reloc;
+
+               mux {
+                       function = "jtag";
+                       groups = "ephy_leds_jtag";
+                       u-boot,dm-pre-reloc;
+               };
+       };
+
        snfi_pins: snfi-pins {
                mux {
                        function = "flash";
index 0539426..7dea780 100644 (file)
                compatible = "mediatek,mt7629-pinctrl";
                reg = <0x10217000 0x8000>;
 
+               pinctrl-names = "default";
+               pinctrl-0 = <&state_default>;
+
+               state_default: pinmux_conf {
+               };
+
                gpio: gpio-controller {
                        gpio-controller;
                        #gpio-cells = <2>;
diff --git a/arch/arm/dts/mt8183-pumpkin.dts b/arch/arm/dts/mt8183-pumpkin.dts
new file mode 100644 (file)
index 0000000..470a769
--- /dev/null
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2021 BayLibre SAS.
+ * Author: Fabien Parent <fparent@baylibre.com>
+ */
+
+/dts-v1/;
+
+#include <config.h>
+#include "mt8183.dtsi"
+
+/ {
+       model = "MediaTek MT8183 pumpkin board";
+       compatible = "mediatek,mt8183-pumpkin", "mediatek,mt8183";
+
+       memory@40000000 {
+               device_type = "memory";
+               reg = <0 0x40000000 0 0x80000000>;
+       };
+
+       reserved-memory {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               /* 192 KiB reserved for ARM Trusted Firmware (BL31) */
+               bl31_secmon_reserved: secmon@54600000 {
+                       no-map;
+                       reg = <0 0x54600000 0x0 0x30000>;
+               };
+
+               /* 12 MiB reserved for OP-TEE (BL32)
+                * +-----------------------+ 0x43e0_0000
+                * |      SHMEM 2MiB       |
+                * +-----------------------+ 0x43c0_0000
+                * |        | TA_RAM  8MiB |
+                * + TZDRAM +--------------+ 0x4340_0000
+                * |        | TEE_RAM 2MiB |
+                * +-----------------------+ 0x4320_0000
+                */
+               optee_reserved: optee@43200000 {
+                       no-map;
+                       reg = <0 0x43200000 0 0x00c00000>;
+               };
+       };
+
+       chosen {
+               stdout-path = &uart0;
+       };
+
+       reg_1p8v: regulator-1p8v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-1.8V";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+};
+
+&watchdog {
+       status = "okay";
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&mmc0 {
+       bus-width = <4>;
+       max-frequency = <200000000>;
+       cap-mmc-highspeed;
+       mmc-hs200-1_8v;
+       cap-mmc-hw-reset;
+       vmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_1p8v>;
+       non-removable;
+       status = "okay";
+};
+
+&usb {
+       status = "okay";
+};
+
+&ssusb {
+       mediatek,force-vbus;
+       maximum-speed = "high-speed";
+       dr_mode = "peripheral";
+       status = "okay";
+};
diff --git a/arch/arm/dts/mt8183.dtsi b/arch/arm/dts/mt8183.dtsi
new file mode 100644 (file)
index 0000000..294aa2b
--- /dev/null
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Copyright (C) 2021 BayLibre, SAS
+ * Author: Ben Ho <ben.ho@mediatek.com>
+ *         Erin Lo <erin.lo@mediatek.com>
+ *         Fabien Parent <fparent@baylibre.com>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/mt8183-clk.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy.h>
+
+/ {
+       compatible = "mediatek,mt8183";
+       interrupt-parent = <&sysirq>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&cpu0>;
+                               };
+                               core1 {
+                                       cpu = <&cpu1>;
+                               };
+                               core2 {
+                                       cpu = <&cpu2>;
+                               };
+                               core3 {
+                                       cpu = <&cpu3>;
+                               };
+                       };
+
+                       cluster1 {
+                               core0 {
+                                       cpu = <&cpu4>;
+                               };
+                               core1 {
+                                       cpu = <&cpu5>;
+                               };
+                               core2 {
+                                       cpu = <&cpu6>;
+                               };
+                               core3 {
+                                       cpu = <&cpu7>;
+                               };
+                       };
+               };
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x000>;
+                       enable-method = "psci";
+                       capacity-dmips-mhz = <741>;
+               };
+
+               cpu1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x001>;
+                       enable-method = "psci";
+                       capacity-dmips-mhz = <741>;
+               };
+
+               cpu2: cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x002>;
+                       enable-method = "psci";
+                       capacity-dmips-mhz = <741>;
+               };
+
+               cpu3: cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x003>;
+                       enable-method = "psci";
+                       capacity-dmips-mhz = <741>;
+               };
+
+               cpu4: cpu@100 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a73";
+                       reg = <0x100>;
+                       enable-method = "psci";
+                       capacity-dmips-mhz = <1024>;
+               };
+
+               cpu5: cpu@101 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a73";
+                       reg = <0x101>;
+                       enable-method = "psci";
+                       capacity-dmips-mhz = <1024>;
+               };
+
+               cpu6: cpu@102 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a73";
+                       reg = <0x102>;
+                       enable-method = "psci";
+                       capacity-dmips-mhz = <1024>;
+               };
+
+               cpu7: cpu@103 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a73";
+                       reg = <0x103>;
+                       enable-method = "psci";
+                       capacity-dmips-mhz = <1024>;
+               };
+       };
+
+       clk26m: oscillator {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <26000000>;
+               clock-output-names = "clk26m";
+       };
+
+       soc {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               compatible = "simple-bus";
+               ranges;
+
+               watchdog: watchdog@10007000 {
+                       compatible = "mediatek,mt8183-wdt",
+                                     "mediatek,wdt";
+                       reg = <0 0x10007000 0 0x100>;
+                       status = "disabled";
+               };
+
+               gic: interrupt-controller@c000000 {
+                       compatible = "arm,gic-v3";
+                       #interrupt-cells = <4>;
+                       interrupt-parent = <&gic>;
+                       interrupt-controller;
+                       reg = <0 0x0c000000 0 0x40000>,  /* GICD */
+                             <0 0x0c100000 0 0x200000>, /* GICR */
+                             <0 0x0c400000 0 0x2000>,   /* GICC */
+                             <0 0x0c410000 0 0x1000>,   /* GICH */
+                             <0 0x0c420000 0 0x2000>;   /* GICV */
+
+                       interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>;
+                       ppi-partitions {
+                               ppi_cluster0: interrupt-partition-0 {
+                                       affinity = <&cpu0 &cpu1 &cpu2 &cpu3>;
+                               };
+                               ppi_cluster1: interrupt-partition-1 {
+                                       affinity = <&cpu4 &cpu5 &cpu6 &cpu7>;
+                               };
+                       };
+               };
+
+               sysirq: interrupt-controller@c530a80 {
+                       compatible = "mediatek,mt8183-sysirq",
+                                    "mediatek,mt6577-sysirq";
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       interrupt-parent = <&gic>;
+                       reg = <0 0x0c530a80 0 0x50>;
+               };
+
+               topckgen: syscon@10000000 {
+                       compatible = "mediatek,mt8183-topckgen", "syscon";
+                       reg = <0 0x10000000 0 0x1000>;
+                       #clock-cells = <1>;
+               };
+
+               infracfg: syscon@10001000 {
+                       compatible = "mediatek,mt8183-infracfg", "syscon";
+                       reg = <0 0x10001000 0 0x1000>;
+                       #clock-cells = <1>;
+               };
+
+               apmixedsys: syscon@1000c000 {
+                       compatible = "mediatek,mt8183-apmixedsys", "syscon";
+                       reg = <0 0x1000c000 0 0x1000>;
+                       #clock-cells = <1>;
+               };
+
+               uart0: serial@11002000 {
+                       compatible = "mediatek,mt8183-uart",
+                                    "mediatek,hsuart";
+                       reg = <0 0x11002000 0 0x1000>;
+                       interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
+                       clock-frequency = <26000000>;
+                       clocks = <&clk26m>, <&infracfg CLK_INFRA_UART0>;
+                       clock-names = "baud", "bus";
+                       status = "disabled";
+               };
+
+               mmc0: mmc@11230000 {
+                       compatible = "mediatek,mt8183-mmc";
+                       reg = <0 0x11230000 0 0x1000>,
+                             <0 0x11f50000 0 0x1000>;
+                       interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_LOW>;
+                       clocks = <&topckgen CLK_TOP_MUX_MSDC50_0>,
+                                <&infracfg CLK_INFRA_MSDC0>,
+                                <&infracfg CLK_INFRA_MSDC0_SCK>;
+                       clock-names = "source", "hclk", "source_cg";
+                       status = "disabled";
+               };
+
+               u3phy: usb-phy@11f40000 {
+                       compatible = "mediatek,generic-tphy-v2";
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+                       status = "okay";
+
+                       u2port0: usb-phy2@11f40000 {
+                               reg = <0 0x11f40000 0 0x700>;
+                               clocks = <&clk26m>;
+                               clock-names = "ref";
+                               #phy-cells = <1>;
+                               status = "okay";
+                       };
+
+                       u3port0: usb-phy3@11f40700 {
+                               reg = <0 0x11f40700 0 0x900>;
+                               clocks = <&clk26m>;
+                               clock-names = "ref";
+                               #phy-cells = <1>;
+                               status = "okay";
+                       };
+               };
+
+               usb: usb@11200000 {
+                       compatible ="mediatek,mt8183-mtu3", "mediatek,mtu3";
+                       reg = <0 0x11200000 0 0x3e00>,
+                             <0 0x11203e00 0 0x0100>;
+                       reg-names = "mac", "ippc";
+                       interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>;
+                       phys = <&u2port0 PHY_TYPE_USB2>;
+                       clocks = <&infracfg CLK_INFRA_UNIPRO_SCK>,
+                                <&infracfg CLK_INFRA_USB>;
+                       clock-names = "sys_ck", "ref_ck";
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+                       status = "disabled";
+
+                       ssusb: ssusb@11200000 {
+                               compatible = "mediatek,ssusb";
+                               reg = <0 0x11200000 0 0x3e00>;
+                               reg-names = "mac";
+                               interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>;
+                               status = "disabled";
+                       };
+
+                       usb_host: xhci@11200000 {
+                               compatible = "mediatek,mtk-xhci";
+                               reg = <0 0x11200000 0 0x1000>;
+                               reg-names = "mac";
+                               interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_LOW>;
+                               clocks = <&infracfg CLK_INFRA_UNIPRO_SCK>,
+                                        <&infracfg CLK_INFRA_USB>;
+                               clock-names = "sys_ck", "ref_ck";
+                               status = "disabled";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/dts/r8a774b1-hihope-rzg2n-ex.dts b/arch/arm/dts/r8a774b1-hihope-rzg2n-ex.dts
new file mode 100644 (file)
index 0000000..60d7c8a
--- /dev/null
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2N Rev.3.0/4.0 connected to
+ * sub board
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include "r8a774b1-hihope-rzg2n.dts"
+#include "hihope-rzg2-ex.dtsi"
+
+/ {
+       model = "HopeRun HiHope RZ/G2N with sub board";
+       compatible = "hoperun,hihope-rzg2-ex", "hoperun,hihope-rzg2n",
+                    "renesas,r8a774b1";
+};
+
+/* Set SW43 = ON and SW1001[7] = OFF for SATA port to be activated */
+&sata {
+       status = "okay";
+};
diff --git a/arch/arm/dts/r8a774b1-hihope-rzg2n-u-boot.dts b/arch/arm/dts/r8a774b1-hihope-rzg2n-u-boot.dts
new file mode 100644 (file)
index 0000000..0bdc690
--- /dev/null
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot for the Hihope RZ/G2N board
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include "r8a774b1-hihope-rzg2n-ex.dts"
+#include "r8a774b1-u-boot.dtsi"
+
+&gpio3 {
+       bt_reg_on{
+               gpio-hog;
+               gpios = <13 GPIO_ACTIVE_HIGH>;
+               output-low;
+               line-name = "bt-reg-on";
+       };
+};
+
+&gpio4 {
+       wlan_reg_on{
+               gpio-hog;
+               gpios = <6 GPIO_ACTIVE_HIGH>;
+               output-low;
+               line-name = "wlan-reg-on";
+       };
+};
diff --git a/arch/arm/dts/r8a774b1-hihope-rzg2n.dts b/arch/arm/dts/r8a774b1-hihope-rzg2n.dts
new file mode 100644 (file)
index 0000000..f1883cb
--- /dev/null
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2N main board Rev.3.0/4.0
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a774b1.dtsi"
+#include "hihope-rev4.dtsi"
+
+/ {
+       model = "HopeRun HiHope RZ/G2N main board based on r8a774b1";
+       compatible = "hoperun,hihope-rzg2n", "renesas,r8a774b1";
+
+       memory@48000000 {
+               device_type = "memory";
+               /* first 128MB is reserved for secure area. */
+               reg = <0x0 0x48000000 0x0 0x78000000>;
+       };
+
+       memory@480000000 {
+               device_type = "memory";
+               reg = <0x4 0x80000000 0x0 0x80000000>;
+       };
+};
+
+&du {
+       clocks = <&cpg CPG_MOD 724>,
+                <&cpg CPG_MOD 723>,
+                <&cpg CPG_MOD 721>,
+                <&versaclock5 1>,
+                <&x302_clk>,
+                <&versaclock5 2>;
+       clock-names = "du.0", "du.1", "du.3",
+                     "dclkin.0", "dclkin.1", "dclkin.3";
+};
+
+&sdhi3 {
+       mmc-hs400-1_8v;
+};
diff --git a/arch/arm/dts/r8a774b1-u-boot.dtsi b/arch/arm/dts/r8a774b1-u-boot.dtsi
new file mode 100644 (file)
index 0000000..6fab78e
--- /dev/null
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot on RZ/G2 R8A774B1 SoC
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include "r8a779x-u-boot.dtsi"
+
+&extalr_clk {
+       u-boot,dm-pre-reloc;
+};
+
+/delete-node/ &audma0;
+/delete-node/ &audma1;
+/delete-node/ &can0;
+/delete-node/ &can1;
+/delete-node/ &canfd;
+/delete-node/ &csi20;
+/delete-node/ &csi40;
+/delete-node/ &du;
+/delete-node/ &fcpf0;
+/delete-node/ &fcpvb0;
+/delete-node/ &fcpvd0;
+/delete-node/ &fcpvd1;
+/delete-node/ &fcpvi0;
+/delete-node/ &hdmi0;
+/delete-node/ &lvds0;
+/delete-node/ &rcar_sound;
+/delete-node/ &sdhi2;
+/delete-node/ &sound_card;
+/delete-node/ &vin0;
+/delete-node/ &vin1;
+/delete-node/ &vin2;
+/delete-node/ &vin3;
+/delete-node/ &vin4;
+/delete-node/ &vin5;
+/delete-node/ &vin6;
+/delete-node/ &vin7;
+/delete-node/ &vspb;
+/delete-node/ &vspd0;
+/delete-node/ &vspd1;
+/delete-node/ &vspi0;
+
+/ {
+       /delete-node/ hdmi0-out;
+};
+
+/ {
+       soc {
+               /delete-node/ fdp1@fe940000;
+       };
+};
diff --git a/arch/arm/dts/r8a774c0-cat874.dts b/arch/arm/dts/r8a774c0-cat874.dts
new file mode 100644 (file)
index 0000000..676fdef
--- /dev/null
@@ -0,0 +1,453 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the Silicon Linux RZ/G2E 96board platform (CAT874)
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a774c0.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/display/tda998x.h>
+
+/ {
+       model = "Silicon Linux RZ/G2E 96board platform (CAT874)";
+       compatible = "si-linux,cat874", "renesas,r8a774c0";
+
+       aliases {
+               serial0 = &scif2;
+               serial1 = &hscif2;
+       };
+
+       chosen {
+               bootargs = "ignore_loglevel rw root=/dev/nfs ip=on";
+               stdout-path = "serial0:115200n8";
+       };
+
+       hdmi-out {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_con_out: endpoint {
+                               remote-endpoint = <&tda19988_out>;
+                       };
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led0 {
+                       gpios = <&gpio5 19 GPIO_ACTIVE_HIGH>;
+                       label = "LED0";
+               };
+
+               led1 {
+                       gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>;
+                       label = "LED1";
+               };
+
+               led2 {
+                       gpios = <&gpio4 10 GPIO_ACTIVE_HIGH>;
+                       label = "LED2";
+               };
+
+               led3 {
+                       gpios = <&gpio6 4 GPIO_ACTIVE_HIGH>;
+                       label = "LED3";
+               };
+       };
+
+       memory@48000000 {
+               device_type = "memory";
+               /* first 128MB is reserved for secure area. */
+               reg = <0x0 0x48000000 0x0 0x78000000>;
+       };
+
+       reg_12p0v: regulator-12p0v {
+               compatible = "regulator-fixed";
+               regulator-name = "D12.0V";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       sound: sound {
+               compatible = "simple-audio-card";
+
+               simple-audio-card,name = "CAT874 HDMI sound";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,bitclock-master = <&sndcpu>;
+               simple-audio-card,frame-master = <&sndcpu>;
+
+               sndcodec: simple-audio-card,codec {
+                       sound-dai = <&tda19988>;
+               };
+
+               sndcpu: simple-audio-card,cpu {
+                       sound-dai = <&rcar_sound>;
+               };
+       };
+
+       vcc_sdhi0: regulator-vcc-sdhi0 {
+               compatible = "regulator-fixed";
+
+               regulator-name = "SDHI0 Vcc";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       vccq_sdhi0: regulator-vccq-sdhi0 {
+               compatible = "regulator-gpio";
+
+               regulator-name = "SDHI0 VccQ";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <3300000>;
+
+               gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+               gpios-states = <1>;
+               states = <3300000 1>, <1800000 0>;
+       };
+
+       wlan_en_reg: fixedregulator {
+               compatible = "regulator-fixed";
+               regulator-name = "wlan-en-regulator";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               startup-delay-us = <70000>;
+
+               gpio = <&gpio2 25 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       x13_clk: x13 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <74250000>;
+       };
+
+       connector {
+               compatible = "usb-c-connector";
+               label = "USB-C";
+               data-role = "dual";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       port@0 {
+                               reg = <0>;
+                               hs_ep: endpoint {
+                                       remote-endpoint = <&usb3_hs_ep>;
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               ss_ep: endpoint {
+                                       remote-endpoint = <&hd3ss3220_in_ep>;
+                               };
+                       };
+               };
+       };
+};
+
+&audio_clk_a {
+       clock-frequency = <22579200>;
+};
+
+&du {
+       pinctrl-0 = <&du_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+
+       clocks = <&cpg CPG_MOD 724>,
+                <&cpg CPG_MOD 723>,
+                <&x13_clk>;
+       clock-names = "du.0", "du.1", "dclkin.0";
+
+       ports {
+               port@0 {
+                       endpoint {
+                               remote-endpoint = <&tda19988_in>;
+                       };
+               };
+       };
+};
+
+&ehci0 {
+       dr_mode = "host";
+       status = "okay";
+};
+
+&extal_clk {
+       clock-frequency = <48000000>;
+};
+
+&hscif2 {
+       pinctrl-0 = <&hscif2_pins>;
+       pinctrl-names = "default";
+
+       uart-has-rtscts;
+       status = "okay";
+
+       bluetooth {
+               compatible = "ti,wl1837-st";
+               enable-gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
+       };
+};
+
+&i2c0 {
+       status = "okay";
+       clock-frequency = <100000>;
+
+       hd3ss3220@47 {
+               compatible = "ti,hd3ss3220";
+               reg = <0x47>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       port@0 {
+                               reg = <0>;
+                               hd3ss3220_in_ep: endpoint {
+                                       remote-endpoint = <&ss_ep>;
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               hd3ss3220_out_ep: endpoint {
+                                       remote-endpoint = <&usb3_role_switch>;
+                               };
+                       };
+               };
+       };
+
+       tda19988: tda19988@70 {
+               compatible = "nxp,tda998x";
+               reg = <0x70>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+
+               video-ports = <0x234501>;
+
+               #sound-dai-cells = <0>;
+               audio-ports = <TDA998x_I2S 0x03>;
+               clocks = <&rcar_sound 1>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               tda19988_in: endpoint {
+                                       remote-endpoint = <&du_out_rgb>;
+                               };
+                       };
+
+                       port@1 {
+                               reg = <1>;
+                               tda19988_out: endpoint {
+                                       remote-endpoint = <&hdmi_con_out>;
+                               };
+                       };
+               };
+       };
+};
+
+&i2c1 {
+       pinctrl-0 = <&i2c1_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+       clock-frequency = <400000>;
+
+       rtc@32 {
+               compatible = "epson,rx8571";
+               reg = <0x32>;
+       };
+};
+
+&lvds0 {
+       status = "okay";
+
+       clocks = <&cpg CPG_MOD 727>, <&x13_clk>, <&extal_clk>;
+       clock-names = "fck", "dclkin.0", "extal";
+};
+
+&ohci0 {
+       dr_mode = "host";
+       status = "okay";
+};
+
+&pcie_bus_clk {
+       clock-frequency = <100000000>;
+};
+
+&pciec0 {
+       /* Map all possible DDR as inbound ranges */
+       dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>;
+};
+
+&pfc {
+       du_pins: du {
+               groups = "du_rgb888", "du_clk_out_0", "du_sync", "du_disp",
+                        "du_clk_in_0";
+               function = "du";
+       };
+
+       hscif2_pins: hscif2 {
+               groups = "hscif2_data_a", "hscif2_ctrl_a";
+               function = "hscif2";
+       };
+
+       i2c1_pins: i2c1 {
+               groups = "i2c1_b";
+               function = "i2c1";
+       };
+
+       scif2_pins: scif2 {
+               groups = "scif2_data_a";
+               function = "scif2";
+       };
+
+       sdhi0_pins: sd0 {
+               groups = "sdhi0_data4", "sdhi0_ctrl";
+               function = "sdhi0";
+               power-source = <3300>;
+       };
+
+       sdhi0_pins_uhs: sd0_uhs {
+               groups = "sdhi0_data4", "sdhi0_ctrl";
+               function = "sdhi0";
+               power-source = <1800>;
+       };
+
+       sdhi3_pins: sd3 {
+               groups = "sdhi3_data4", "sdhi3_ctrl";
+               function = "sdhi3";
+               power-source = <1800>;
+       };
+
+       sound_clk_pins: sound_clk {
+               groups = "audio_clkout1_a";
+               function = "audio_clk";
+       };
+
+       sound_pins: sound {
+               groups = "ssi01239_ctrl", "ssi0_data";
+               function = "ssi";
+       };
+
+       usb30_pins: usb30 {
+               groups = "usb30", "usb30_id";
+               function = "usb30";
+       };
+};
+
+&rcar_sound {
+       pinctrl-0 = <&sound_pins &sound_clk_pins>;
+       pinctrl-names = "default";
+
+       /* Single DAI */
+       #sound-dai-cells = <0>;
+
+       /* audio_clkout0/1/2/3 */
+       #clock-cells = <1>;
+       clock-frequency = <11289600>;
+
+       status = "okay";
+
+       rcar_sound,dai {
+               dai0 {
+                       playback = <&ssi0 &src0 &dvc0>;
+               };
+       };
+};
+
+&rwdt {
+       timeout-sec = <60>;
+       status = "okay";
+};
+
+&scif2 {
+       pinctrl-0 = <&scif2_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+};
+
+&sdhi0 {
+       pinctrl-0 = <&sdhi0_pins>;
+       pinctrl-1 = <&sdhi0_pins_uhs>;
+       pinctrl-names = "default", "state_uhs";
+
+       vmmc-supply = <&vcc_sdhi0>;
+       vqmmc-supply = <&vccq_sdhi0>;
+       cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
+       bus-width = <4>;
+       sd-uhs-sdr50;
+       sd-uhs-sdr104;
+       status = "okay";
+};
+
+&sdhi3 {
+       status = "okay";
+       pinctrl-0 = <&sdhi3_pins>;
+       pinctrl-names = "default";
+
+       vmmc-supply = <&wlan_en_reg>;
+       bus-width = <4>;
+       non-removable;
+       cap-power-off-card;
+       keep-power-in-suspend;
+
+       #address-cells = <1>;
+       #size-cells = <0>;
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1837";
+               reg = <2>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+       };
+};
+
+&usb2_phy0 {
+       renesas,no-otg-pins;
+       status = "okay";
+};
+
+&usb3_peri0 {
+       companion = <&xhci0>;
+       status = "okay";
+       usb-role-switch;
+
+       ports {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               port@0 {
+                       reg = <0>;
+                       usb3_hs_ep: endpoint {
+                               remote-endpoint = <&hs_ep>;
+                       };
+               };
+               port@1 {
+                       reg = <1>;
+                       usb3_role_switch: endpoint {
+                               remote-endpoint = <&hd3ss3220_out_ep>;
+                       };
+               };
+       };
+};
+
+&xhci0 {
+       pinctrl-0 = <&usb30_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+};
diff --git a/arch/arm/dts/r8a774c0-ek874-u-boot.dts b/arch/arm/dts/r8a774c0-ek874-u-boot.dts
new file mode 100644 (file)
index 0000000..8fa6d80
--- /dev/null
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot for the Hihope board
+ *
+ * Copyright (C) 2021 Renesas Electronisc Corporation
+ */
+
+#include "r8a774c0-ek874.dts"
+#include "r8a774c0-u-boot.dtsi"
+
+/ {
+       aliases {
+               spi0 = &rpc;
+       };
+};
+
+&rpc {
+       num-cs = <1>;
+       status = "okay";
+       spi-max-frequency = <50000000>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       flash0: spi-flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "w25m512jv", "spi-flash", "jedec,spi-nor";
+               spi-max-frequency = <50000000>;
+               spi-tx-bus-width = <1>;
+               spi-rx-bus-width = <1>;
+               reg = <0>;
+       };
+};
diff --git a/arch/arm/dts/r8a774c0-ek874.dts b/arch/arm/dts/r8a774c0-ek874.dts
new file mode 100644 (file)
index 0000000..d3ab28b
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the Silicon Linux RZ/G2E evaluation kit (EK874)
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include "r8a774c0-cat874.dts"
+#include "cat875.dtsi"
+
+/ {
+       model = "Silicon Linux RZ/G2E evaluation kit EK874 (CAT874 + CAT875)";
+       compatible = "si-linux,cat875", "si-linux,cat874", "renesas,r8a774c0";
+};
diff --git a/arch/arm/dts/r8a774c0-u-boot.dtsi b/arch/arm/dts/r8a774c0-u-boot.dtsi
new file mode 100644 (file)
index 0000000..af1c861
--- /dev/null
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot on R8A774C0 SoC
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ */
+
+#include "r8a779x-u-boot.dtsi"
+
+/ {
+       soc {
+               rpc: rpc@ee200000 {
+                       compatible = "renesas,rcar-gen3-rpc", "renesas,rpc-r8a774c0";
+                       reg = <0 0xee200000 0 0x100>, <0 0x08000000 0 0x04000000>;
+                       clocks = <&cpg CPG_MOD 917>;
+                       bank-width = <2>;
+                       status = "disabled";
+               };
+       };
+};
+
+/delete-node/ &can0;
+/delete-node/ &can1;
+/delete-node/ &canfd;
+/delete-node/ &pwm0;
+/delete-node/ &pwm1;
+/delete-node/ &pwm2;
+/delete-node/ &pwm3;
+/delete-node/ &pwm4;
+/delete-node/ &pwm5;
+/delete-node/ &pwm6;
+/delete-node/ &vin4;
+/delete-node/ &vin5;
+/delete-node/ &rcar_sound;
+/delete-node/ &audma0;
+/delete-node/ &sdhi1;
+/delete-node/ &sdhi3;
+/delete-node/ &vspb0;
+/delete-node/ &vspd0;
+/delete-node/ &vspd1;
+/delete-node/ &vspi0;
+/delete-node/ &fcpvb0;
+/delete-node/ &fcpvd0;
+/delete-node/ &fcpvd1;
+/delete-node/ &fcpvi0;
+/delete-node/ &csi40;
+/delete-node/ &du;
+/delete-node/ &lvds0;
+/delete-node/ &lvds1;
+/delete-node/ &hdmi_con_out;
+/delete-node/ &sound;
+/delete-node/ &tda19988;
index e14db4d..2bdd571 100644 (file)
                        resets = <&cpg 906>;
                };
 
-               pfc: pin-controller@e6060000 {
+               pfc: pinctrl@e6060000 {
                        compatible = "renesas,pfc-r8a774c0";
                        reg = <0 0xe6060000 0 0x508>;
                };
                        power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
                        resets = <&cpg 812>;
                        phy-mode = "rgmii";
+                       rx-internal-delay-ps = <0>;
                        iommus = <&ipmmu_ds0 16>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <0 0xe6ea0000 0 0x0064>;
                        interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 210>;
-                       dmas = <&dmac1 0x43>, <&dmac1 0x42>,
-                              <&dmac2 0x43>, <&dmac2 0x42>;
-                       dma-names = "tx", "rx", "tx", "rx";
+                       dmas = <&dmac0 0x43>, <&dmac0 0x42>;
+                       dma-names = "tx", "rx";
                        power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
                        resets = <&cpg 210>;
                        #address-cells = <1>;
                        status = "disabled";
                };
 
+               pciec0_ep: pcie-ep@fe000000 {
+                       compatible = "renesas,r8a774c0-pcie-ep",
+                                    "renesas,rcar-gen3-pcie-ep";
+                       reg = <0x0 0xfe000000 0 0x80000>,
+                             <0x0 0xfe100000 0 0x100000>,
+                             <0x0 0xfe200000 0 0x200000>,
+                             <0x0 0x30000000 0 0x8000000>,
+                             <0x0 0x38000000 0 0x8000000>;
+                       reg-names = "apb-base", "memory0", "memory1", "memory2", "memory3";
+                       interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 319>;
+                       clock-names = "pcie";
+                       resets = <&cpg 319>;
+                       power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
+                       status = "disabled";
+               };
+
                vspb0: vsp@fe960000 {
                        compatible = "renesas,vsp2";
                        reg = <0 0xfe960000 0 0x8000>;
diff --git a/arch/arm/dts/r8a774e1-hihope-rzg2h-ex.dts b/arch/arm/dts/r8a774e1-hihope-rzg2h-ex.dts
new file mode 100644 (file)
index 0000000..8129959
--- /dev/null
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2H sub board
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include "r8a774e1-hihope-rzg2h.dts"
+#include "hihope-rzg2-ex.dtsi"
+
+/ {
+       model = "HopeRun HiHope RZ/G2H with sub board";
+       compatible = "hoperun,hihope-rzg2-ex", "hoperun,hihope-rzg2h",
+                    "renesas,r8a774e1";
+};
+
+/* Set SW43 = ON and SW1001[7] = OFF for SATA port to be activated */
+&sata {
+       status = "okay";
+};
diff --git a/arch/arm/dts/r8a774e1-hihope-rzg2h-u-boot.dts b/arch/arm/dts/r8a774e1-hihope-rzg2h-u-boot.dts
new file mode 100644 (file)
index 0000000..03a17ba
--- /dev/null
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot for the Hihope RZ/G2H board
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include "r8a774e1-hihope-rzg2h-ex.dts"
+#include "r8a774e1-u-boot.dtsi"
+
+&gpio3 {
+       bt_reg_on{
+               gpio-hog;
+               gpios = <13 GPIO_ACTIVE_HIGH>;
+               output-low;
+               line-name = "bt-reg-on";
+       };
+};
+
+&gpio4 {
+       wlan_reg_on{
+               gpio-hog;
+               gpios = <6 GPIO_ACTIVE_HIGH>;
+               output-low;
+               line-name = "wlan-reg-on";
+       };
+};
diff --git a/arch/arm/dts/r8a774e1-hihope-rzg2h.dts b/arch/arm/dts/r8a774e1-hihope-rzg2h.dts
new file mode 100644 (file)
index 0000000..9525d5e
--- /dev/null
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2H main board
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a774e1.dtsi"
+#include "hihope-rev4.dtsi"
+
+/ {
+       model = "HopeRun HiHope RZ/G2H main board based on r8a774e1";
+       compatible = "hoperun,hihope-rzg2h", "renesas,r8a774e1";
+
+       memory@48000000 {
+               device_type = "memory";
+               /* first 128MB is reserved for secure area. */
+               reg = <0x0 0x48000000 0x0 0x78000000>;
+       };
+
+       memory@500000000 {
+               device_type = "memory";
+               reg = <0x5 0x00000000 0x0 0x80000000>;
+       };
+};
+
+&du {
+       clocks = <&cpg CPG_MOD 724>,
+                <&cpg CPG_MOD 723>,
+                <&cpg CPG_MOD 721>,
+                <&versaclock5 1>,
+                <&x302_clk>,
+                <&versaclock5 2>;
+       clock-names = "du.0", "du.1", "du.3",
+                     "dclkin.0", "dclkin.1", "dclkin.3";
+};
+
+&sdhi3 {
+       mmc-hs400-1_8v;
+};
diff --git a/arch/arm/dts/r8a774e1-u-boot.dtsi b/arch/arm/dts/r8a774e1-u-boot.dtsi
new file mode 100644 (file)
index 0000000..74758df
--- /dev/null
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot on RZ/G2 R8A774E1 SoC
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include "r8a779x-u-boot.dtsi"
+
+&extalr_clk {
+       u-boot,dm-pre-reloc;
+};
+
+/delete-node/ &audma0;
+/delete-node/ &audma1;
+/delete-node/ &can0;
+/delete-node/ &can1;
+/delete-node/ &canfd;
+/delete-node/ &csi20;
+/delete-node/ &csi40;
+/delete-node/ &du;
+/delete-node/ &fcpf0;
+/delete-node/ &fcpf1;
+/delete-node/ &fcpvb0;
+/delete-node/ &fcpvb1;
+/delete-node/ &fcpvd0;
+/delete-node/ &fcpvd1;
+/delete-node/ &fcpvi0;
+/delete-node/ &fcpvi1;
+/delete-node/ &hdmi0;
+/delete-node/ &lvds0;
+/delete-node/ &rcar_sound;
+/delete-node/ &sdhi2;
+/delete-node/ &sound_card;
+/delete-node/ &vin0;
+/delete-node/ &vin1;
+/delete-node/ &vin2;
+/delete-node/ &vin3;
+/delete-node/ &vin4;
+/delete-node/ &vin5;
+/delete-node/ &vin6;
+/delete-node/ &vin7;
+/delete-node/ &vspbc;
+/delete-node/ &vspbd;
+/delete-node/ &vspd0;
+/delete-node/ &vspd1;
+/delete-node/ &vspi0;
+/delete-node/ &vspi1;
+
+/ {
+       /delete-node/ hdmi0-out;
+};
+
+/ {
+       soc {
+               /delete-node/ fdp1@fe940000;
+               /delete-node/ fdp1@fe944000;
+       };
+};
index b043d34..e45eba3 100644 (file)
@@ -51,7 +51,7 @@
        leds {
                compatible = "gpio-leds";
 
-               ds23 {
+               led-ds23 {
                        label = "ds23";
                        gpios = <&gpio0 10 0>;
                        linux,default-trigger = "heartbeat";
index 1d7af02..486b6fa 100644 (file)
        };
 
        accelerometer@53 {
-               compatible = "adi,adxl345", "adxl345", "adi,adxl34x", "adxl34x";
+               compatible = "adi,adxl345";
                reg = <0x53>;
                interrupt-parent = <&intc>;
                interrupts = <0x0 0x1e 0x4>;
index 3f8a3bf..116958e 100644 (file)
@@ -31,7 +31,7 @@
        gpio-leds {
                compatible = "gpio-leds";
 
-               ld4 {
+               led-ld4 {
                        label = "zynq-zybo-z7:green:ld4";
                        gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
                };
index b02ef22..987792e 100644 (file)
        clocks = <&zynqmp_clk AMS_REF>;
 };
 
-&zynqmp_dpsub {
-       clocks = <&dp_aclk>, <&zynqmp_clk DP_AUDIO_REF>, <&zynqmp_clk DP_VIDEO_REF>;
+&zynqmp_pcap {
+       clocks = <&zynqmp_clk PCAP>;
 };
 
-&xlnx_dpdma {
+&zynqmp_dpdma {
        clocks = <&zynqmp_clk DPDMA_REF>;
 };
 
-&zynqmp_dp_snd_codec0 {
-       clocks = <&zynqmp_clk DP_AUDIO_REF>;
-};
-
-&zynqmp_pcap {
-       clocks = <&zynqmp_clk PCAP>;
+&zynqmp_dpsub {
+       clocks = <&zynqmp_clk TOPSW_LSBUS>,
+                <&zynqmp_clk DP_AUDIO_REF>,
+                <&zynqmp_clk DP_VIDEO_REF>;
 };
index 9468dc5..f94b797 100644 (file)
@@ -88,9 +88,6 @@
                reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
 /*             xlnx,phy-type = <PHY_TYPE_SGMII>; */
        };
-/*     phy-names = "...";
-       phys = <&lane0 PHY_TYPE_SGMII ... >
-       Note: lane0 sgmii/lane1 usb3 */
 };
 
 &gpio {
index 66ea02e..19e1ebd 100644 (file)
                reg = <0>;
 /*             xlnx,phy-type = <PHY_TYPE_SGMII>; */
        };
-/*     phy-names = "...";
-       phys = <&lane0 PHY_TYPE_SGMII ... >
-       Note: lane0 sgmii/lane1 usb3 */
 };
 
 &gpio {
index 2213bb2..8467dd8 100644 (file)
@@ -51,6 +51,8 @@
                        u-boot,dm-pre-reloc;
                        compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
                        status = "disabled";
+                       non-removable;
+                       bus-width = <8>;
                        reg = <0x0 0xff160000 0x0 0x1000>;
                        clock-names = "clk_xin", "clk_ahb";
                        clocks = <&clk_xin &clk_xin>;
index 0538da4..2afcc77 100644 (file)
@@ -51,6 +51,8 @@
                        u-boot,dm-pre-reloc;
                        compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
                        status = "disabled";
+                       non-removable;
+                       bus-width = <8>;
                        reg = <0x0 0xff170000 0x0 0x1000>;
                        clock-names = "clk_xin", "clk_ahb";
                        clocks = <&clk_xin &clk_xin>;
index afb3e96..ef7cf0a 100644 (file)
@@ -78,8 +78,6 @@
        ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
        ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
        ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
-       phy-names = "sata-phy";
-       phys = <&lane0 PHY_TYPE_SATA 0 0 125000000>, <&lane1 PHY_TYPE_SATA 1 1 125000000>;
 };
 
 &uart0 {
index e2428ec..b8c5efb 100644 (file)
        dr_mode = "host";
 };
 
-&zynqmp_dpsub {
-       status = "okay";
-};
-
-&zynqmp_dp_snd_pcm0 {
-       status = "okay";
-};
-
-&zynqmp_dp_snd_pcm1 {
+&zynqmp_dpdma {
        status = "okay";
 };
 
-&zynqmp_dp_snd_card0 {
-       status = "okay";
-};
-
-&zynqmp_dp_snd_codec0 {
+&zynqmp_dpsub {
        status = "okay";
 };
 
-&xlnx_dpdma {
-       status = "okay";
-};
index 92d938d..3204456 100644 (file)
                reg = <0x0>;
                #address-cells = <0x2>;
                #size-cells = <0x1>;
+               nand-ecc-mode = "soft";
+               nand-ecc-algo = "bch";
+               nand-rb = <0>;
+               label = "main-storage-0";
 
                partition@0 {   /* for testing purpose */
                        label = "nand-fsbl-uboot";
                reg = <0x1>;
                #address-cells = <0x2>;
                #size-cells = <0x1>;
+               nand-ecc-mode = "soft";
+               nand-ecc-algo = "bch";
+               nand-rb = <0>;
+               label = "main-storage-1";
 
                partition@0 {   /* for testing purpose */
                        label = "nand1-fsbl-uboot";
index 9b38b8b..aadda17 100644 (file)
        status = "okay";
 };
 
-&xlnx_dpdma {
+&zynqmp_dpdma {
        status = "okay";
 };
 
index d6c914c..bbcc69c 100644 (file)
 
        leds {
                compatible = "gpio-leds";
-               ds2 {
+               led-ds2 {
                        label = "ds2";
                        gpios = <&gpio 20 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "heartbeat";
                };
 
-               ds3 {
+               led-ds3 {
                        label = "ds3";
                        gpios = <&gpio 19 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "phy0tx"; /* WLAN tx */
                        default-state = "off";
                };
 
-               ds4 {
+               led-ds4 {
                        label = "ds4";
                        gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "phy0rx"; /* WLAN rx */
                        default-state = "off";
                };
 
-               ds5 {
+               led-ds5 {
                        label = "ds5";
                        gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "bluetooth-power";
                compatible = "iio-hwmon";
                io-channels = <&u35 0>, <&u35 1>, <&u35 2>, <&u35 3>;
        };
+
+       si5335a_0: clk26 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <26000000>;
+       };
+
+       si5335a_1: clk27 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <27000000>;
+       };
 };
 
 &dcc {
                                compatible = "ti,tps65086";
                                reg = <0x5e>;
                                interrupt-parent = <&gpio>;
-                               interrupts = <77 GPIO_ACTIVE_LOW>;
+                               interrupts = <77 IRQ_TYPE_LEVEL_LOW>;
                                #gpio-cells = <2>;
                                gpio-controller;
                        };
        };
 };
 
+&psgtr {
+       status = "okay";
+       /* usb3, dps */
+       clocks = <&si5335a_0>, <&si5335a_1>;
+       clock-names = "ref0", "ref1";
+};
+
 &rtc {
        status = "okay";
 };
        };
 };
 
-&serdes {
-       status = "okay";
-};
-
 &spi0 { /* Low Speed connector */
        status = "okay";
        label = "LS-SPI0";
 &dwc3_0 {
        status = "okay";
        dr_mode = "peripheral";
-       phy-names = "usb3-phy";
-       phys = <&lane2 PHY_TYPE_USB3 0 0 26000000>;
        maximum-speed = "super-speed";
 };
 
 &dwc3_1 {
        status = "okay";
        dr_mode = "host";
-       phy-names = "usb3-phy";
-       phys = <&lane3 PHY_TYPE_USB3 1 0 26000000>;
        maximum-speed = "super-speed";
 };
 
 &ams_ps {
        status = "okay";
 };
+
+&zynqmp_dpdma {
+       status = "okay";
+};
+
+&zynqmp_dpsub {
+       status = "okay";
+       phy-names = "dp-phy0", "dp-phy1";
+       phys = <&psgtr 1 PHY_TYPE_DP 0 1>,
+              <&psgtr 0 PHY_TYPE_DP 1 1>;
+};
index ed036e6..9323b8d 100644 (file)
                compatible = "iio-hwmon";
                io-channels = <&u75 0>, <&u75 1>, <&u75 2>, <&u75 3>;
        };
+
+       /* 48MHz reference crystal */
+       ref48: ref48M {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <48000000>;
+       };
+
+       refhdmi: refhdmi {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <114285000>;
+       };
 };
 
 &can1 {
                gpio-line-names = "PS_GTR_LAN_SEL0", "PS_GTR_LAN_SEL1", "PS_GTR_LAN_SEL2", "PS_GTR_LAN_SEL3",
                                "PCI_CLK_DIR_SEL", "IIC_MUX_RESET_B", "GEM3_EXP_RESET_B",
                                "", "", "", "", "", "", "", "", "";
-               gtr-sel0 {
+               gtr-sel0-hog {
                        gpio-hog;
                        gpios = <0 0>;
                        output-low; /* PCIE = 0, DP = 1 */
                        line-name = "sel0";
                };
-               gtr-sel1 {
+               gtr-sel1-hog {
                        gpio-hog;
                        gpios = <1 0>;
                        output-high; /* PCIE = 0, DP = 1 */
                        line-name = "sel1";
                };
-               gtr-sel2 {
+               gtr-sel2-hog {
                        gpio-hog;
                        gpios = <2 0>;
                        output-high; /* PCIE = 0, USB0 = 1 */
                        line-name = "sel2";
                };
-               gtr-sel3 {
+               gtr-sel3-hog {
                        gpio-hog;
                        gpios = <3 0>;
                        output-high; /* PCIE = 0, SATA = 1 */
                        si5341: clock-generator@36 { /* SI5341 - u69 */
                                compatible = "silabs,si5341";
                                reg = <0x36>;
+                               #clock-cells = <2>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               clocks = <&ref48>;
+                               clock-names = "xtal";
+                               clock-output-names = "si5341";
+
+                               si5341_0: out@0 {
+                                       /* refclk0 for PS-GT, used for DP */
+                                       reg = <0>;
+                                       always-on;
+                               };
+                               si5341_2: out@2 {
+                                       /* refclk2 for PS-GT, used for USB3 */
+                                       reg = <2>;
+                                       always-on;
+                               };
+                               si5341_3: out@3 {
+                                       /* refclk3 for PS-GT, used for SATA */
+                                       reg = <3>;
+                                       always-on;
+                               };
+                               si5341_4: out@4 {
+                                       /* refclk4 for PS-GT, used for PCIE slot */
+                                       reg = <4>;
+                                       always-on;
+                               };
+                               si5341_5: out@5 {
+                                       /* refclk5 for PS-GT, used for PCIE */
+                                       reg = <5>;
+                                       always-on;
+                               };
+                               si5341_6: out@6 {
+                                       /* refclk6 PL CLK125 */
+                                       reg = <6>;
+                                       always-on;
+                               };
+                               si5341_7: out@7 {
+                                       /* refclk7 PL CLK74 */
+                                       reg = <7>;
+                                       always-on;
+                               };
+                               si5341_9: out@9 {
+                                       /* refclk9 used for PS_REF_CLK 33.3 MHz */
+                                       reg = <9>;
+                                       always-on;
+                               };
                        };
-
                };
                i2c@2 {
                        #address-cells = <1>;
        status = "okay";
 };
 
+&psgtr {
+       status = "okay";
+       /* pcie, sata, usb3, dp */
+       clocks = <&si5341 0 5>, <&si5341 0 3>, <&si5341 0 2>, <&si5341 0 0>;
+       clock-names = "ref0", "ref1", "ref2", "ref3";
+};
+
 &qspi {
        status = "okay";
        is-dual = <1>;
        ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
        ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
        phy-names = "sata-phy";
-       phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
+       phys = <&psgtr 3 PHY_TYPE_SATA 1 1>;
 };
 
 /* SD1 with level shifter */
        xlnx,mio-bank = <1>;
 };
 
-&serdes {
-       status = "okay";
-};
-
 &uart0 {
        status = "okay";
 };
        status = "okay";
        dr_mode = "host";
        snps,usb3_lpm_capable;
-       phy-names = "usb3-phy";
-       phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
        maximum-speed = "super-speed";
 };
 
        status = "okay";
 };
 
-&zynqmp_dpsub {
+&zynqmp_dpdma {
        status = "okay";
 };
 
-&zynqmp_dp_snd_codec0 {
-       status = "okay";
-};
-
-&zynqmp_dp_snd_pcm0 {
-       status = "okay";
-};
-
-&zynqmp_dp_snd_pcm1 {
-       status = "okay";
-};
-
-&zynqmp_dp_snd_card0 {
-       status = "okay";
-};
-
-&xlnx_dpdma {
+&zynqmp_dpsub {
        status = "okay";
+       phy-names = "dp-phy0";
+       phys = <&psgtr 1 PHY_TYPE_DP 0 3>;
 };
index cb8ffdf..a95bd49 100644 (file)
                device_type = "memory";
                reg = <0x0 0x0 0x0 0x80000000>;
        };
+
+       clock_8t49n287_5: clk125 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <125000000>;
+       };
+
+       clock_8t49n287_2: clk26 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <26000000>;
+       };
+
+       clock_8t49n287_3: clk27 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <27000000>;
+       };
 };
 
 &can1 {
        };
 };
 
+&psgtr {
+       status = "okay";
+       /* nc, sata, usb3, dp */
+       clocks = <&clock_8t49n287_5>, <&clock_8t49n287_2>, <&clock_8t49n287_3>;
+       clock-names = "ref1", "ref2", "ref3";
+};
+
 &rtc {
        status = "okay";
 };
        ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
        ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
        phy-names = "sata-phy";
-       phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
+       phys = <&psgtr 3 PHY_TYPE_SATA 1 1>;
 };
 
 /* SD1 with level shifter */
        disable-wp;
 };
 
-&serdes {
-       status = "okay";
-};
-
 &uart0 {
        status = "okay";
 };
        status = "okay";
        dr_mode = "host";
        snps,usb3_lpm_capable;
-       phy-names = "usb3-phy";
-       phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
        maximum-speed = "super-speed";
 };
 
 &ams_pl {
        status = "okay";
 };
+
+&zynqmp_dpdma {
+       status = "okay";
+};
+
+&zynqmp_dpsub {
+       status = "okay";
+       phy-names = "dp-phy0", "dp-phy1";
+       phys = <&psgtr 1 PHY_TYPE_DP 0 3>,
+              <&psgtr 0 PHY_TYPE_DP 1 3>;
+};
index e203280..8f30a28 100644 (file)
                compatible = "iio-hwmon";
                io-channels = <&u183 0>, <&u183 1>, <&u183 2>, <&u183 3>;
        };
+
+       clock_8t49n287_5: clk125 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <125000000>;
+       };
+
+       clock_8t49n287_2: clk26 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <26000000>;
+       };
+
+       clock_8t49n287_3: clk27 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <27000000>;
+       };
 };
 
 &can1 {
        status = "okay";
 };
 
+&psgtr {
+       status = "okay";
+       /* nc, sata, usb3, dp */
+       clocks = <&clock_8t49n287_5>, <&clock_8t49n287_2>, <&clock_8t49n287_3>;
+       clock-names = "ref1", "ref2", "ref3";
+};
+
 &sata {
        status = "okay";
        /* SATA OOB timing settings */
        ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
        ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
        phy-names = "sata-phy";
-       phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
+       phys = <&psgtr 3 PHY_TYPE_SATA 1 1>;
 };
 
 /* SD1 with level shifter */
        disable-wp;
 };
 
-&serdes {
-       status = "okay";
-};
-
 &uart0 {
        status = "okay";
 };
        status = "okay";
        dr_mode = "host";
        snps,usb3_lpm_capable;
-       phy-names = "usb3-phy";
-       phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
        maximum-speed = "super-speed";
 };
 
 &ams_pl {
        status = "okay";
 };
+
+&zynqmp_dpdma {
+       status = "okay";
+};
+
+&zynqmp_dpsub {
+       status = "okay";
+       phy-names = "dp-phy0", "dp-phy1";
+       phys = <&psgtr 1 PHY_TYPE_DP 0 3>,
+              <&psgtr 0 PHY_TYPE_DP 1 3>;
+};
index 1dff845..971f76f 100644 (file)
                compatible = "iio-hwmon";
                io-channels = <&u75 0>, <&u75 1>, <&u75 2>, <&u75 3>;
        };
+
+       /* 48MHz reference crystal */
+       ref48: ref48M {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <48000000>;
+       };
+
+       refhdmi: refhdmi {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <114285000>;
+       };
 };
 
 &can1 {
        status = "okay";
 };
 
+&zynqmp_dpdma {
+       status = "okay";
+};
+
+&zynqmp_dpsub {
+       status = "okay";
+       phy-names = "dp-phy0", "dp-phy1";
+       phys = <&psgtr 1 PHY_TYPE_DP 0 3>,
+              <&psgtr 0 PHY_TYPE_DP 1 3>;
+};
+
+/* fpd_dma clk 667MHz, lpd_dma 500MHz */
 &fpd_dma_chan1 {
        status = "okay";
 };
                        #size-cells = <0>;
                        reg = <1>;
                        si5341: clock-generator@36 { /* SI5341 - u69 */
-                               compatible = "si5341";
+                               compatible = "silabs,si5341";
                                reg = <0x36>;
+                               #clock-cells = <2>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               clocks = <&ref48>;
+                               clock-names = "xtal";
+                               clock-output-names = "si5341";
+
+                               si5341_0: out@0 {
+                                       /* refclk0 for PS-GT, used for DP */
+                                       reg = <0>;
+                                       always-on;
+                               };
+                               si5341_2: out@2 {
+                                       /* refclk2 for PS-GT, used for USB3 */
+                                       reg = <2>;
+                                       always-on;
+                               };
+                               si5341_3: out@3 {
+                                       /* refclk3 for PS-GT, used for SATA */
+                                       reg = <3>;
+                                       always-on;
+                               };
+                               si5341_6: out@6 {
+                                       /* refclk6 PL CLK125 */
+                                       reg = <6>;
+                                       always-on;
+                               };
+                               si5341_7: out@7 {
+                                       /* refclk7 PL CLK74 */
+                                       reg = <7>;
+                                       always-on;
+                               };
+                               si5341_9: out@9 {
+                                       /* refclk9 used for PS_REF_CLK 33.3 MHz */
+                                       reg = <9>;
+                                       always-on;
+                               };
                        };
 
                };
                        #size-cells = <0>;
                        reg = <4>;
                        si5328: clock-generator@69 {/* SI5328 - u20 */
-                               compatible = "silabs,si5328";
                                reg = <0x69>;
+                               /*
+                                * Chip has interrupt present connected to PL
+                                * interrupt-parent = <&>;
+                                * interrupts = <>;
+                                */
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               #clock-cells = <1>;
+                               clocks = <&refhdmi>;
+                               clock-names = "xtal";
+                               clock-output-names = "si5328";
+
+                               si5328_clk: clk0@0 {
+                                       reg = <0>;
+                                       clock-frequency = <27000000>;
+                               };
                        };
                };
                i2c@5 {
        };
 };
 
+&psgtr {
+       status = "okay";
+       /* nc, sata, usb3, dp */
+       clocks = <&si5341 0 3>, <&si5341 0 2>, <&si5341 0 0>;
+       clock-names = "ref1", "ref2", "ref3";
+};
+
 &qspi {
        status = "okay";
        is-dual = <1>;
        ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
        ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
        phy-names = "sata-phy";
-       phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
+       phys = <&psgtr 3 PHY_TYPE_SATA 1 1>;
 };
 
 /* SD1 with level shifter */
        xlnx,mio-bank = <1>;
 };
 
-&serdes {
-       status = "okay";
-};
-
 &uart0 {
        status = "okay";
 };
        status = "okay";
        dr_mode = "host";
        snps,usb3_lpm_capable;
-       phy-names = "usb3-phy";
-       phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
 };
 
 &watchdog0 {
index 82e6c8d..9e47008 100644 (file)
                compatible = "iio-hwmon";
                io-channels = <&u79 0>, <&u79 1>, <&u79 2>, <&u79 3>;
        };
+
+       /* 48MHz reference crystal */
+       ref48: ref48M {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <48000000>;
+       };
 };
 
 &dcc {
                        #size-cells = <0>;
                        reg = <1>;
                        si5341: clock-generator@36 { /* SI5341 - u46 */
-                               compatible = "si5341";
+                               compatible = "silabs,si5341";
                                reg = <0x36>;
+                               #clock-cells = <2>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               clocks = <&ref48>;
+                               clock-names = "xtal";
+                               clock-output-names = "si5341";
+
+                               si5341_0: out@0 {
+                                       /* refclk0 for PS-GT, used for DP */
+                                       reg = <0>;
+                                       always-on;
+                               };
+                               si5341_2: out@2 {
+                                       /* refclk2 for PS-GT, used for USB3 */
+                                       reg = <2>;
+                                       always-on;
+                               };
+                               si5341_3: out@3 {
+                                       /* refclk3 for PS-GT, used for SATA */
+                                       reg = <3>;
+                                       always-on;
+                               };
+                               si5341_5: out@5 {
+                                       /* refclk5 PL CLK100 */
+                                       reg = <5>;
+                                       always-on;
+                               };
+                               si5341_6: out@6 {
+                                       /* refclk6 PL CLK125 */
+                                       reg = <6>;
+                                       always-on;
+                               };
+                               si5341_9: out@9 {
+                                       /* refclk9 used for PS_REF_CLK 33.3 MHz */
+                                       reg = <9>;
+                                       always-on;
+                               };
                        };
-
                };
                i2c@2 {
                        #address-cells = <1>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <4>;
-                       si5328: clock-generator@69 { /* SI5328 - u48 */
-                               compatible = "silabs,si5328";
+                       si5382: clock-generator@69 { /* SI5382 - u48 */
+                               compatible = "silabs,si5382";
                                reg = <0x69>;
                        };
                };
        };
 };
 
+&psgtr {
+       status = "okay";
+       /* nc, sata, usb3, dp */
+       clocks = <&si5341 0 3>, <&si5341 0 2>, <&si5341 0 0>;
+       clock-names = "ref1", "ref2", "ref3";
+};
+
 &qspi {
        status = "okay";
        is-dual = <1>;
        ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
        ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
        phy-names = "sata-phy";
-       phys = <&lane3 PHY_TYPE_SATA 1 3 125000000>;
+       phys = <&psgtr 3 PHY_TYPE_SATA 1 1>;
 };
 
 /* SD1 with level shifter */
        xlnx,mio-bank = <1>;
 };
 
-&serdes {
-       status = "okay";
-};
-
 &uart0 {
        status = "okay";
 };
 /* ULPI SMSC USB3320 */
 &usb0 {
        status = "okay";
+       dr_mode = "host";
 };
 
-&dwc3_0 {
+&zynqmp_dpdma {
        status = "okay";
-       dr_mode = "host";
-       snps,usb3_lpm_capable;
-       phy-names = "usb3-phy";
-       phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
+};
+
+&zynqmp_dpsub {
+       status = "okay";
+       phy-names = "dp-phy0", "dp-phy1";
+       phys = <&psgtr 1 PHY_TYPE_DP 0 1>,
+              <&psgtr 0 PHY_TYPE_DP 1 1>;
 };
index 1242193..0e114cd 100644 (file)
                compatible = "iio-hwmon";
                io-channels = <&dac_avcc 0>, <&dac_avcc 1>, <&dac_avcc 2>, <&dac_avcc 3>;
        };
+
+       /* 48MHz reference crystal */
+       ref48: ref48M {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <48000000>;
+       };
 };
 
 &dcc {
                        #size-cells = <0>;
                        reg = <1>;
                        si5341: clock-generator@36 { /* SI5341 - u43 */
-                               compatible = "si5341";
+                               compatible = "silabs,si5341";
                                reg = <0x36>;
+                               #clock-cells = <2>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               clocks = <&ref48>;
+                               clock-names = "xtal";
+                               clock-output-names = "si5341";
+
+                               si5341_2: out@2 {
+                                       /* refclk2 for PS-GT, used for USB3 */
+                                       reg = <2>;
+                                       always-on; /* assigned-clocks does not enable, so do it here */
+                               };
+                               si5341_3: out@3 {
+                                       /* refclk3 for PS-GT, used for SATA */
+                                       reg = <3>;
+                                       always-on; /* assigned-clocks does not enable, so do it here */
+                               };
+                               si5341_5: out@5 {
+                                       /* refclk5 PL CLK100 */
+                                       reg = <5>;
+                                       always-on; /* assigned-clocks does not enable, so do it here */
+                               };
+                               si5341_6: out@6 {
+                                       /* refclk6 PL CLK125 */
+                                       reg = <6>;
+                                       always-on; /* assigned-clocks does not enable, so do it here */
+                               };
+                               si5341_9: out@9 {
+                                       /* refclk9 used for PS_REF_CLK 33.3 MHz */
+                                       reg = <9>;
+                                       always-on; /* assigned-clocks does not enable, so do it here */
+                               };
                        };
-
                };
                i2c_si570_user_c0: i2c@2 {
                        #address-cells = <1>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <4>;
-                       /* U409B - 8a34001 */
+                       idt_8a34001: phc@5b {
+                               compatible = "idt,8a34001"; /* u409B */
+                               reg = <0x5b>;
+                       };
                };
                i2c_clk104: i2c@5 {
                        #address-cells = <1>;
        };
 };
 
+&psgtr {
+       status = "okay";
+       /* pcie, sata, usb3, dp */
+       clocks = <&si5341 0 5>, <&si5341 0 3>, <&si5341 0 2>, <&si5341 0 0>;
+       clock-names = "ref0", "ref1", "ref2", "ref3";
+};
+
 &rtc {
        status = "okay";
 };
        ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
        ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
        ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
-       phy-names = "sata-phy";
-       phys = <&lane3 PHY_TYPE_SATA 1 3 125000000>;
+       phys = <&psgtr 3 PHY_TYPE_SATA 1 3>;
 };
 
 /* SD1 with level shifter */
        xlnx,mio-bank = <1>;
 };
 
-&serdes {
-       status = "okay";
-};
-
 &uart0 {
        status = "okay";
 };
        status = "okay";
        dr_mode = "host";
        snps,usb3_lpm_capable;
-       phy-names = "usb3-phy";
-       phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
 };
index 511727f..2302b07 100644 (file)
                compatible = "iio-hwmon";
                io-channels = <&dac_avcc 0>, <&dac_avcc 1>, <&dac_avcc 2>, <&dac_avcc 3>;
        };
+
+       /* 48MHz reference crystal */
+       ref48: ref48M {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <48000000>;
+       };
+};
+
+&psgtr {
+       status = "okay";
+       /* pcie, sata, usb3, dp */
+       clocks = <&si5341 0 5>, <&si5341 0 3>, <&si5341 0 2>, <&si5341 0 0>;
+       clock-names = "ref0", "ref1", "ref2", "ref3";
 };
 
 &dcc {
                        #size-cells = <0>;
                        reg = <1>;
                        si5341: clock-generator@36 { /* SI5341 - u43 */
-                               compatible = "si5341";
+                               compatible = "silabs,si5341";
                                reg = <0x36>;
+                               #clock-cells = <2>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               clocks = <&ref48>;
+                               clock-names = "xtal";
+                               clock-output-names = "si5341";
+
+                               si5341_2: out@2 {
+                                       /* refclk2 for PS-GT, used for USB3 */
+                                       reg = <2>;
+                                       always-on; /* assigned-clocks does not enable, so do it here */
+                               };
+                               si5341_3: out@3 {
+                                       /* refclk3 for PS-GT, used for SATA */
+                                       reg = <3>;
+                                       always-on; /* assigned-clocks does not enable, so do it here */
+                               };
+                               si5341_5: out@5 {
+                                       /* refclk5 PL CLK100 */
+                                       reg = <5>;
+                                       always-on; /* assigned-clocks does not enable, so do it here */
+                               };
+                               si5341_6: out@6 {
+                                       /* refclk6 PL CLK125 */
+                                       reg = <6>;
+                                       always-on; /* assigned-clocks does not enable, so do it here */
+                               };
+                               si5341_9: out@9 {
+                                       /* refclk9 used for PS_REF_CLK 33.3 MHz */
+                                       reg = <9>;
+                                       always-on; /* assigned-clocks does not enable, so do it here */
+                               };
                        };
-
                };
                i2c_si570_user_c0: i2c@2 {
                        #address-cells = <1>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <4>;
-                       /* U409B - 8a34001 */
+                       idt_8a34001: phc@5b {
+                               compatible = "idt,8a34001"; /* u409B */
+                               reg = <0x5b>;
+                       };
                };
                i2c_clk104: i2c@5 {
                        #address-cells = <1>;
        ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
        ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
        ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
-       phy-names = "sata-phy";
-       phys = <&lane3 PHY_TYPE_SATA 1 3 125000000>;
+       phys = <&psgtr 3 PHY_TYPE_SATA 1 3>;
 };
 
 /* SD1 with level shifter */
        xlnx,mio-bank = <1>;
 };
 
-&serdes {
-       status = "okay";
-};
-
 &uart0 {
        status = "okay";
 };
        status = "okay";
        dr_mode = "host";
        snps,usb3_lpm_capable;
-       phy-names = "usb3-phy";
-       phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
 };
index aa0ac95..84d9770 100644 (file)
@@ -12,6 +12,7 @@
  * the License, or (at your option) any later version.
  */
 
+#include <dt-bindings/dma/xlnx-zynqmp-dpdma.h>
 #include <dt-bindings/power/xlnx-zynqmp-power.h>
 #include <dt-bindings/reset/xlnx-zynqmp-resets.h>
 
                                mbox-names = "tx", "rx";
                        };
 
+                       nvmem_firmware {
+                               compatible = "xlnx,zynqmp-nvmem-fw";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+
+                               soc_revision: soc_revision@0 {
+                                       reg = <0x0 0x4>;
+                               };
+                       };
+
                        zynqmp_pcap: pcap {
                                compatible = "xlnx,zynqmp-pcap-fpga";
                                clock-names = "ref_clk";
                        };
 
+                       xlnx_aes: zynqmp-aes {
+                               compatible = "xlnx,zynqmp-aes";
+                       };
+
                        zynqmp_reset: reset-controller {
                                compatible = "xlnx,zynqmp-reset";
                                #reset-cells = <1>;
                ranges;
        };
 
-       nvmem_firmware {
-               compatible = "xlnx,zynqmp-nvmem-fw";
-               #address-cells = <1>;
-               #size-cells = <1>;
-
-               soc_revision: soc_revision@0 {
-                       reg = <0x0 0x4>;
-               };
-       };
-
        amba: axi {
                compatible = "simple-bus";
                u-boot,dm-pre-reloc;
                        interrupts = <0 112 4>;
                };
 
-               nand0: nand@ff100000 {
-                       compatible = "arasan,nfc-v3p10";
+               nand0: nand-controller@ff100000 {
+                       compatible = "xlnx,zynqmp-nand-controller", "arasan,nfc-v3p10";
                        status = "disabled";
                        reg = <0x0 0xff100000 0x0 0x1000>;
-                       clock-names = "clk_sys", "clk_flash";
+                       clock-names = "controller", "bus";
                        interrupt-parent = <&gic>;
                        interrupts = <0 14 4>;
                        #address-cells = <1>;
                        power-domains = <&zynqmp_firmware PD_QSPI>;
                };
 
+               psgtr: phy@fd400000 {
+                       compatible = "xlnx,zynqmp-psgtr-v1.1";
+                       status = "disabled";
+                       reg = <0x0 0xfd400000 0x0 0x40000>,
+                             <0x0 0xfd3d0000 0x0 0x1000>;
+                       reg-names = "serdes", "siou";
+                       #phy-cells = <4>;
+               };
+
                rtc: rtc@ffa60000 {
                        compatible = "xlnx,zynqmp-rtc";
                        status = "disabled";
                        calibration = <0x8000>;
                };
 
-               serdes: zynqmp_phy@fd400000 {
-                       compatible = "xlnx,zynqmp-psgtr";
-                       status = "disabled";
-                       reg = <0x0 0xfd400000 0x0 0x40000>,
-                             <0x0 0xfd3d0000 0x0 0x1000>,
-                             <0x0 0xff5e0000 0x0 0x1000>;
-                       reg-names = "serdes", "siou", "lpd";
-                       nvmem-cells = <&soc_revision>;
-                       nvmem-cell-names = "soc_revision";
-                       resets = <&zynqmp_reset ZYNQMP_RESET_SATA>,
-                                <&zynqmp_reset ZYNQMP_RESET_USB0_CORERESET>,
-                                <&zynqmp_reset ZYNQMP_RESET_USB1_CORERESET>,
-                                <&zynqmp_reset ZYNQMP_RESET_USB0_HIBERRESET>,
-                                <&zynqmp_reset ZYNQMP_RESET_USB1_HIBERRESET>,
-                                <&zynqmp_reset ZYNQMP_RESET_USB0_APB>,
-                                <&zynqmp_reset ZYNQMP_RESET_USB1_APB>,
-                                <&zynqmp_reset ZYNQMP_RESET_DP>,
-                                <&zynqmp_reset ZYNQMP_RESET_GEM0>,
-                                <&zynqmp_reset ZYNQMP_RESET_GEM1>,
-                                <&zynqmp_reset ZYNQMP_RESET_GEM2>,
-                                <&zynqmp_reset ZYNQMP_RESET_GEM3>;
-                       reset-names = "sata_rst", "usb0_crst", "usb1_crst",
-                                     "usb0_hibrst", "usb1_hibrst", "usb0_apbrst",
-                                     "usb1_apbrst", "dp_rst", "gem0_rst",
-                                     "gem1_rst", "gem2_rst", "gem3_rst";
-                       lane0: lane0 {
-                               #phy-cells = <4>;
-                       };
-                       lane1: lane1 {
-                               #phy-cells = <4>;
-                       };
-                       lane2: lane2 {
-                               #phy-cells = <4>;
-                       };
-                       lane3: lane3 {
-                               #phy-cells = <4>;
-                       };
-               };
-
                sata: ahci@fd0c0000 {
                        compatible = "ceva,ahci-1v84";
                        status = "disabled";
                        xlnx,device_id = <0>;
                        #stream-id-cells = <1>;
                        iommus = <&smmu 0x870>;
-                       power-domains = <&zynqmp_firmware PD_SD_0>;
                        nvmem-cells = <&soc_revision>;
                        nvmem-cell-names = "soc_revision";
                        #clock-cells = <1>;
                        clock-output-names = "clk_out_sd0", "clk_in_sd0";
+                       power-domains = <&zynqmp_firmware PD_SD_0>;
                };
 
                sdhci1: mmc@ff170000 {
                        xlnx,device_id = <1>;
                        #stream-id-cells = <1>;
                        iommus = <&smmu 0x871>;
-                       power-domains = <&zynqmp_firmware PD_SD_1>;
                        nvmem-cells = <&soc_revision>;
                        nvmem-cell-names = "soc_revision";
                        #clock-cells = <1>;
                        clock-output-names = "clk_out_sd1", "clk_in_sd1";
+                       power-domains = <&zynqmp_firmware PD_SD_1>;
                };
 
                smmu: iommu@fd800000 {
                        };
                };
 
-               xlnx_dpdma: dma@fd4c0000 {
-                       compatible = "xlnx,dpdma";
+               zynqmp_dpdma: dma-controller@fd4c0000 {
+                       compatible = "xlnx,zynqmp-dpdma";
                        status = "disabled";
                        reg = <0x0 0xfd4c0000 0x0 0x1000>;
                        interrupts = <0 122 4>;
                        interrupt-parent = <&gic>;
                        clock-names = "axi_clk";
                        power-domains = <&zynqmp_firmware PD_DP>;
-                       dma-channels = <6>;
                        #dma-cells = <1>;
-                       dma-video0channel {
-                               compatible = "xlnx,video0";
-                       };
-                       dma-video1channel {
-                               compatible = "xlnx,video1";
-                       };
-                       dma-video2channel {
-                               compatible = "xlnx,video2";
-                       };
-                       dma-graphicschannel {
-                               compatible = "xlnx,graphics";
-                       };
-                       dma-audio0channel {
-                               compatible = "xlnx,audio0";
-                       };
-                       dma-audio1channel {
-                               compatible = "xlnx,audio1";
-                       };
                };
 
-               zynqmp_dpsub: zynqmp-display@fd4a0000 {
+               zynqmp_dpsub: display@fd4a0000 {
                        compatible = "xlnx,zynqmp-dpsub-1.7";
                        status = "disabled";
                        reg = <0x0 0xfd4a0000 0x0 0x1000>,
                        reg-names = "dp", "blend", "av_buf", "aud";
                        interrupts = <0 119 4>;
                        interrupt-parent = <&gic>;
-
                        clock-names = "dp_apb_clk", "dp_aud_clk",
                                      "dp_vtc_pixel_clk_in";
-
                        power-domains = <&zynqmp_firmware PD_DP>;
-
-                       vid-layer {
-                               dma-names = "vid0", "vid1", "vid2";
-                               dmas = <&xlnx_dpdma 0>,
-                                      <&xlnx_dpdma 1>,
-                                      <&xlnx_dpdma 2>;
-                       };
-
-                       gfx-layer {
-                               dma-names = "gfx0";
-                               dmas = <&xlnx_dpdma 3>;
-                       };
-
-                       /* dummy node to indicate there's no child i2c device */
-                       i2c-bus {
-                       };
-
-                       zynqmp_dp_snd_codec0: zynqmp_dp_snd_codec0 {
-                               compatible = "xlnx,dp-snd-codec";
-                               clock-names = "aud_clk";
-                       };
-
-                       zynqmp_dp_snd_pcm0: zynqmp_dp_snd_pcm0 {
-                               compatible = "xlnx,dp-snd-pcm";
-                               dmas = <&xlnx_dpdma 4>;
-                               dma-names = "tx";
-                       };
-
-                       zynqmp_dp_snd_pcm1: zynqmp_dp_snd_pcm1 {
-                               compatible = "xlnx,dp-snd-pcm";
-                               dmas = <&xlnx_dpdma 5>;
-                               dma-names = "tx";
-                       };
-
-                       zynqmp_dp_snd_card0: zynqmp_dp_snd_card {
-                               compatible = "xlnx,dp-snd-card";
-                               xlnx,dp-snd-pcm = <&zynqmp_dp_snd_pcm0>,
-                                                 <&zynqmp_dp_snd_pcm1>;
-                               xlnx,dp-snd-codec = <&zynqmp_dp_snd_codec0>;
-                       };
+                       resets = <&zynqmp_reset ZYNQMP_RESET_DP>;
+                       dma-names = "vid0", "vid1", "vid2", "gfx0";
+                       dmas = <&zynqmp_dpdma ZYNQMP_DPDMA_VIDEO0>,
+                              <&zynqmp_dpdma ZYNQMP_DPDMA_VIDEO1>,
+                              <&zynqmp_dpdma ZYNQMP_DPDMA_VIDEO2>,
+                              <&zynqmp_dpdma ZYNQMP_DPDMA_GRAPHICS>;
                };
        };
 };
index c20e05e..b10edf8 100644 (file)
@@ -35,7 +35,6 @@ void l2_cache_disable(void);
 void set_section_dcache(int section, enum dcache_option option);
 
 void arm_init_before_mmu(void);
-void arm_init_domains(void);
 void cpu_cache_initialization(void);
 void dram_bank_mmu_setup(int bank);
 
index 5fe8369..11fceec 100644 (file)
@@ -397,20 +397,6 @@ static inline void set_cr(unsigned int val)
        isb();
 }
 
-static inline unsigned int get_dacr(void)
-{
-       unsigned int val;
-       asm("mrc p15, 0, %0, c3, c0, 0  @ get DACR" : "=r" (val) : : "cc");
-       return val;
-}
-
-static inline void set_dacr(unsigned int val)
-{
-       asm volatile("mcr p15, 0, %0, c3, c0, 0 @ set DACR"
-         : : "r" (val) : "cc");
-       isb();
-}
-
 #ifdef CONFIG_ARMV7_LPAE
 /* Long-Descriptor Translation Table Level 1/2 Bits */
 #define TTB_SECT_XN_MASK       (1ULL << 54)
@@ -475,7 +461,7 @@ enum dcache_option {
 #define TTB_SECT_XN_MASK       (1 << 4)
 #define TTB_SECT_C_MASK                (1 << 3)
 #define TTB_SECT_B_MASK                (1 << 2)
-#define TTB_SECT                       (2 << 0)
+#define TTB_SECT               (2 << 0)
 
 /*
  * Short-descriptor format memory region attributes, without TEX remap
@@ -489,7 +475,7 @@ enum dcache_option {
  */
 enum dcache_option {
        DCACHE_OFF = TTB_SECT_DOMAIN(0) | TTB_SECT_XN_MASK | TTB_SECT,
-       DCACHE_WRITETHROUGH = DCACHE_OFF | TTB_SECT_C_MASK,
+       DCACHE_WRITETHROUGH = TTB_SECT_DOMAIN(0) | TTB_SECT | TTB_SECT_C_MASK,
        DCACHE_WRITEBACK = DCACHE_WRITETHROUGH | TTB_SECT_B_MASK,
        DCACHE_WRITEALLOC = DCACHE_WRITEBACK | TTB_SECT_TEX(1),
 };
index 24050e5..aab1bf4 100644 (file)
@@ -22,10 +22,6 @@ __weak void arm_init_before_mmu(void)
 {
 }
 
-__weak void arm_init_domains(void)
-{
-}
-
 static void set_section_phys(int section, phys_addr_t phys,
                             enum dcache_option option)
 {
@@ -203,11 +199,12 @@ static inline void mmu_setup(void)
        asm volatile("mcr p15, 0, %0, c2, c0, 0"
                     : : "r" (gd->arch.tlb_addr) : "memory");
 #endif
-       /* Set the access control to all-supervisor */
+       /*
+        * initial value of Domain Access Control Register (DACR)
+        * Set the access control to client (1U) for each of the 16 domains
+        */
        asm volatile("mcr p15, 0, %0, c3, c0, 0"
-                    : : "r" (~0));
-
-       arm_init_domains();
+                    : : "r" (0x55555555));
 
        /* and enable the mmu */
        reg = get_cr(); /* get control reg. */
index 05bb1a3..6dc27d1 100644 (file)
@@ -53,7 +53,7 @@ int disable_interrupts(void)
 void bad_mode (void)
 {
        panic ("Resetting CPU ...\n");
-       reset_cpu(0);
+       reset_cpu();
 }
 
 static void show_efi_loaded_images(struct pt_regs *regs)
index 2ae1c5b..277854a 100644 (file)
@@ -59,7 +59,7 @@ void dump_regs(struct autosave_regs *regs)
 void bad_mode(void)
 {
        panic("Resetting CPU ...\n");
-       reset_cpu(0);
+       reset_cpu();
 }
 
 void do_hard_fault(struct autosave_regs *autosave_regs)
index 4f1a768..95169ba 100644 (file)
@@ -39,7 +39,7 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        disable_interrupts();
 
        reset_misc();
-       reset_cpu(0);
+       reset_cpu();
 
        /*NOTREACHED*/
        return 0;
index d92bc57..91e3751 100644 (file)
@@ -24,7 +24,7 @@ void  __attribute__((weak)) board_reset(void)
        /* true empty function for defining weak symbol */
 }
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        at91_st_t *st = (at91_st_t *) ATMEL_BASE_ST;
 
index 71d7582..994f42e 100644 (file)
@@ -71,10 +71,10 @@ POS1:
        str     r0, [r1]
 
        /* Reading the PMC Status to detect when the Main Oscillator is enabled */
-       mov     r4, #AT91_PMC_IXR_MOSCS
+       mov     r6, #AT91_PMC_IXR_MOSCS
 MOSCS_Loop:
        ldr     r3, [r2]
-       and     r3, r4, r3
+       and     r3, r6, r3
        cmp     r3, #AT91_PMC_IXR_MOSCS
        bne     MOSCS_Loop
 
@@ -89,10 +89,10 @@ MOSCS_Loop:
        str     r0, [r1]
 
        /* Reading the PMC Status register to detect when the PLLA is locked */
-       mov     r4, #AT91_PMC_IXR_LOCKA
+       mov     r6, #AT91_PMC_IXR_LOCKA
 MOSCS_Loop1:
        ldr     r3, [r2]
-       and     r3, r4, r3
+       and     r3, r6, r3
        cmp     r3, #AT91_PMC_IXR_LOCKA
        bne     MOSCS_Loop1
 
@@ -109,10 +109,10 @@ MOSCS_Loop1:
        str     r0, [r1]
 
        /* Reading the PMC Status to detect when the Master clock is ready */
-       mov     r4, #AT91_PMC_IXR_MCKRDY
+       mov     r6, #AT91_PMC_IXR_MCKRDY
 MCKRDY_Loop:
        ldr     r3, [r2]
-       and     r3, r4, r3
+       and     r3, r6, r3
        cmp     r3, #AT91_PMC_IXR_MCKRDY
        bne     MCKRDY_Loop
 
@@ -120,10 +120,10 @@ MCKRDY_Loop:
        str     r0, [r1]
 
        /* Reading the PMC Status to detect when the Master clock is ready */
-       mov     r4, #AT91_PMC_IXR_MCKRDY
+       mov     r6, #AT91_PMC_IXR_MCKRDY
 MCKRDY_Loop1:
        ldr     r3, [r2]
-       and     r3, r4, r3
+       and     r3, r6, r3
        cmp     r3, #AT91_PMC_IXR_MCKRDY
        bne     MCKRDY_Loop1
 PLL_setup_end:
index 56fbbd9..6acbfa3 100644 (file)
@@ -12,7 +12,7 @@
 #include <asm/arch/at91_rstc.h>
 
 /* Reset the cpu by telling the reset controller to do so */
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        at91_rstc_t *rstc = (at91_rstc_t *) ATMEL_BASE_RSTC;
 
index 8f4c81d..1ea415e 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/arch/at91_rstc.h>
 
 /* Reset the cpu by telling the reset controller to do so */
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        at91_rstc_t *rstc = (at91_rstc_t *)ATMEL_BASE_RSTC;
 
index 35ac7b2..c3bd914 100644 (file)
@@ -44,6 +44,7 @@ struct atmel_pio4_port {
 #define ATMEL_PIO_DIR_MASK             BIT(8)
 #define ATMEL_PIO_PUEN_MASK            BIT(9)
 #define ATMEL_PIO_PDEN_MASK            BIT(10)
+#define ATMEL_PIO_SR                   BIT(11)
 #define ATMEL_PIO_IFEN_MASK            BIT(12)
 #define ATMEL_PIO_IFSCEN_MASK          BIT(13)
 #define ATMEL_PIO_OPD_MASK             BIT(14)
index 2b4ccd4..f13ac0c 100644 (file)
@@ -48,7 +48,7 @@ __reset_cpu(struct bcm2835_wdog_regs *wdog_regs, ulong ticks)
        writel(BCM2835_WDOG_PASSWORD | rstc, &wdog_regs->rstc);
 }
 
-void reset_cpu(ulong ticks)
+void reset_cpu(void)
 {
        struct bcm2835_wdog_regs *regs =
                (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR;
index 4e6031a..0d59eb6 100644 (file)
@@ -12,7 +12,7 @@
 #include <asm/arch/timer_defs.h>
 #include <asm/arch/hardware.h>
 
-void reset_cpu(unsigned long a)
+void reset_cpu(void)
 {
        struct davinci_timer *const wdttimer =
                (struct davinci_timer *)DAVINCI_WDOG_BASE;
index 810fa34..a07c87a 100644 (file)
@@ -20,7 +20,7 @@ extern void _main(void);
 void *secondary_boot_addr = (void *)_main;
 #endif /* CONFIG_TARGET_ESPRESSO7420 */
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 #ifdef CONFIG_CPU_V7A
        writel(0x1, samsung_get_base_swreset());
index 5f37282..e6bc977 100644 (file)
@@ -923,7 +923,7 @@ usb_modify_speed:
 #endif
 
 #if !CONFIG_IS_ENABLED(SYSRESET)
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
 
index 8dd6b4d..320f24d 100644 (file)
@@ -197,7 +197,7 @@ void s_init(void)
 #endif
 
 #ifndef CONFIG_ULP_WATCHDOG
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        setbits_le32(SIM0_RBASE, SIM_SOPT1_A7_SW_RESET);
        while (1)
index 4fbf148..9191f68 100644 (file)
@@ -320,7 +320,7 @@ int fdt_disable_node(void *blob, char *node_path)
 #endif
 
 #ifndef CONFIG_SYSRESET
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 }
 #endif
index 7dea600..9ee3284 100644 (file)
@@ -345,7 +345,7 @@ void ddr3_check_ecc_int(u32 base)
 
                if (!ecc_test) {
                        puts("Reseting the device ...\n");
-                       reset_cpu(0);
+                       reset_cpu();
                }
        }
 
@@ -445,7 +445,7 @@ void ddr3_err_reset_workaround(void)
                tmp &= ~KS2_RSTYPE_PLL_SOFT;
                __raw_writel(tmp, KS2_RSTCTRL_RSCFG);
 
-               reset_cpu(0);
+               reset_cpu();
        }
 }
 #endif
index 4950f14..5b95f60 100644 (file)
@@ -192,7 +192,7 @@ int arch_cpu_init(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        volatile u32 *rstctrl = (volatile u32 *)(KS2_RSTCTRL);
        u32 tmp;
index 551c22a..9c818fa 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/arch/soc.h>
 #include <mvebu_mmc.h>
 
-void reset_cpu(unsigned long ignored)
+void reset_cpu(void)
 {
        struct kwcpu_registers *cpureg =
            (struct kwcpu_registers *)KW_CPU_REG_BASE;
index 32af620..c2586d0 100644 (file)
 static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
 static struct wdt_regs  *wdt = (struct wdt_regs *)WDT_BASE;
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        /* Enable watchdog clock */
        setbits_le32(&clk->timclk_ctrl, CLK_TIMCLK_WATCHDOG);
 
-       /* To be compatible with the original U-Boot code:
-        * addr: - 0: perform hard reset.
-        *       - !=0: perform a soft reset; i.e. "RESOUT_N" not asserted). */
-       if (addr == 0) {
-               /* Reset pulse length is 13005 peripheral clock frames */
-               writel(13000, &wdt->pulse);
+       /* Reset pulse length is 13005 peripheral clock frames */
+       writel(13000, &wdt->pulse);
 
-               /* Force WDOG_RESET2 and RESOUT_N signal active */
-               writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1
-                      | WDTIM_MCTRL_M_RES2, &wdt->mctrl);
-       } else {
-               /* Force match output active */
-               writel(0x01, &wdt->emr);
-
-               /* Internal reset on match output (no pulse on "RESOUT_N") */
-               writel(WDTIM_MCTRL_M_RES1, &wdt->mctrl);
-       }
+       /* Force WDOG_RESET2 and RESOUT_N signal active */
+       writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1 | WDTIM_MCTRL_M_RES2,
+              &wdt->mctrl);
 
        while (1)
                /* NOP */;
index 7f40ba9..e067604 100644 (file)
@@ -36,12 +36,20 @@ config TARGET_MT7629
        bool "MediaTek MT7629 SoC"
        select CPU_V7A
        select SPL
-       select BINMAN
        help
          The MediaTek MT7629 is a ARM-based SoC with a dual-core Cortex-A7
          including DDR3, crypto engine, 3x3 11n/ac Wi-Fi, Gigabit Ethernet,
          switch, USB3.0, PCIe, UART, SPI, I2C and PWM.
 
+config TARGET_MT8183
+       bool "MediaTek MT8183 SoC"
+       select ARM64
+       help
+         The MediaTek MT8183 is a ARM64-based SoC with a quad-core Cortex-A73 and
+         a quad-core Cortex-A53. It is including UART, SPI, USB3.0 dual role,
+         SD and MMC cards, UFS, PWM, I2C, I2S, S/PDIF, and several LPDDR3
+         and LPDDR4 options.
+
 config TARGET_MT8512
         bool "MediaTek MT8512 M1 Board"
         select ARM64
@@ -75,8 +83,9 @@ endchoice
 source "board/mediatek/mt7622/Kconfig"
 source "board/mediatek/mt7623/Kconfig"
 source "board/mediatek/mt7629/Kconfig"
+source "board/mediatek/mt8183/Kconfig"
 source "board/mediatek/mt8512/Kconfig"
+source "board/mediatek/mt8516/Kconfig"
 source "board/mediatek/mt8518/Kconfig"
-source "board/mediatek/pumpkin/Kconfig"
 
 endif
index 290d2c7..0f5b0c1 100644 (file)
@@ -7,5 +7,6 @@ obj-$(CONFIG_MT8512) += mt8512/
 obj-$(CONFIG_TARGET_MT7622) += mt7622/
 obj-$(CONFIG_TARGET_MT7623) += mt7623/
 obj-$(CONFIG_TARGET_MT7629) += mt7629/
+obj-$(CONFIG_TARGET_MT8183) += mt8183/
 obj-$(CONFIG_TARGET_MT8516) += mt8516/
 obj-$(CONFIG_TARGET_MT8518) += mt8518/
index 7f6ce80..e501907 100644 (file)
@@ -27,7 +27,7 @@ int dram_init(void)
 
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        psci_system_reset();
 }
similarity index 65%
rename from board/mediatek/pumpkin/Makefile
rename to arch/arm/mach-mediatek/mt8183/Makefile
index 75fce4a..886ab7e 100644 (file)
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier:     GPL-2.0
 
-obj-y += pumpkin.o
+obj-y += init.o
diff --git a/arch/arm/mach-mediatek/mt8183/init.c b/arch/arm/mach-mediatek/mt8183/init.c
new file mode 100644 (file)
index 0000000..877f387
--- /dev/null
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Copyright (C) 2021 BayLibre, SAS
+ * Author: Fabien Parent <fparent@baylibre.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <ram.h>
+#include <asm/arch/misc.h>
+#include <asm/armv8/mmu.h>
+#include <asm/sections.h>
+#include <asm/system.h>
+#include <dm/uclass.h>
+#include <dt-bindings/clock/mt8516-clk.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+       int ret;
+
+       ret = fdtdec_setup_memory_banksize();
+       if (ret)
+               return ret;
+
+       return fdtdec_setup_mem_size_base();
+}
+
+int dram_init_banksize(void)
+{
+       gd->bd->bi_dram[0].start = gd->ram_base;
+       gd->bd->bi_dram[0].size = gd->ram_size;
+
+       return 0;
+}
+
+int mtk_pll_early_init(void)
+{
+       return 0;
+}
+
+int mtk_soc_early_init(void)
+{
+       return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+       psci_system_reset();
+}
+
+int print_cpuinfo(void)
+{
+       printf("CPU:   MediaTek MT8183\n");
+       return 0;
+}
+
+static struct mm_region mt8183_mem_map[] = {
+       {
+               /* DDR */
+               .virt = 0x40000000UL,
+               .phys = 0x40000000UL,
+               .size = 0x80000000UL,
+               .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE,
+       }, {
+               .virt = 0x00000000UL,
+               .phys = 0x00000000UL,
+               .size = 0x20000000UL,
+               .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+                        PTE_BLOCK_NON_SHARE |
+                        PTE_BLOCK_PXN | PTE_BLOCK_UXN
+       }, {
+               0,
+       }
+};
+struct mm_region *mem_map = mt8183_mem_map;
index c14e7d2..b7050df 100644 (file)
@@ -43,7 +43,7 @@ int dram_init_banksize(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct udevice *watchdog_dev = NULL;
 
index 3771152..3460dcc 100644 (file)
@@ -85,7 +85,7 @@ int mtk_soc_early_init(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        psci_system_reset();
 }
index 28b00c3..f7e03de 100644 (file)
@@ -42,7 +42,7 @@ int dram_init_banksize(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        psci_system_reset();
 }
index 34b3c8f..1690b6b 100644 (file)
@@ -167,7 +167,7 @@ int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct pt_regs regs;
 
@@ -182,7 +182,7 @@ void reset_cpu(ulong addr)
                ;
 }
 #else
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        psci_system_reset();
 }
index 70f76c7..0cf60d7 100644 (file)
@@ -314,7 +314,7 @@ int a3700_fdt_fix_pcie_regions(void *blob)
        return fdt_setprop_inplace(blob, node, "ranges", new_ranges, len);
 }
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        /*
         * Write magic number of 0x1d1e to North Bridge Warm Reset register
index 529dac9..474327a 100644 (file)
@@ -104,7 +104,7 @@ void enable_caches(void)
        dcache_enable();
 }
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        u32 reg;
 
index 7dce11e..0b935c4 100644 (file)
@@ -42,7 +42,7 @@ void lowlevel_init(void)
         */
 }
 
-void reset_cpu(unsigned long ignored)
+void reset_cpu(void)
 {
        struct mvebu_system_registers *reg =
                (struct mvebu_system_registers *)MVEBU_SYSTEM_REG_BASE;
index 10b3963..dda16db 100644 (file)
@@ -10,4 +10,3 @@ obj-y                         += nx_gpio.o
 obj-y                          += tieoff.o
 obj-$(CONFIG_ARCH_S5P4418)     += reg-call.o
 obj-$(CONFIG_ARCH_S5P4418)     += nx_sec_reg.o
-obj-$(CONFIG_CMD_BOOTL)                += cmd_boot_linux.o
diff --git a/arch/arm/mach-nexell/cmd_boot_linux.c b/arch/arm/mach-nexell/cmd_boot_linux.c
deleted file mode 100644 (file)
index 9b38d38..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2016 nexell
- * jhkim <jhkim@nexell.co.kr>
- */
-
-#include <common.h>
-#include <bootm.h>
-#include <command.h>
-#include <environment.h>
-#include <errno.h>
-#include <image.h>
-#include <fdt_support.h>
-#include <asm/global_data.h>
-
-#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_CLI_FRAMEWORK)
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static bootm_headers_t linux_images;
-
-static void boot_go_set_os(cmd_tbl_t *cmdtp, int flag, int argc,
-                          char * const argv[],
-                          bootm_headers_t *images)
-{
-       char * const img_addr = argv[0];
-
-       images->os.type = IH_TYPE_KERNEL;
-       images->os.comp = IH_COMP_NONE;
-       images->os.os = IH_OS_LINUX;
-       images->os.load = simple_strtoul(img_addr, NULL, 16);
-       images->ep = images->os.load;
-#if defined(CONFIG_ARM)
-       images->os.arch = IH_ARCH_ARM;
-#elif defined(CONFIG_ARM64)
-       images->os.arch = IH_ARCH_ARM64;
-#else
-       #error "Not support architecture ..."
-#endif
-       if (!IS_ENABLED(CONFIG_OF_LIBFDT) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
-               /* set DTB address for linux kernel */
-               if (argc > 2) {
-                       unsigned long ft_addr;
-
-                       ft_addr = simple_strtol(argv[2], NULL, 16);
-                       images->ft_addr = (char *)ft_addr;
-
-                       /*
-                        * if not defined IMAGE_ENABLE_OF_LIBFDT,
-                        * must be set to fdt address
-                        */
-                       if (!IMAGE_ENABLE_OF_LIBFDT)
-                               gd->bd->bi_boot_params = ft_addr;
-
-                       debug("## set ft:%08lx and boot params:%08lx [control of:%s]"
-                             "...\n", ft_addr, gd->bd->bi_boot_params,
-                             IMAGE_ENABLE_OF_LIBFDT ? "on" : "off");
-               }
-       }
-}
-
-#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
-static void boot_start_lmb(bootm_headers_t *images)
-{
-       ulong           mem_start;
-       phys_size_t     mem_size;
-
-       lmb_init(&images->lmb);
-
-       mem_start = getenv_bootm_low();
-       mem_size = getenv_bootm_size();
-
-       lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
-
-       arch_lmb_reserve(&images->lmb);
-       board_lmb_reserve(&images->lmb);
-}
-#else
-#define lmb_reserve(lmb, base, size)
-static inline void boot_start_lmb(bootm_headers_t *images) { }
-#endif
-
-int do_boot_linux(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-       boot_os_fn *boot_fn;
-       bootm_headers_t *images = &linux_images;
-       int flags;
-       int ret;
-
-       boot_start_lmb(images);
-
-       flags  = BOOTM_STATE_START;
-
-       argc--; argv++;
-       boot_go_set_os(cmdtp, flag, argc, argv, images);
-
-       if (IS_ENABLED(CONFIG_OF_LIBFDT)) {
-               /* find flattened device tree */
-               ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images,
-                                  &images->ft_addr, &images->ft_len);
-               if (ret) {
-                       puts("Could not find a valid device tree\n");
-                       return 1;
-               }
-               set_working_fdt_addr((ulong)images->ft_addr);
-       }
-
-       if (!IS_ENABLED(CONFIG_OF_LIBFDT))
-               flags |= BOOTM_STATE_OS_GO;
-
-       boot_fn = do_bootm_linux;
-       ret = boot_fn(flags, argc, argv, images);
-
-       if (ret == BOOTM_ERR_UNIMPLEMENTED)
-               show_boot_progress(BOOTSTAGE_ID_DECOMP_UNIMPL);
-       else if (ret == BOOTM_ERR_RESET)
-               do_reset(cmdtp, flag, argc, argv);
-
-       return ret;
-}
-
-U_BOOT_CMD(bootl, CONFIG_SYS_MAXARGS, 1, do_boot_linux,
-          "boot linux image from memory",
-          "[addr [arg ...]]\n    - boot linux image stored in memory\n"
-          "\tuse a '-' for the DTB address\n"
-);
-#endif
-
-#if defined(CONFIG_CMD_BOOTD) && !defined(CONFIG_CMD_BOOTM)
-int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-       return run_command(env_get("bootcmd"), flag);
-}
-
-U_BOOT_CMD(boot, 1, 1, do_bootd,
-          "boot default, i.e., run 'bootcmd'",
-          ""
-);
-
-/* keep old command name "bootd" for backward compatibility */
-U_BOOT_CMD(bootd, 1,   1,      do_bootd,
-          "boot default, i.e., run 'bootcmd'",
-          ""
-);
-#endif
index ce5f2b4..7bd74fe 100644 (file)
@@ -72,6 +72,6 @@ u64 get_page_table_size(void)
        return 0x80000;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index 8786815..afa458c 100644 (file)
@@ -68,6 +68,6 @@ u64 get_page_table_size(void)
        return 0x80000;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index 1b246f8..36db588 100644 (file)
@@ -41,9 +41,6 @@ DECLARE_GLOBAL_DATA_PTR;
 #define ARMV7_DCACHE_POLICY    DCACHE_WRITEBACK & ~TTB_SECT_XN_MASK
 #endif
 
-#define ARMV7_DOMAIN_CLIENT    1
-#define ARMV7_DOMAIN_MASK      (0x3 << 0)
-
 void enable_caches(void)
 {
 
@@ -67,17 +64,3 @@ void dram_bank_mmu_setup(int bank)
        for (i = start; i < end; i++)
                set_section_dcache(i, ARMV7_DCACHE_POLICY);
 }
-
-void arm_init_domains(void)
-{
-       u32 reg;
-
-       reg = get_dacr();
-       /*
-       * Set DOMAIN to client access so that all permissions
-       * set in pagetables are validated by the mmu.
-       */
-       reg &= ~ARMV7_DOMAIN_MASK;
-       reg |= ARMV7_DOMAIN_CLIENT;
-       set_dacr(reg);
-}
index 47ac865..edab9a9 100644 (file)
@@ -417,7 +417,7 @@ void omap_die_id(unsigned int *die_id)
        die_id[3] = readl((*ctrl)->control_std_fuse_die_id_3);
 }
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
        u32 omap_rev = omap_revision();
 
index 2bbd5fc..1fd79c2 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/arch/cpu.h>
 #include <linux/compiler.h>
 
-void __weak reset_cpu(unsigned long ignored)
+void __weak reset_cpu(void)
 {
        writel(PRM_RSTCTRL_RESET, PRM_RSTCTRL);
 }
index beae7b8..ffae9a0 100644 (file)
@@ -20,7 +20,7 @@
 
 #define BUFLEN 16
 
-void reset_cpu(unsigned long ignored)
+void reset_cpu(void)
 {
        struct orion5x_cpu_registers *cpureg =
            (struct orion5x_cpu_registers *)ORION5X_CPU_REG_BASE;
index 4d2b9d0..4baef2e 100644 (file)
@@ -74,7 +74,7 @@ int board_init(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        psci_system_reset();
 }
index b95c8e8..8127d33 100644 (file)
@@ -4,6 +4,8 @@ menu "Select Target SoC"
 
 config R8A774A1
        bool "Renesas SoC R8A774A1"
+       imply CLK_R8A774A1
+       imply PINCTRL_PFC_R8A774A1
 
 config R8A774B1
        bool "Renesas SoC R8A774B1"
@@ -13,6 +15,7 @@ config R8A774B1
 config R8A774C0
        bool "Renesas SoC R8A774C0"
        imply CLK_R8A774C0
+       imply PINCTRL_PFC_R8A774C0
 
 config R8A774E1
        bool "Renesas SoC R8A774E1"
@@ -99,6 +102,23 @@ config TARGET_EBISU
        help
           Support for Renesas R-Car Gen3 Ebisu platform
 
+config TARGET_HIHOPE_RZG2
+       bool "HiHope RZ/G2 board"
+       imply R8A774A1
+       imply R8A774B1
+       imply R8A774E1
+       imply SYS_MALLOC_F
+       imply MULTI_DTB_FIT
+       imply MULTI_DTB_FIT_USER_DEFINED_AREA
+       help
+          Support for RZG2 HiHope platform
+
+config TARGET_SILINUX_EK874
+       bool "Silicon Linux EK874 board"
+       imply R8A774C0
+       help
+          Support for Silicon Linux EK874 platform
+
 config TARGET_SALVATOR_X
        bool "Salvator-X board"
        imply R8A7795
@@ -133,12 +153,16 @@ source "board/renesas/ebisu/Kconfig"
 source "board/renesas/salvator-x/Kconfig"
 source "board/renesas/ulcb/Kconfig"
 source "board/beacon/beacon-rzg2m/Kconfig"
+source "board/hoperun/hihope-rzg2/Kconfig"
+source "board/silinux/ek874/Kconfig"
 
 config MULTI_DTB_FIT_UNCOMPRESS_SZ
+       default 0x80000 if TARGET_HIHOPE_RZG2
        default 0x80000 if TARGET_SALVATOR_X
        default 0x80000 if TARGET_ULCB
 
 config MULTI_DTB_FIT_USER_DEF_ADDR
+       default 0x49000000 if TARGET_HIHOPE_RZG2
        default 0x49000000 if TARGET_SALVATOR_X
        default 0x49000000 if TARGET_ULCB
 
index 3206bce..9f56af4 100644 (file)
@@ -22,7 +22,7 @@ cmd_objcopy = $(OBJCOPY) --gap-fill=0x00 $(OBJCOPYFLAGS) \
 spl/u-boot-spl.srec: spl/u-boot-spl FORCE
        $(call if_changed,objcopy)
 
-ifneq ($(CONFIG_R8A77990)$(CONFIG_R8A77995),)
+ifneq ($(CONFIG_R8A774C0)$(CONFIG_R8A77990)$(CONFIG_R8A77995),)
 #
 # The first 6 generate statements generate the R-Car Gen3 SCIF loader header.
 # The subsequent generate statements represent the following chunk of assembler
index 8c25325..1d68034 100644 (file)
@@ -8,7 +8,7 @@
 
 phys_addr_t socfpga_get_rstmgr_addr(void);
 
-void reset_cpu(ulong addr);
+void reset_cpu(void);
 
 void socfpga_per_reset(u32 reset, int set);
 void socfpga_per_reset_all(void);
index bc2db53..897ec13 100644 (file)
@@ -212,6 +212,35 @@ u32 get_bootmode(void)
 }
 
 /*
+ * weak function overidde: set the DDR/SYSRAM executable before to enable the
+ * MMU and configure DACR, for early early_enable_caches (SPL or pre-reloc)
+ */
+void dram_bank_mmu_setup(int bank)
+{
+       struct bd_info *bd = gd->bd;
+       int     i;
+       phys_addr_t start;
+       phys_size_t size;
+
+       if (IS_ENABLED(CONFIG_SPL_BUILD)) {
+               start = ALIGN_DOWN(STM32_SYSRAM_BASE, MMU_SECTION_SIZE);
+               size = ALIGN(STM32_SYSRAM_SIZE, MMU_SECTION_SIZE);
+       } else if (gd->flags & GD_FLG_RELOC) {
+               /* bd->bi_dram is available only after relocation */
+               start = bd->bi_dram[bank].start;
+               size =  bd->bi_dram[bank].size;
+       } else {
+               /* mark cacheable and executable the beggining of the DDR */
+               start = STM32_DDR_BASE;
+               size = CONFIG_DDR_CACHEABLE_SIZE;
+       }
+
+       for (i = start >> MMU_SECTION_SHIFT;
+            i < (start >> MMU_SECTION_SHIFT) + (size >> MMU_SECTION_SHIFT);
+            i++)
+               set_section_dcache(i, DCACHE_DEFAULT_OPTION);
+}
+/*
  * initialize the MMU and activate cache in SPL or in U-Boot pre-reloc stage
  * MMU/TLB is updated in enable_caches() for U-Boot after relocation
  * or is deactivated in U-Boot entry function start.S::cpu_init_cp15
@@ -228,17 +257,8 @@ static void early_enable_caches(void)
                gd->arch.tlb_addr = (unsigned long)&early_tlb;
        }
 
+       /* enable MMU (default configuration) */
        dcache_enable();
-
-       if (IS_ENABLED(CONFIG_SPL_BUILD))
-               mmu_set_region_dcache_behaviour(
-                       ALIGN_DOWN(STM32_SYSRAM_BASE, MMU_SECTION_SIZE),
-                       ALIGN(STM32_SYSRAM_SIZE, MMU_SECTION_SIZE),
-                       DCACHE_DEFAULT_OPTION);
-       else
-               mmu_set_region_dcache_behaviour(STM32_DDR_BASE,
-                                               CONFIG_DDR_CACHEABLE_SIZE,
-                                               DCACHE_DEFAULT_OPTION);
 }
 
 /*
index ad6977f..66e81ba 100644 (file)
@@ -13,6 +13,7 @@
 #include <log.h>
 #include <ram.h>
 #include <asm/global_data.h>
+#include <asm/system.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -41,6 +42,7 @@ int dram_init(void)
 
 ulong board_get_usable_ram_top(ulong total_size)
 {
+       phys_size_t size;
        phys_addr_t reg;
        struct lmb lmb;
 
@@ -48,10 +50,13 @@ ulong board_get_usable_ram_top(ulong total_size)
        lmb_init(&lmb);
        lmb_add(&lmb, gd->ram_base, gd->ram_size);
        boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob);
-       reg = lmb_alloc(&lmb, CONFIG_SYS_MALLOC_LEN + total_size, SZ_4K);
+       size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE),
+       reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE);
 
-       if (reg)
-               return ALIGN(reg + CONFIG_SYS_MALLOC_LEN + total_size, SZ_4K);
+       if (!reg)
+               reg = gd->ram_top - size;
 
-       return gd->ram_top;
+       mmu_set_region_dcache_behaviour(reg, size, DCACHE_DEFAULT_OPTION);
+
+       return reg + size;
 }
index 0135575..a29d115 100644 (file)
@@ -816,13 +816,14 @@ config VIDEO_SUNXI
        depends on !MACH_SUN9I
        depends on !MACH_SUN50I
        depends on !SUN50I_GEN_H6
-       select VIDEO
+       select DM_VIDEO
+       select DISPLAY
        imply VIDEO_DT_SIMPLEFB
        default y
        ---help---
-       Say Y here to add support for using a cfb console on the HDMI, LCD
-       or VGA output found on most sunxi devices. See doc/README.video for
-       info on how to select the video output and mode.
+       Say Y here to add support for using a graphical console on the HDMI,
+       LCD or VGA output found on older sunxi devices. This will also provide
+       a simple_framebuffer device for Linux.
 
 config VIDEO_HDMI
        bool "HDMI output support"
index fa2b6fc..503538e 100644 (file)
@@ -338,7 +338,7 @@ void board_init_f(ulong dummy)
 }
 #endif
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 #if defined(CONFIG_SUNXI_GEN_SUN4I) || defined(CONFIG_MACH_SUN8I_R40)
        static const struct sunxi_wdog *wdog =
index 25df31a..92ff6cb 100644 (file)
@@ -40,7 +40,7 @@ static int do_enterrcm(struct cmd_tbl *cmdtp, int flag, int argc,
 
        tegra_pmc_writel(2, PMC_SCRATCH0);
        disable_interrupts();
-       reset_cpu(0);
+       reset_cpu();
 
        return 0;
 }
index 93db63e..8d617be 100644 (file)
@@ -85,7 +85,7 @@ void tegra_pmc_writel(u32 value, unsigned long offset)
        writel(value, NV_PA_PMC_BASE + offset);
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        u32 value;
 
index a4d260a..fbb6ebc 100644 (file)
@@ -158,5 +158,5 @@ s32 __secure psci_cpu_on(u32 function_id, u32 cpuid, u32 entry_point,
 
 void __secure psci_system_reset(void)
 {
-       reset_cpu(0);
+       reset_cpu();
 }
index 5fffd23..dddb48e 100644 (file)
@@ -18,7 +18,7 @@
 #define __SECURE
 #endif
 
-void __SECURE reset_cpu(unsigned long ignored)
+void __SECURE reset_cpu(void)
 {
        u32 tmp;
 
index 3befc12..69b818f 100644 (file)
@@ -78,7 +78,7 @@ unsigned int zynq_get_silicon_version(void)
                                                >> ZYNQ_SILICON_VER_SHIFT;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        zynq_slcr_cpu_reset();
        while (1)
index d841c3a..0d36844 100644 (file)
@@ -30,7 +30,7 @@ int arch_cpu_init(void)
 /*
  * Perform the low-level reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        while (1)
                ;
index 9d99c83..91c3574 100644 (file)
@@ -46,7 +46,7 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        /*
         * reset to the base addr of andesboot.
         * currently no ROM loader at addr 0.
-        * do not use reset_cpu(0);
+        * do not use reset_cpu();
         */
 #ifdef CONFIG_FTWDT010_WATCHDOG
        /*
index 386c199..3395721 100644 (file)
@@ -500,25 +500,3 @@ software_interrupt:
        bal     do_interruption
 
        .align  5
-
-/*
- * void reset_cpu(ulong addr);
- * $r0: input address to jump to
- */
-.globl reset_cpu
-reset_cpu:
-/* No need to disable MMU because we never enable it */
-
-       bal     invalidate_icac
-       bal     invalidate_dcac
-       mfsr    $p0, $MMU_CFG
-       andi    $p0, $p0, 0x3                   ! MMPS
-       li      $p1, 0x2                        ! TLB MMU
-       bne     $p0, $p1, 1f
-       tlbop   flushall                        ! Flush TLB
-1:
-       mfsr    $p0, MR_CAC_CTL                 ! Get the $CACHE_CTL reg
-       li      $p1, DIS_DCAC
-       and     $p0, $p0, $p1                   ! Clear the DC_EN bit
-       mtsr    $p0, MR_CAC_CTL                 ! Write back the $CACHE_CTL reg
-       br      $r0                             ! Jump to the input address
index 1481e05..0ec72d1 100644 (file)
@@ -66,7 +66,7 @@ int disable_interrupts(void)
 void bad_mode(void)
 {
        panic("Resetting CPU ...\n");
-       reset_cpu(0);
+       reset_cpu();
 }
 
 void show_regs(struct pt_regs *regs)
index 327b74e..941d963 100644 (file)
@@ -6,7 +6,7 @@ config RISCV_NDS
        imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
        imply ANDES_PLIC if (RISCV_MMODE || SPL_RISCV_MMODE)
        imply ANDES_PLMT_TIMER if (RISCV_MMODE || SPL_RISCV_MMODE)
-       imply SPL_CPU_SUPPORT
+       imply SPL_CPU
        imply SPL_OPENSBI
        imply SPL_LOAD_FIT
        help
index 61bd5c4..616b256 100644 (file)
@@ -13,7 +13,7 @@ config SIFIVE_FU540
        imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
        imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
        imply CMD_CPU
-       imply SPL_CPU_SUPPORT
+       imply SPL_CPU
        imply SPL_OPENSBI
        imply SPL_LOAD_FIT
        imply SMP
index f4c2e26..198e36e 100644 (file)
@@ -10,6 +10,6 @@ config GENERIC_RISCV
        imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
        imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
        imply CMD_CPU
-       imply SPL_CPU_SUPPORT
+       imply SPL_CPU
        imply SPL_OPENSBI
        imply SPL_LOAD_FIT
index edd48e2..48636ab 100644 (file)
@@ -6,7 +6,6 @@
 #include <common.h>
 #include <bootstage.h>
 #include <cpu_func.h>
-#include <dm.h>
 #include <errno.h>
 #include <log.h>
 #include <asm/global_data.h>
@@ -17,7 +16,6 @@
 #include <asm/malloc.h>
 #include <asm/setjmp.h>
 #include <asm/state.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -34,10 +32,8 @@ void sandbox_exit(void)
 {
        /* Do this here while it still has an effect */
        os_fd_restore();
-       if (state_uninit())
-               os_exit(2);
 
-       if (dm_uninit())
+       if (state_uninit())
                os_exit(2);
 
        /* This is considered normal termination for now */
index 3d8af0a..b9ad341 100644 (file)
@@ -153,7 +153,7 @@ int os_read_file(const char *fname, void **bufp, int *sizep)
                printf("Cannot seek to start of file '%s'\n", fname);
                goto err;
        }
-       *bufp = malloc(size);
+       *bufp = os_malloc(size);
        if (!*bufp) {
                printf("Not enough memory to read file '%s'\n", fname);
                ret = -ENOMEM;
@@ -267,11 +267,18 @@ void os_tty_raw(int fd, bool allow_sigs)
        signal(SIGINT, os_sigint_handler);
 }
 
+/*
+ * Provide our own malloc so we don't use space in the sandbox ram_buf for
+ * allocations that are internal to sandbox, or need to be done before U-Boot's
+ * malloc() is ready.
+ */
 void *os_malloc(size_t length)
 {
        int page_size = getpagesize();
        struct os_mem_hdr *hdr;
 
+       if (!length)
+               return NULL;
        /*
         * Use an address that is hopefully available to us so that pointers
         * to this memory are fairly obvious. If we end up with a different
@@ -298,6 +305,47 @@ void os_free(void *ptr)
        }
 }
 
+/* These macros are from kernel.h but not accessible in this file */
+#define ALIGN(x, a)            __ALIGN_MASK((x), (typeof(x))(a) - 1)
+#define __ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
+
+/*
+ * Provide our own malloc so we don't use space in the sandbox ram_buf for
+ * allocations that are internal to sandbox, or need to be done before U-Boot's
+ * malloc() is ready.
+ */
+void *os_realloc(void *ptr, size_t length)
+{
+       int page_size = getpagesize();
+       struct os_mem_hdr *hdr;
+       void *new_ptr;
+
+       /* Reallocating a NULL pointer is just an alloc */
+       if (!ptr)
+               return os_malloc(length);
+
+       /* Changing a length to 0 is just a free */
+       if (length) {
+               os_free(ptr);
+               return NULL;
+       }
+
+       /*
+        * If the new size is the same number of pages as the old, nothing to
+        * do. There isn't much point in shrinking things
+        */
+       hdr = ptr - page_size;
+       if (ALIGN(length, page_size) <= ALIGN(hdr->length, page_size))
+               return ptr;
+
+       /* We have to grow it, so allocate something new */
+       new_ptr = os_malloc(length);
+       memcpy(new_ptr, ptr, hdr->length);
+       os_free(ptr);
+
+       return new_ptr;
+}
+
 void os_usleep(unsigned long usec)
 {
        usleep(usec);
@@ -343,8 +391,8 @@ int os_parse_args(struct sandbox_state *state, int argc, char *argv[])
        state->argv = argv;
 
        /* dynamically construct the arguments to the system getopt_long */
-       short_opts = malloc(sizeof(*short_opts) * num_options * 2 + 1);
-       long_opts = malloc(sizeof(*long_opts) * (num_options + 1));
+       short_opts = os_malloc(sizeof(*short_opts) * num_options * 2 + 1);
+       long_opts = os_malloc(sizeof(*long_opts) * (num_options + 1));
        if (!short_opts || !long_opts)
                return 1;
 
@@ -423,7 +471,7 @@ void os_dirent_free(struct os_dirent_node *node)
 
        while (node) {
                next = node->next;
-               free(node);
+               os_free(node);
                node = next;
        }
 }
@@ -448,7 +496,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
        /* Create a buffer upfront, with typically sufficient size */
        dirlen = strlen(dirname) + 2;
        len = dirlen + 256;
-       fname = malloc(len);
+       fname = os_malloc(len);
        if (!fname) {
                ret = -ENOMEM;
                goto done;
@@ -461,7 +509,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
                        ret = errno;
                        break;
                }
-               next = malloc(sizeof(*node) + strlen(entry->d_name) + 1);
+               next = os_malloc(sizeof(*node) + strlen(entry->d_name) + 1);
                if (!next) {
                        os_dirent_free(head);
                        ret = -ENOMEM;
@@ -470,10 +518,10 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
                if (dirlen + strlen(entry->d_name) > len) {
                        len = dirlen + strlen(entry->d_name);
                        old_fname = fname;
-                       fname = realloc(fname, len);
+                       fname = os_realloc(fname, len);
                        if (!fname) {
-                               free(old_fname);
-                               free(next);
+                               os_free(old_fname);
+                               os_free(next);
                                os_dirent_free(head);
                                ret = -ENOMEM;
                                goto done;
@@ -507,7 +555,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
 
 done:
        closedir(dir);
-       free(fname);
+       os_free(fname);
        return ret;
 }
 
@@ -624,7 +672,7 @@ static int add_args(char ***argvp, char *add_args[], int count)
        for (argc = 0; (*argvp)[argc]; argc++)
                ;
 
-       argv = malloc((argc + count + 1) * sizeof(char *));
+       argv = os_malloc((argc + count + 1) * sizeof(char *));
        if (!argv) {
                printf("Out of memory for %d argv\n", count);
                return -ENOMEM;
@@ -663,7 +711,7 @@ static int add_args(char ***argvp, char *add_args[], int count)
  * @fname: Filename to exec
  * @return does not return on success, any return value is an error
  */
-static int os_jump_to_file(const char *fname)
+static int os_jump_to_file(const char *fname, bool delete_it)
 {
        struct sandbox_state *state = state_get_current();
        char mem_fname[30];
@@ -686,11 +734,13 @@ static int os_jump_to_file(const char *fname)
 
        os_fd_restore();
 
-       extra_args[0] = "-j";
-       extra_args[1] = (char *)fname;
-       extra_args[2] = "-m";
-       extra_args[3] = mem_fname;
-       argc = 4;
+       argc = 0;
+       if (delete_it) {
+               extra_args[argc++] = "-j";
+               extra_args[argc++] = (char *)fname;
+       }
+       extra_args[argc++] = "-m";
+       extra_args[argc++] = mem_fname;
        if (state->ram_buf_rm)
                extra_args[argc++] = "--rm_memory";
        err = add_args(&argv, extra_args, argc);
@@ -707,14 +757,17 @@ static int os_jump_to_file(const char *fname)
                os_exit(2);
 
        err = execv(fname, argv);
-       free(argv);
+       os_free(argv);
        if (err) {
                perror("Unable to run image");
                printf("Image filename '%s'\n", fname);
                return err;
        }
 
-       return unlink(fname);
+       if (delete_it)
+               return unlink(fname);
+
+       return -EFAULT;
 }
 
 int os_jump_to_image(const void *dest, int size)
@@ -726,10 +779,10 @@ int os_jump_to_image(const void *dest, int size)
        if (err)
                return err;
 
-       return os_jump_to_file(fname);
+       return os_jump_to_file(fname, true);
 }
 
-int os_find_u_boot(char *fname, int maxlen)
+int os_find_u_boot(char *fname, int maxlen, bool use_img)
 {
        struct sandbox_state *state = state_get_current();
        const char *progname = state->argv[0];
@@ -753,8 +806,8 @@ int os_find_u_boot(char *fname, int maxlen)
                        return 0;
                }
 
-               /* Look for 'u-boot-tpl' in the tpl/ directory */
-               p = strstr(fname, "/tpl/");
+               /* Look for 'u-boot-spl' in the spl/ directory */
+               p = strstr(fname, "/spl/");
                if (p) {
                        p[1] = 's';
                        fd = os_open(fname, O_RDONLY);
@@ -781,6 +834,8 @@ int os_find_u_boot(char *fname, int maxlen)
        if (p) {
                /* Remove the "spl" characters */
                memmove(p, p + 4, strlen(p + 4) + 1);
+               if (use_img)
+                       strcat(p, ".img");
                fd = os_open(fname, O_RDONLY);
                if (fd >= 0) {
                        close(fd);
@@ -795,10 +850,10 @@ int os_spl_to_uboot(const char *fname)
 {
        struct sandbox_state *state = state_get_current();
 
-       printf("%s\n", __func__);
        /* U-Boot will delete ram buffer after read: "--rm_memory"*/
        state->ram_buf_rm = true;
-       return os_jump_to_file(fname);
+
+       return os_jump_to_file(fname, false);
 }
 
 long os_get_time_offset(void)
index d4dab36..8102649 100644 (file)
@@ -69,14 +69,14 @@ static void sandbox_sdl_poll_events(void)
         * We don't want to include common.h in this file since it uses
         * system headers. So add a declation here.
         */
-       extern void reset_cpu(unsigned long addr);
+       extern void reset_cpu(void);
        SDL_Event event;
 
        while (SDL_PollEvent(&event)) {
                switch (event.type) {
                case SDL_QUIT:
                        puts("LCD window closed - quitting\n");
-                       reset_cpu(1);
+                       reset_cpu();
                        break;
                }
        }
index e7b4b50..f82b0d3 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/global_data.h>
 #include <asm/spl.h>
 #include <asm/state.h>
-#include <test/test.h>
+#include <test/ut.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -37,16 +37,20 @@ static int spl_board_load_image(struct spl_image_info *spl_image,
        char fname[256];
        int ret;
 
-       ret = os_find_u_boot(fname, sizeof(fname));
+       ret = os_find_u_boot(fname, sizeof(fname), false);
        if (ret) {
                printf("(%s not found, error %d)\n", fname, ret);
                return ret;
        }
 
-       /* Set up spl_image to boot from jump_to_image_no_args() */
-       spl_image->arg = strdup(fname);
+       /*
+        * Set up spl_image to boot from jump_to_image_no_args(). Allocate this
+        * outsdide the RAM buffer (i.e. don't use strdup()).
+        */
+       spl_image->arg = os_malloc(strlen(fname) + 1);
        if (!spl_image->arg)
-               return log_msg_ret("Setup exec filename", -ENOMEM);
+               return log_msg_ret("exec", -ENOMEM);
+       strcpy(spl_image->arg, fname);
 
        return 0;
 }
@@ -59,9 +63,12 @@ void spl_board_init(void)
        preloader_console_init();
 
        if (state->run_unittests) {
+               struct unit_test *tests = UNIT_TEST_ALL_START();
+               const int count = UNIT_TEST_ALL_COUNT();
                int ret;
 
-               ret = dm_test_main(state->select_unittests);
+               ret = ut_run_list("spl", NULL, tests, count,
+                                 state->select_unittests);
                /* continue execution into U-Boot */
        }
 }
index 483a264..e87365e 100644 (file)
@@ -88,7 +88,7 @@ int sandbox_early_getopt_check(void)
 
        /* Sort the options */
        size = sizeof(*sorted_opt) * num_options;
-       sorted_opt = malloc(size);
+       sorted_opt = os_malloc(size);
        if (!sorted_opt) {
                printf("No memory to sort options\n");
                os_exit(1);
@@ -188,7 +188,7 @@ static int sandbox_cmdline_cb_default_fdt(struct sandbox_state *state,
        int len;
 
        len = strlen(state->argv[0]) + strlen(fmt) + 1;
-       fname = malloc(len);
+       fname = os_malloc(len);
        if (!fname)
                return -ENOMEM;
        snprintf(fname, len, fmt, state->argv[0]);
@@ -208,7 +208,7 @@ static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state,
        int len;
 
        len = strlen(state->argv[0]) + strlen(fmt) + 1;
-       fname = malloc(len);
+       fname = os_malloc(len);
        if (!fname)
                return -ENOMEM;
        strcpy(fname, state->argv[0]);
@@ -436,16 +436,18 @@ int main(int argc, char *argv[])
 {
        struct sandbox_state *state;
        gd_t data;
+       int size;
        int ret;
 
        /*
         * Copy argv[] so that we can pass the arguments in the original
         * sequence when resetting the sandbox.
         */
-       os_argv = calloc(argc + 1, sizeof(char *));
+       size = sizeof(char *) * (argc + 1);
+       os_argv = os_malloc(size);
        if (!os_argv)
                os_exit(1);
-       memcpy(os_argv, argv, sizeof(char *) * (argc + 1));
+       memcpy(os_argv, argv, size);
 
        memset(&data, '\0', sizeof(data));
        gd = &data;
@@ -489,7 +491,6 @@ int main(int argc, char *argv[])
        gd->reloc_off = (ulong)gd->arch.text_base;
 
        /* sandbox test: log functions called before log_init in board_init_f */
-       log_info("sandbox: starting...\n");
        log_debug("debug: %s\n", __func__);
 
        /* Do pre- and post-relocation init */
index b2901b7..f63cfd3 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <common.h>
+#include <bloblist.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <log.h>
@@ -29,17 +30,17 @@ static int state_ensure_space(int extra_size)
                return 0;
 
        size = used + extra_size;
-       buf = malloc(size);
+       buf = os_malloc(size);
        if (!buf)
                return -ENOMEM;
 
        ret = fdt_open_into(blob, buf, size);
        if (ret) {
-               free(buf);
+               os_free(buf);
                return -EIO;
        }
 
-       free(blob);
+       os_free(blob);
        state->state_fdt = buf;
        return 0;
 }
@@ -55,7 +56,7 @@ static int state_read_file(struct sandbox_state *state, const char *fname)
                printf("Cannot find sandbox state file '%s'\n", fname);
                return -ENOENT;
        }
-       state->state_fdt = malloc(size);
+       state->state_fdt = os_malloc(size);
        if (!state->state_fdt) {
                puts("No memory to read sandbox state\n");
                return -ENOMEM;
@@ -77,7 +78,7 @@ static int state_read_file(struct sandbox_state *state, const char *fname)
 err_read:
        os_close(fd);
 err_open:
-       free(state->state_fdt);
+       os_free(state->state_fdt);
        state->state_fdt = NULL;
 
        return ret;
@@ -244,7 +245,7 @@ int sandbox_write_state(struct sandbox_state *state, const char *fname)
        /* Create a state FDT if we don't have one */
        if (!state->state_fdt) {
                size = 0x4000;
-               state->state_fdt = malloc(size);
+               state->state_fdt = os_malloc(size);
                if (!state->state_fdt) {
                        puts("No memory to create FDT\n");
                        return -ENOMEM;
@@ -302,7 +303,7 @@ int sandbox_write_state(struct sandbox_state *state, const char *fname)
 err_write:
        os_close(fd);
 err_create:
-       free(state->state_fdt);
+       os_free(state->state_fdt);
 
        return ret;
 }
@@ -398,8 +399,12 @@ int state_uninit(void)
 {
        int err;
 
+       log_info("Writing sandbox state\n");
        state = &main_state;
 
+       /* Finish the bloblist, so that it is correct before writing memory */
+       bloblist_finish();
+
        if (state->write_ram_buf) {
                err = os_write_ram_buf(state->ram_buf_fname);
                if (err) {
@@ -419,8 +424,8 @@ int state_uninit(void)
        if (state->jumped_fname)
                os_unlink(state->jumped_fname);
 
-       if (state->state_fdt)
-               free(state->state_fdt);
+       os_free(state->state_fdt);
+       os_free(state->ram_buf);
        memset(state, '\0', sizeof(*state));
 
        return 0;
index 649abeb..1816043 100644 (file)
@@ -13,6 +13,14 @@ SECTIONS
                KEEP(*(SORT(.u_boot_list*)));
        }
 
+       /* Private data for devices with OF_PLATDATA_RT */
+       . = ALIGN(4);
+       .priv_data : {
+               __priv_data_start = .;
+               *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.priv_data*)))
+               __priv_data_end = .;
+       }
+
        __u_boot_sandbox_option_start = .;
        _u_boot_sandbox_getopt : { KEEP(*(.u_boot_sandbox_getopt)) }
        __u_boot_sandbox_option_end = .;
index 936da5e..a1f509c 100644 (file)
@@ -44,6 +44,13 @@ SECTIONS
        {
                *(.__efi_runtime_rel_stop)
        }
+
+       .dynsym :
+       {
+               __dyn_sym_start = .;
+               *(.dynsym)
+               __dyn_sym_end = .;
+       }
 }
 
 INSERT BEFORE .data;
index dc933f3..31db50d 100644 (file)
@@ -31,7 +31,7 @@
 
        clk_fixed: clk-fixed {
                u-boot,dm-pre-reloc;
-               compatible = "fixed-clock";
+               compatible = "sandbox,fixed-clock";
                #clock-cells = <0>;
                clock-frequency = <1234>;
        };
                };
 
                i2c_emul: emul {
+                       u-boot,dm-pre-reloc;
                        reg = <0xff>;
                        compatible = "sandbox,i2c-emul-parent";
                        emul_eeprom: emul-eeprom {
                                compatible = "sandbox,i2c-eeprom";
                                sandbox,filename = "i2c.bin";
                                sandbox,size = <256>;
+                               #emul-cells = <0>;
                        };
                        emul0: emul0 {
-                               compatible = "sandbox,i2c-rtc";
+                               u-boot,dm-pre-reloc;
+                               compatible = "sandbox,i2c-rtc-emul";
+                               #emul-cells = <0>;
                        };
                };
        };
                compatible = "sandbox,reset";
        };
 
+       rng {
+               compatible = "sandbox,sandbox-rng";
+       };
+
        sound {
                compatible = "sandbox,sound";
                cpu {
                stringarray = "pre-proper";
        };
 
-       test-bus {
-               compatible = "simple-bus";
+       spl-test7 {
                u-boot,dm-spl;
-               spl-test7 {
-                       u-boot,dm-spl;
-                       compatible = "sandbox,spl-test";
-                       stringarray = "spl";
-               };
+               compatible = "sandbox,spl-test";
+               stringarray = "spl";
        };
 
        square {
index 2600360..899e75f 100644 (file)
                                sandbox,size = <256>;
                        };
                        emul0: emul0 {
-                               compatible = "sandbox,i2c-rtc";
+                               compatible = "sandbox,i2c-rtc-emul";
                        };
                        emul1: emull {
-                               compatible = "sandbox,i2c-rtc";
+                               compatible = "sandbox,i2c-rtc-emul";
                        };
                };
 
 };
 
 #include "sandbox_pmic.dtsi"
+#include "cros-ec-keyboard.dtsi"
index 68a8687..df7156f 100644 (file)
@@ -7,6 +7,9 @@
 #define __SANDBOX_CLK_H
 
 #include <common.h>
+#include <clk.h>
+#include <dt-structs.h>
+#include <linux/clk-provider.h>
 
 struct udevice;
 
@@ -45,6 +48,27 @@ enum sandbox_clk_test_id {
 
 #define SANDBOX_CLK_TEST_NON_DEVM_COUNT SANDBOX_CLK_TEST_ID_DEVM1
 
+struct sandbox_clk_priv {
+       bool probed;
+       ulong rate[SANDBOX_CLK_ID_COUNT];
+       bool enabled[SANDBOX_CLK_ID_COUNT];
+       bool requested[SANDBOX_CLK_ID_COUNT];
+};
+
+struct sandbox_clk_test {
+       struct clk clks[SANDBOX_CLK_TEST_NON_DEVM_COUNT];
+       struct clk *clkps[SANDBOX_CLK_TEST_ID_COUNT];
+       struct clk_bulk bulk;
+};
+
+/* Platform data for the sandbox fixed-rate clock driver */
+struct sandbox_clk_fixed_rate_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+       struct dtd_sandbox_fixed_clock dtplat;
+#endif
+       struct clk_fixed_rate fixed;
+};
+
 /**
  * sandbox_clk_query_rate - Query the current rate of a sandbox clock.
  *
index df4ba4f..9e10052 100644 (file)
  */
 #include <asm-generic/gpio.h>
 
+/* Our own private GPIO flags, which musn't conflict with GPIOD_... */
+#define GPIOD_EXT_HIGH         BIT(31) /* external source is high (else low) */
+#define GPIOD_EXT_DRIVEN       BIT(30) /* external source is driven */
+#define GPIOD_EXT_PULL_UP      BIT(29) /* GPIO has external pull-up */
+#define GPIOD_EXT_PULL_DOWN    BIT(28) /* GPIO has external pull-down */
+
+#define GPIOD_EXT_PULL         (BIT(28) | BIT(29))
+#define GPIOD_SANDBOX_MASK     GENMASK(31, 28)
+
 /**
  * Return the simulated value of a GPIO (used only in sandbox test code)
  *
@@ -69,17 +78,17 @@ int sandbox_gpio_set_direction(struct udevice *dev, unsigned int offset,
  * @param offset       GPIO offset within bank
  * @return dir_flags: bitfield accesses by GPIOD_ defines
  */
-ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset);
+ulong sandbox_gpio_get_flags(struct udevice *dev, unsigned int offset);
 
 /**
  * Set the simulated flags of a GPIO (used only in sandbox test code)
  *
  * @param dev          device to use
  * @param offset       GPIO offset within bank
- * @param flags                dir_flags: bitfield accesses by GPIOD_ defines
+ * @param flags                bitfield accesses by GPIOD_ defines
  * @return -1 on error, 0 if ok
  */
-int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-                              ulong flags);
+int sandbox_gpio_set_flags(struct udevice *dev, unsigned int offset,
+                          ulong flags);
 
 #endif
index b482be4..4fc190b 100644 (file)
@@ -11,4 +11,19 @@ struct sandbox_i2c_priv {
        bool test_mode;
 };
 
+/**
+ * struct i2c_emul_uc_plat - information about the emulator for this device
+ *
+ * This is used by devices in UCLASS_I2C_EMUL to record information about the
+ * device being emulated. It is accessible with dev_get_uclass_plat()
+ *
+ * @dev: Device being emulated
+ * @idx: of-platdata index, set up by the device's bind() method if of-platdata
+ *     is in use
+ */
+struct i2c_emul_uc_plat {
+       struct udevice *dev;
+       int idx;
+};
+
 #endif /* __asn_i2c_h */
index 5bb032f..025cd6c 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef __asm_rtc_h
 #define __asm_rtc_h
 
+#include <dt-structs.h>
+
 /* Register numbers in the sandbox RTC */
 enum {
        REG_SEC         = 5,
@@ -29,4 +31,26 @@ enum {
        REG_COUNT       = 0x80,
 };
 
+/**
+ * struct sandbox_i2c_rtc_plat_data - platform data for the RTC
+ *
+ * @base_time:         Base system time when RTC device was bound
+ * @offset:            RTC offset from current system time
+ * @use_system_time:   true to use system time, false to use @base_time
+ * @reg:               Register values
+ */
+struct sandbox_i2c_rtc_plat_data {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+       struct dtd_sandbox_i2c_rtc_emul dtplat;
+#endif
+       long base_time;
+       long offset;
+       bool use_system_time;
+       u8 reg[REG_COUNT];
+};
+
+struct sandbox_i2c_rtc {
+       unsigned int offset_secs;
+};
+
 #endif
index 801102f..1b2f50d 100644 (file)
@@ -32,7 +32,7 @@ int cleanup_before_linux (void)
 int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
        disable_interrupts();
-       reset_cpu(0);
+       reset_cpu();
        return 0;
 }
 
index 1de32cd..bf403d3 100644 (file)
@@ -51,7 +51,7 @@ int watchdog_disable(void)
 }
 #endif
 
-void reset_cpu(unsigned long ignored)
+void reset_cpu(void)
 {
        /* Address error with SR.BL=1 first. */
        trigger_address_error();
index 5b089af..970bdff 100644 (file)
@@ -1047,4 +1047,25 @@ config INTEL_GMA_SWSMISCI
 
 endif # INTEL_SOC
 
+config COREBOOT_SYSINFO
+       bool "Support reading coreboot sysinfo"
+       default y if SYS_COREBOOT
+       help
+         Select this option to read the coreboot sysinfo table on start-up,
+         if present. This is written by coreboot before it exits and provides
+         various pieces of information about the running system, including
+         display, memory and build information. It is stored in
+         struct sysinfo_t after parsing by get_coreboot_info().
+
+config SPL_COREBOOT_SYSINFO
+       bool "Support reading coreboot sysinfo"
+       depends on SPL
+       default y if COREBOOT_SYSINFO
+       help
+         Select this option to read the coreboot sysinfo table in SPL,
+         if present. This is written by coreboot before it exits and provides
+         various pieces of information about the running system, including
+         display, memory and build information. It is stored in
+         struct sysinfo_t after parsing by get_coreboot_info().
+
 endmenu
index 590fe31..b3ce053 100644 (file)
@@ -21,6 +21,8 @@ config INTEL_APOLLOLAKE
        select INTEL_GMA_SWSMISCI
        select ACPI_GNVS_EXTERNAL
        select TPL_OF_PLATDATA_PARENT
+       select TPL_OF_PLATDATA_INST
+       select TPL_READ_ONLY
        imply ENABLE_MRC_CACHE
        imply AHCI_PCI
        imply SCSI
index fbc016d..647c9df 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/arch/iomap.h>
 #include <dm/acpi.h>
 
+#ifdef CONFIG_ACPIGEN
 #define CSTATE_RES(address_space, width, offset, address)              \
        {                                                               \
        .space_id = address_space,                                      \
@@ -57,11 +58,6 @@ static struct acpi_cstate cstate_map[] = {
        },
 };
 
-static int apl_get_info(const struct udevice *dev, struct cpu_info *info)
-{
-       return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
-}
-
 static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
 {
        uint core_id = dev_seq(dev);
@@ -89,6 +85,12 @@ static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
 
        return 0;
 }
+#endif /* CONFIG_ACPIGEN */
+
+static int apl_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+       return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
+}
 
 static void update_fixed_mtrrs(void)
 {
@@ -170,9 +172,11 @@ static int cpu_apl_probe(struct udevice *dev)
        return 0;
 }
 
+#ifdef CONFIG_ACPIGEN
 struct acpi_ops apl_cpu_acpi_ops = {
        .fill_ssdt      = acpi_cpu_fill_ssdt,
 };
+#endif
 
 static const struct cpu_ops cpu_x86_apl_ops = {
        .get_desc       = cpu_x86_get_desc,
index 63f6999..5d7d26b 100644 (file)
@@ -7,11 +7,17 @@
 #include <dm.h>
 #include <log.h>
 #include <asm/cpu_common.h>
+#include <asm/io.h>
 #include <asm/msr.h>
+#include <asm/pci.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/iomap.h>
+#include <asm/arch/uart.h>
 #include <power/acpi_pmc.h>
 
+/* Define this here to avoid referencing any drivers for the debug UART 1 */
+#define PCH_DEV_P2SB   PCI_BDF(0, 0x0d, 0)
+
 void cpu_flush_l1d_to_l2(void)
 {
        struct msr_t msr;
@@ -40,3 +46,57 @@ void enable_pm_timer_emulation(const struct udevice *pmc)
        debug("PM timer %x %x\n", msr.hi, msr.lo);
        msr_write(MSR_EMULATE_PM_TIMER, msr);
 }
+
+static void pch_uart_init(void)
+{
+       /*
+        * Set up the pinmux so that the UART rx/tx signals are connected
+        * outside the SoC.
+        *
+        * There are about 500 lines of code required to program the GPIO
+        * configuration for the UARTs. But it boils down to four writes, and
+        * for the debug UART we want the minimum possible amount of code before
+        * the UART is running. So just add the magic writes here. See
+        * apl_hostbridge_early_init_pinctrl() for the full horror.
+        */
+       if (PCI_FUNC(PCH_DEV_UART) == 1) {
+               writel(0x40000402, 0xd0c50650);
+               writel(0x3c47, 0xd0c50654);
+               writel(0x40000400, 0xd0c50658);
+               writel(0x3c48, 0xd0c5065c);
+       } else { /* UART2 */
+               writel(0x40000402, 0xd0c50670);
+               writel(0x3c4b, 0xd0c50674);
+               writel(0x40000400, 0xd0c50678);
+               writel(0x3c4c, 0xd0c5067c);
+       }
+
+#ifdef CONFIG_DEBUG_UART
+       apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE);
+#endif
+}
+
+static void p2sb_enable_bar(ulong bar)
+{
+       /* Enable PCR Base address in PCH */
+       pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar,
+                            PCI_SIZE_32);
+       pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
+
+       /* Enable P2SB MSE */
+       pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND,
+                            PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY,
+                            PCI_SIZE_8);
+}
+
+/*
+ * board_debug_uart_init() - Init the debug UART ready for use
+ *
+ * This is the minimum init needed to get the UART running. It avoids any
+ * drivers or complex code, so that the UART is running as soon as possible.
+ */
+void board_debug_uart_init(void)
+{
+       p2sb_enable_bar(IOMAP_P2SB_BAR);
+       pch_uart_init();
+}
index 9a18476..8f48457 100644 (file)
 #include <asm/arch/lpc.h>
 #include <asm/arch/pch.h>
 #include <asm/arch/systemagent.h>
-#include <asm/arch/uart.h>
 #include <asm/fsp2/fsp_api.h>
 #include <linux/sizes.h>
 #include <power/acpi_pmc.h>
 
-/* Define this here to avoid referencing any drivers for the debug UART 1 */
-#define PCH_DEV_P2SB   PCI_BDF(0, 0x0d, 0)
-
-static void pch_uart_init(void)
-{
-       /*
-        * Set up the pinmux so that the UART rx/tx signals are connected
-        * outside the SoC.
-        *
-        * There are about 500 lines of code required to program the GPIO
-        * configuration for the UARTs. But it boils down to four writes, and
-        * for the debug UART we want the minimum possible amount of code before
-        * the UART is running. So just add the magic writes here. See
-        * apl_hostbridge_early_init_pinctrl() for the full horror.
-        */
-       if (PCI_FUNC(PCH_DEV_UART) == 1) {
-               writel(0x40000402, 0xd0c50650);
-               writel(0x3c47, 0xd0c50654);
-               writel(0x40000400, 0xd0c50658);
-               writel(0x3c48, 0xd0c5065c);
-       } else { /* UART2 */
-               writel(0x40000402, 0xd0c50670);
-               writel(0x3c4b, 0xd0c50674);
-               writel(0x40000400, 0xd0c50678);
-               writel(0x3c4c, 0xd0c5067c);
-       }
-
-#ifdef CONFIG_DEBUG_UART
-       apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE);
-#endif
-}
-
-static void p2sb_enable_bar(ulong bar)
-{
-       /* Enable PCR Base address in PCH */
-       pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar,
-                            PCI_SIZE_32);
-       pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
-
-       /* Enable P2SB MSE */
-       pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND,
-                            PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY,
-                            PCI_SIZE_8);
-}
-
-/*
- * board_debug_uart_init() - Init the debug UART ready for use
- *
- * This is the minimum init needed to get the UART running. It avoids any
- * drivers or complex code, so that the UART is running as soon as possible.
- */
-void board_debug_uart_init(void)
-{
-       p2sb_enable_bar(IOMAP_P2SB_BAR);
-       pch_uart_init();
-}
-
 static int fast_spi_cache_bios_region(void)
 {
        uint map_size, offset;
index e23d38e..1d21187 100644 (file)
@@ -9,8 +9,8 @@
 #define LOG_CATEGORY UCLASS_ACPI_PMC
 
 #include <common.h>
-#include <dt-structs.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <log.h>
 #include <spl.h>
 #include <acpi/acpi_s3.h>
index e67c011..5ed7963 100644 (file)
@@ -93,4 +93,5 @@ U_BOOT_DRIVER(intel_apl_punit) = {
        .id             = UCLASS_SYSCON,
        .of_match       = apl_syscon_ids,
        .probe          = apl_punit_probe,
+       DM_HEADER(<asm/cpu.h>)    /* for X86_SYSCON_PUNIT */
 };
index 605f903..a6cdb9a 100644 (file)
@@ -20,5 +20,4 @@ else
 obj-y += sdram.o
 endif
 obj-y += coreboot.o
-obj-y += tables.o
 obj-y += timestamp.o
index 15c3ad8..69cf8f4 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/io.h>
 #include <asm/msr.h>
 #include <asm/mtrr.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 #include <asm/arch/timestamp.h>
 
 DECLARE_GLOBAL_DATA_PTR;
index a2e47d1..4a256ba 100644 (file)
@@ -8,7 +8,7 @@
 #include <common.h>
 #include <init.h>
 #include <asm/e820.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 #include <asm/global_data.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -16,32 +16,7 @@ DECLARE_GLOBAL_DATA_PTR;
 unsigned int install_e820_map(unsigned int max_entries,
                              struct e820_entry *entries)
 {
-       unsigned int num_entries;
-       int i;
-
-       num_entries = min((unsigned int)lib_sysinfo.n_memranges, max_entries);
-       if (num_entries < lib_sysinfo.n_memranges) {
-               printf("Warning: Limiting e820 map to %d entries.\n",
-                       num_entries);
-       }
-       for (i = 0; i < num_entries; i++) {
-               struct memrange *memrange = &lib_sysinfo.memrange[i];
-
-               entries[i].addr = memrange->base;
-               entries[i].size = memrange->size;
-
-               /*
-                * coreboot has some extensions (type 6 & 16) to the E820 types.
-                * When we detect this, mark it as E820_RESERVED.
-                */
-               if (memrange->type == CB_MEM_VENDOR_RSVD ||
-                   memrange->type == CB_MEM_TABLE)
-                       entries[i].type = E820_RESERVED;
-               else
-                       entries[i].type = memrange->type;
-       }
-
-       return num_entries;
+       return cb_install_e820_map(max_entries, entries);
 }
 
 /*
diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c
deleted file mode 100644 (file)
index c52741a..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-// SPDX-License-Identifier: BSD-3-Clause
-/*
- * This file is part of the libpayload project.
- *
- * Copyright (C) 2008 Advanced Micro Devices, Inc.
- * Copyright (C) 2009 coresystems GmbH
- */
-
-#include <common.h>
-#include <net.h>
-#include <asm/arch/sysinfo.h>
-#include <asm/global_data.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/*
- * This needs to be in the .data section so that it's copied over during
- * relocation. By default it's put in the .bss section which is simply filled
- * with zeroes when transitioning from "ROM", which is really RAM, to other
- * RAM.
- */
-struct sysinfo_t lib_sysinfo __attribute__((section(".data")));
-
-/*
- * Some of this is x86 specific, and the rest of it is generic. Right now,
- * since we only support x86, we'll avoid trying to make lots of infrastructure
- * we don't need. If in the future, we want to use coreboot on some other
- * architecture, then take out the generic parsing code and move it elsewhere.
- */
-
-/* === Parsing code === */
-/* This is the generic parsing code. */
-
-static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info)
-{
-       struct cb_memory *mem = (struct cb_memory *)ptr;
-       int count = MEM_RANGE_COUNT(mem);
-       int i;
-
-       if (count > SYSINFO_MAX_MEM_RANGES)
-               count = SYSINFO_MAX_MEM_RANGES;
-
-       info->n_memranges = 0;
-
-       for (i = 0; i < count; i++) {
-               struct cb_memory_range *range =
-                   (struct cb_memory_range *)MEM_RANGE_PTR(mem, i);
-
-               info->memrange[info->n_memranges].base =
-                   UNPACK_CB64(range->start);
-
-               info->memrange[info->n_memranges].size =
-                   UNPACK_CB64(range->size);
-
-               info->memrange[info->n_memranges].type = range->type;
-
-               info->n_memranges++;
-       }
-}
-
-static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info)
-{
-       struct cb_serial *ser = (struct cb_serial *)ptr;
-       info->serial = ser;
-}
-
-static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
-{
-       struct cb_vbnv *vbnv = (struct cb_vbnv *)ptr;
-
-       info->vbnv_start = vbnv->vbnv_start;
-       info->vbnv_size = vbnv->vbnv_size;
-}
-
-static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info)
-{
-       struct cb_cbmem_entry *entry = (struct cb_cbmem_entry *)ptr;
-
-       if (entry->id != CBMEM_ID_SMBIOS)
-               return;
-
-       info->smbios_start = entry->address;
-       info->smbios_size = entry->entry_size;
-}
-
-static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
-{
-       int i;
-       struct cb_gpios *gpios = (struct cb_gpios *)ptr;
-
-       info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ?
-                               (gpios->count) : SYSINFO_MAX_GPIOS;
-
-       for (i = 0; i < info->num_gpios; i++)
-               info->gpios[i] = gpios->gpios[i];
-}
-
-static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info)
-{
-       struct cb_vdat *vdat = (struct cb_vdat *) ptr;
-
-       info->vdat_addr = vdat->vdat_addr;
-       info->vdat_size = vdat->vdat_size;
-}
-
-static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info)
-{
-       info->tstamp_table = ((struct cb_cbmem_tab *)ptr)->cbmem_tab;
-}
-
-static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info)
-{
-       info->cbmem_cons = ((struct cb_cbmem_tab *)ptr)->cbmem_tab;
-}
-
-static void cb_parse_framebuffer(unsigned char *ptr, struct sysinfo_t *info)
-{
-       info->framebuffer = (struct cb_framebuffer *)ptr;
-}
-
-static void cb_parse_string(unsigned char *ptr, char **info)
-{
-       *info = (char *)((struct cb_string *)ptr)->string;
-}
-
-__weak void cb_parse_unhandled(u32 tag, unsigned char *ptr)
-{
-}
-
-static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
-{
-       unsigned char *ptr = addr;
-       struct cb_header *header;
-       int i;
-
-       header = (struct cb_header *)ptr;
-       if (!header->table_bytes)
-               return 0;
-
-       /* Make sure the checksums match. */
-       if (!ip_checksum_ok(header, sizeof(*header)))
-               return -1;
-
-       if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) !=
-           header->table_checksum)
-               return -1;
-
-       /* Now, walk the tables. */
-       ptr += header->header_bytes;
-
-       /* Inintialize some fields to sentinel values. */
-       info->vbnv_start = info->vbnv_size = (uint32_t)(-1);
-
-       for (i = 0; i < header->table_entries; i++) {
-               struct cb_record *rec = (struct cb_record *)ptr;
-
-               /* We only care about a few tags here (maybe more later). */
-               switch (rec->tag) {
-               case CB_TAG_FORWARD:
-                       return cb_parse_header(
-                               (void *)(unsigned long)
-                               ((struct cb_forward *)rec)->forward,
-                               len, info);
-                       continue;
-               case CB_TAG_MEMORY:
-                       cb_parse_memory(ptr, info);
-                       break;
-               case CB_TAG_SERIAL:
-                       cb_parse_serial(ptr, info);
-                       break;
-               case CB_TAG_VERSION:
-                       cb_parse_string(ptr, &info->version);
-                       break;
-               case CB_TAG_EXTRA_VERSION:
-                       cb_parse_string(ptr, &info->extra_version);
-                       break;
-               case CB_TAG_BUILD:
-                       cb_parse_string(ptr, &info->build);
-                       break;
-               case CB_TAG_COMPILE_TIME:
-                       cb_parse_string(ptr, &info->compile_time);
-                       break;
-               case CB_TAG_COMPILE_BY:
-                       cb_parse_string(ptr, &info->compile_by);
-                       break;
-               case CB_TAG_COMPILE_HOST:
-                       cb_parse_string(ptr, &info->compile_host);
-                       break;
-               case CB_TAG_COMPILE_DOMAIN:
-                       cb_parse_string(ptr, &info->compile_domain);
-                       break;
-               case CB_TAG_COMPILER:
-                       cb_parse_string(ptr, &info->compiler);
-                       break;
-               case CB_TAG_LINKER:
-                       cb_parse_string(ptr, &info->linker);
-                       break;
-               case CB_TAG_ASSEMBLER:
-                       cb_parse_string(ptr, &info->assembler);
-                       break;
-               /*
-                * FIXME we should warn on serial if coreboot set up a
-                * framebuffer buf the payload does not know about it.
-                */
-               case CB_TAG_FRAMEBUFFER:
-                       cb_parse_framebuffer(ptr, info);
-                       break;
-               case CB_TAG_GPIO:
-                       cb_parse_gpios(ptr, info);
-                       break;
-               case CB_TAG_VDAT:
-                       cb_parse_vdat(ptr, info);
-                       break;
-               case CB_TAG_TIMESTAMPS:
-                       cb_parse_tstamp(ptr, info);
-                       break;
-               case CB_TAG_CBMEM_CONSOLE:
-                       cb_parse_cbmem_cons(ptr, info);
-                       break;
-               case CB_TAG_VBNV:
-                       cb_parse_vbnv(ptr, info);
-                       break;
-               case CB_TAG_CBMEM_ENTRY:
-                       cb_parse_cbmem_entry(ptr, info);
-                       break;
-               default:
-                       cb_parse_unhandled(rec->tag, ptr);
-                       break;
-               }
-
-               ptr += rec->size;
-       }
-
-       return 1;
-}
-
-/* == Architecture specific == */
-/* This is the x86 specific stuff. */
-
-int get_coreboot_info(struct sysinfo_t *info)
-{
-       long addr;
-       int ret;
-
-       addr = locate_coreboot_table();
-       if (addr < 0)
-               return addr;
-       ret = cb_parse_header((void *)addr, 0x1000, info);
-       if (!ret)
-               return -ENOENT;
-       gd->arch.coreboot_table = addr;
-       gd->flags |= GD_FLG_SKIP_LL_INIT;
-
-       return 0;
-}
index 0162597..7f133ce 100644 (file)
@@ -8,21 +8,9 @@
 #include <common.h>
 #include <bootstage.h>
 #include <asm/arch/timestamp.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 #include <linux/compiler.h>
 
-struct timestamp_entry {
-       uint32_t        entry_id;
-       uint64_t        entry_stamp;
-} __packed;
-
-struct timestamp_table {
-       uint64_t        base_time;
-       uint32_t        max_entries;
-       uint32_t        num_entries;
-       struct timestamp_entry entries[0]; /* Variable number of entries */
-} __packed;
-
 static struct timestamp_table *ts_table  __attribute__((section(".data")));
 
 void timestamp_init(void)
index 588a512..1eff030 100644 (file)
@@ -153,8 +153,9 @@ static int route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
 
 static int itss_bind(struct udevice *dev)
 {
-       /* This is not set with of-platdata, so set it manually */
-       if (CONFIG_IS_ENABLED(OF_PLATDATA))
+       /* This is not set with basic of-platdata, so set it manually */
+       if (CONFIG_IS_ENABLED(OF_PLATDATA) &&
+           !CONFIG_IS_ENABLED(OF_PLATDATA_INST))
                dev->driver_data = X86_IRQT_ITSS;
 
        return 0;
index bddba3e..a02f4f9 100644 (file)
@@ -143,7 +143,7 @@ int checkcpu(void)
 
                /* System is not happy after keyboard reset... */
                debug("Issuing CF9 warm reset\n");
-               reset_cpu(0);
+               reset_cpu();
        }
 
        ret = cpu_common_init();
index 905c825..abfd4ab 100644 (file)
@@ -43,6 +43,10 @@ use_existing_stack:
 
        call    board_init_f_init_reserve
 
+#ifdef CONFIG_DEBUG_UART
+       call    debug_uart_init
+#endif
+
        call    x86_cpu_reinit_f
        xorl    %eax, %eax
        call    board_init_f
index b82e53a..4a655bf 100644 (file)
@@ -33,6 +33,14 @@ SECTIONS
        .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
 
        . = ALIGN(4);
+
+       .priv_data : {
+               __priv_data_start = .;
+               *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.priv_data*)))
+               __priv_data_end = .;
+       }
+
+       . = ALIGN(4);
        .data : { *(.data*) }
 
        . = ALIGN(4);
index 2ffe3b4..c8cb4e2 100644 (file)
@@ -47,6 +47,7 @@
                i2c5 = &i2c_5;
                i2c6 = &i2c_6;
                i2c7 = &i2c_7;
+               mmc0 = &emmc;
                mmc1 = &sdmmc;
        };
 
                recovery-gpios = <&gpio_nw (-1) GPIO_ACTIVE_LOW>;
                write-protect-gpios = <&gpio_nw GPIO_75 GPIO_ACTIVE_HIGH>;
                phase-enforce-gpios = <&gpio_n GPIO_10 GPIO_ACTIVE_HIGH>;
+               memconfig-gpios = <&gpio_nw GPIO_101 GPIO_ACTIVE_HIGH
+                       &gpio_nw GPIO_102 GPIO_ACTIVE_HIGH
+                       &gpio_n GPIO_38 GPIO_ACTIVE_HIGH
+                       &gpio_n GPIO_45 GPIO_ACTIVE_HIGH>;
+
+               /*
+                * This is used for reef only:
+                *
+                * skuconfig-gpios = <&gpio_nw GPIO_16 GPIO_ACTIVE_HIGH
+                *      &gpio_nw GPIO_17 GPIO_ACTIVE_HIGH>;
+                */
                smbios {
                        /* Type 1 table */
                        system {
        clk: clock {
                compatible = "intel,apl-clk";
                #clock-cells = <1>;
-               u-boot,dm-pre-reloc;
+               u-boot,dm-pre-proper;
        };
 
        cpus {
        };
 
        acpi_gpe: general-purpose-events {
-               u-boot,dm-pre-reloc;
+               u-boot,dm-pre-proper;
                reg = <IOMAP_ACPI_BASE IOMAP_ACPI_SIZE>;
                compatible = "intel,acpi-gpe";
                interrupt-controller;
                #interrupt-cells = <2>;
        };
 
+       coreboot-video {
+               /* This will only activate when booted from coreboot */
+               compatible = "coreboot-fb";
+       };
+
        keyboard {
                intel,duplicate-por;
        };
                        compatible = "intel,apl-i2c", "snps,designware-i2c-pci";
                        reg = <0x0200b210 0 0 0 0>;
                        early-regs = <IOMAP_I2C2_BASE 0x1000>;
-                       u-boot,dm-pre-reloc;
+                       u-boot,dm-pre-proper;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        clock-frequency = <400000>;
                        tpm: tpm@50 {
                                reg = <0x50>;
                                compatible = "google,cr50";
-                               u-boot,dm-pre-reloc;
+                               u-boot,dm-pre-proper;
                                u-boot,i2c-offset-len = <0>;
                                ready-gpios = <&gpio_n 28 GPIO_ACTIVE_LOW>;
                                interrupts-extended = <&acpi_gpe GPIO_28_IRQ
                sdmmc: sdmmc@1b,0 {
                        reg = <0x0000d800 0 0 0 0>;
                        compatible = "intel,apl-sd";
-                       cd-gpios = <&gpio_n GPIO_177 GPIO_ACTIVE_LOW>;
+                       cd-gpios = <&gpio_sw GPIO_177 GPIO_ACTIVE_LOW>;
                        acpi,name = "SDCD";
                };
 
 &rtc {
        #address-cells = <1>;
        #size-cells = <0>;
-       u-boot,dm-pre-reloc;
+       u-boot,dm-pre-proper;
 };
index 555d0dd..f2ba2fb 100644 (file)
@@ -1,6 +1,6 @@
 / {
        reset: reset {
                compatible = "x86,reset";
-               u-boot,dm-pre-reloc;
+               u-boot,dm-pre-proper;
        };
 };
index bf92f45..ca84d18 100644 (file)
        };
 #endif
        spl {
-               type = "section";
+               type = "u-boot-spl";
                offset = <CONFIG_X86_OFFSET_SPL>;
-               u-boot-spl {
-               };
-               u-boot-spl-dtb {
-               };
        };
        u-boot {
-               type = "section";
                offset = <CONFIG_X86_OFFSET_U_BOOT>;
-               u-boot-nodtb {
-               };
-               u-boot-dtb {
-               };
        };
 #elif defined(CONFIG_SPL)
        u-boot-spl-with-ucode-ptr {
                offset = <CONFIG_X86_OFFSET_U_BOOT>;
        };
 #else
-# ifdef CONFIG_SPL
-       u-boot {
-               offset = <CONFIG_SYS_TEXT_BASE>;
-       };
-# elif defined(CONFIG_HAVE_MICROCODE)
+# ifdef CONFIG_HAVE_MICROCODE
        /* If there is no SPL then we need to put microcode in U-Boot */
        u-boot-with-ucode-ptr {
                offset = <CONFIG_X86_OFFSET_U_BOOT>;
index 38335b0..c3ca171 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef _ASM_ARCH_UART_H
 #define _ASM_ARCH_UART_H
 
+#include <dt-structs.h>
 #include <ns16550.h>
 
 /**
diff --git a/arch/x86/include/asm/arch-coreboot/sysinfo.h b/arch/x86/include/asm/arch-coreboot/sysinfo.h
deleted file mode 100644 (file)
index 419ec52..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/*
- * This file is part of the libpayload project.
- *
- * Copyright (C) 2008 Advanced Micro Devices, Inc.
- */
-
-#ifndef _COREBOOT_SYSINFO_H
-#define _COREBOOT_SYSINFO_H
-
-#include <asm/coreboot_tables.h>
-
-/* Maximum number of memory range definitions */
-#define SYSINFO_MAX_MEM_RANGES 32
-/* Allow a maximum of 8 GPIOs */
-#define SYSINFO_MAX_GPIOS      8
-
-struct sysinfo_t {
-       int n_memranges;
-       struct memrange {
-               unsigned long long base;
-               unsigned long long size;
-               unsigned int type;
-       } memrange[SYSINFO_MAX_MEM_RANGES];
-
-       u32 cmos_range_start;
-       u32 cmos_range_end;
-       u32 cmos_checksum_location;
-       u32 vbnv_start;
-       u32 vbnv_size;
-
-       char *version;
-       char *extra_version;
-       char *build;
-       char *compile_time;
-       char *compile_by;
-       char *compile_host;
-       char *compile_domain;
-       char *compiler;
-       char *linker;
-       char *assembler;
-
-       struct cb_framebuffer *framebuffer;
-
-       int num_gpios;
-       struct cb_gpio gpios[SYSINFO_MAX_GPIOS];
-
-       void    *vdat_addr;
-       u32     vdat_size;
-       void    *tstamp_table;
-       void    *cbmem_cons;
-       u64 smbios_start;
-       u32 smbios_size;
-
-       struct cb_serial *serial;
-};
-
-extern struct sysinfo_t lib_sysinfo;
-
-int get_coreboot_info(struct sysinfo_t *info);
-
-#endif
index 85d42c0..531526b 100644 (file)
@@ -8,30 +8,7 @@
 #ifndef __COREBOOT_TIMESTAMP_H__
 #define __COREBOOT_TIMESTAMP_H__
 
-enum timestamp_id {
-       /* coreboot specific timestamp IDs */
-       TS_START_ROMSTAGE = 1,
-       TS_BEFORE_INITRAM = 2,
-       TS_AFTER_INITRAM = 3,
-       TS_END_ROMSTAGE = 4,
-       TS_START_COPYRAM = 8,
-       TS_END_COPYRAM = 9,
-       TS_START_RAMSTAGE = 10,
-       TS_DEVICE_ENUMERATE = 30,
-       TS_DEVICE_CONFIGURE = 40,
-       TS_DEVICE_ENABLE = 50,
-       TS_DEVICE_INITIALIZE = 60,
-       TS_DEVICE_DONE = 70,
-       TS_CBMEM_POST = 75,
-       TS_WRITE_TABLES = 80,
-       TS_LOAD_PAYLOAD = 90,
-       TS_ACPI_WAKE_JUMP = 98,
-       TS_SELFBOOT_JUMP = 99,
-
-       /* U-Boot entry IDs start at 1000 */
-       TS_U_BOOT_INITTED = 1000, /* This is where u-boot starts */
-       TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel. */
-};
+#include <asm/cb_sysinfo.h>
 
 void timestamp_init(void);
 void timestamp_add(enum timestamp_id id, uint64_t ts_time);
diff --git a/arch/x86/include/asm/cb_sysinfo.h b/arch/x86/include/asm/cb_sysinfo.h
new file mode 100644 (file)
index 0000000..675eef6
--- /dev/null
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _COREBOOT_SYSINFO_H
+#define _COREBOOT_SYSINFO_H
+
+#include <asm/coreboot_tables.h>
+
+/* Maximum number of memory range definitions */
+#define SYSINFO_MAX_MEM_RANGES 32
+/* Allow a maximum of 8 GPIOs */
+#define SYSINFO_MAX_GPIOS      8
+/* Up to 10 MAC addresses */
+#define SYSINFO_MAX_MACS 10
+
+/**
+ * struct sysinfo_t - Information passed to U-Boot from coreboot
+ *
+ * Coreboot passes on a lot of information using a list of individual data
+ * structures identified by a numeric tag. These are parsed in U-Boot to produce
+ * this struct. Some of the pointers here point back to the tagged data
+ * structure, since it is assumed to remain around while U-Boot is running.
+ *
+ * The 'cbsysinfo' command can display this information.
+ *
+ * @cpu_khz: CPU frequence in KHz (e.g. 1100000)
+ * @serial: Pointer to the serial information, NULL if none
+ * @ser_ioport: Not actually provided by a tag and not used on modern hardware,
+ *     which typicaally uses a memory-mapped port
+ * @ser_base: Not used at all, but present to match up with the coreboot data
+ *     structure
+ * @n_memranges: Number of memory ranges
+ * @memrange: List of memory ranges:
+ *     @base: Base address of range
+ *     @size: Size of range in bytes
+ *     @type: Type of range (CB_MEM_RAM, etc.)
+ * @option_table: Provides a pointer to the CMOS RAM options table, which
+ *     indicates which options are available. The header is followed by a list
+ *     of struct cb_cmos_entries records, so that an option can be found from
+ *     its name. This is not used in U-Boot. NULL if not present
+ * @cmos_range_start: Start bit of the CMOS checksum range (in fact this must
+ *     be a multiple of 8)
+ * @cmos_range_end: End bit of the CMOS checksum range (multiple of 8). This is
+ *     the inclusive end.
+ * @cmos_checksum_location: Location of checksum, multiplied by 8. This is the
+ *     byte offset into the CMOS RAM of the first checksum byte. The second one
+ *     follows immediately. The checksum is a simple 16-bit sum of all the
+ *     bytes from offset cmos_range_start / 8 to cmos_range_end / 8, inclusive,
+ *     in big-endian format (so sum >> 8 is stored in the first byte).
+ * @vbnv_start: Start offset of CMOS RAM used for Chromium OS verified boot
+ *     (typically 0x34)
+ * @vbnv_size: Number of bytes used by Chromium OS verified boot (typically
+ *     0x10)
+ * @extra_version: Extra version information, typically ""
+ * @build: Build date, e.g. "Wed Nov 18 02:51:58 UTC 2020"
+ * @compile_time: Compilation time, e.g. "02:51:58"
+ * @compile_by: Who compiled coreboot (never set?)
+ * @compile_host: Name of the machine that compiled coreboot (never set?)
+ * @compile_domain: Domain name of the machine that compiled coreboot (never
+ *     set?)
+ * @compiler: Name of the compiler used to build coreboot (never set?)
+ * @linker: Name of the linker used to build coreboot (never set?)
+ * @assembler: Name of the assembler used to build coreboot (never set?)
+ * @cb_version: Coreboot version string, e.g. v1.9308_26_0.0.22-2599-g232f22c75d
+ * @framebuffer: Address of framebuffer tag, or NULL if none. See
+ *     struct cb_framebuffer for the definition
+ * @num_gpios: Number of verified-boot GPIOs
+ * @gpios: List of GPIOs:
+ *     @port: GPIO number, or 0xffffffff if not a GPIO
+ *     @polarity: CB_GPIO_ACTIVE_LOW or CB_GPIO_ACTIVE_HIGH
+ *     @value: Value of GPIO (0 or 1)
+ *     @name: Name of GPIO
+ *
+ *     A typical list is:
+ *       id: port     polarity val name
+ *        0:    -  active-high   1 write protect
+ *        1:    -  active-high   0 recovery
+ *        2:    -  active-high   1 lid
+ *        3:    -  active-high   0 power
+ *        4:    -  active-high   0 oprom
+ *        5:   29  active-high   0 EC in RW
+ *
+ * @num_macs: Number of MAC addresses
+ * @macs: List of MAC addresses
+ * @serialno: Serial number, or NULL (never set?)
+ * @mbtable: Address of the multiboot table, or NULL. This is a
+ *     struct multiboot_header, not used in U-Boot
+ * @header: Address of header, if there is a CB_TAG_FORWARD, else NULL
+ * @mainboard: Pointer to mainboard info or NULL. Typically the vendor is
+ *     "Google" and the part number is ""
+ * @vboot_handoff: Pointer to Chromium OS verified boot hand-off information.
+ *     This is struct vboot_handoff, providing access to internal information
+ *     generated by coreboot when this is being used
+ * @vboot_handoff_size: Size of hand-off information (typically 0xc0c)
+ * @vdat_addr: Pointer to Chromium OS verified boot data, which uses
+ *     struct chromeos_acpi. It sits in the Intel Global NVS struct, after the
+ *     first 0x100 bytes
+ * @vdat_size: Size of this data, typically 0xf00
+ * @smbios_start: Address of SMBIOS tables
+ * @smbios_size: Size of SMBIOS tables (e.g. 0x800)
+ * @x86_rom_var_mtrr_index: MTRR number used for ROM caching. Not used in U-Boot
+ * @tstamp_table: Pointer to timestamp_table, struct timestamp_table
+ * @cbmem_cons: Pointer to the console dump, struct cbmem_console. This provides
+ *     access to the console output generated by coreboot, typically about 64KB
+ *     and mostly PCI enumeration info
+ * @mrc_cache: Pointer to memory-reference-code cache, typically NULL
+ * acpi_gnvs: @Pointer to Intel Global NVS struct, see struct acpi_global_nvs
+ * @board_id: Board ID indicating the board variant, typically 0xffffffff
+ * @ram_code: RAM code indicating the SDRAM type, typically 0xffffffff
+ * @wifi_calibration: WiFi calibration info, NULL if none
+ * @ramoops_buffer: Address of kernel Ramoops buffer
+ * @ramoops_buffer_size: Sizeof of Ramoops buffer, typically 1MB
+ * @spi_flash: Information about SPI flash:
+ *     @size: Size in bytes, e.g. 16MB
+ *     @sector_size; Sector size of flash device, e.g. 4KB
+ *     @erase_cmd: Command used to erase flash, or 0 if not used
+ * @fmap_offset: SPI-flash offset of the flash map (FMAP) table. This has a
+ *     __FMAP__ header. It provides information about the different top-level
+ *     sections in the SPI flash, e.g. 0x204000
+ * @cbfs_offset: SPI-flash offset of the Coreboot Filesystem (CBFS) used for
+ *     read-only data, e.g. 0x205000. This is typically called 'COREBOOT' in
+ *     the flash map. It holds various coreboot binaries as well as
+ *     video-configuration files and graphics data for the Chromium OS
+ *     verified boot user interface.
+ * @cbfs_size: Size of CBFS, e.g. 0x17b000
+ * @boot_media_size; Size of boot media (i.e. SPI flash), e.g. 16MB
+ * @mtc_start; Start of MTC region (Nvidia private data), 0 if not used. See
+ *     https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/chromeos-2013.04/src/soc/nvidia/tegra210/mtc.c
+ * @mtc_size: Size of MTC region
+ * @chromeos_vpd: Chromium OS Vital Product Data region, typically NULL, meaning
+ *     not used
+ */
+struct sysinfo_t {
+       unsigned int cpu_khz;
+       struct cb_serial *serial;
+       unsigned short ser_ioport;
+       unsigned long ser_base; // for mmapped serial
+
+       int n_memranges;
+
+       struct memrange {
+               unsigned long long base;
+               unsigned long long size;
+               unsigned int type;
+       } memrange[SYSINFO_MAX_MEM_RANGES];
+
+       struct cb_cmos_option_table *option_table;
+       u32 cmos_range_start;
+       u32 cmos_range_end;
+       u32 cmos_checksum_location;
+       u32 vbnv_start;
+       u32 vbnv_size;
+
+       char *version;
+       char *extra_version;
+       char *build;
+       char *compile_time;
+       char *compile_by;
+       char *compile_host;
+       char *compile_domain;
+       char *compiler;
+       char *linker;
+       char *assembler;
+
+       char *cb_version;
+
+       struct cb_framebuffer *framebuffer;
+
+       int num_gpios;
+       struct cb_gpio gpios[SYSINFO_MAX_GPIOS];
+       int num_macs;
+       struct mac_address macs[SYSINFO_MAX_MACS];
+       char *serialno;
+
+       unsigned long *mbtable; /** Pointer to the multiboot table */
+
+       struct cb_header *header;
+       struct cb_mainboard *mainboard;
+
+       void    *vboot_handoff;
+       u32     vboot_handoff_size;
+       void    *vdat_addr;
+       u32     vdat_size;
+       u64 smbios_start;
+       u32 smbios_size;
+
+       int x86_rom_var_mtrr_index;
+
+       void            *tstamp_table;
+       void            *cbmem_cons;
+       void            *mrc_cache;
+       void            *acpi_gnvs;
+       u32             board_id;
+       u32             ram_code;
+       void            *wifi_calibration;
+       u64     ramoops_buffer;
+       u32     ramoops_buffer_size;
+       struct {
+               u32 size;
+               u32 sector_size;
+               u32 erase_cmd;
+       } spi_flash;
+       u64 fmap_offset;
+       u64 cbfs_offset;
+       u64 cbfs_size;
+       u64 boot_media_size;
+       u64 mtc_start;
+       u32 mtc_size;
+       void    *chromeos_vpd;
+};
+
+extern struct sysinfo_t lib_sysinfo;
+
+int get_coreboot_info(struct sysinfo_t *info);
+
+#endif
index 7e15767..a74654b 100644 (file)
@@ -8,6 +8,106 @@
 #ifndef _COREBOOT_TABLES_H
 #define _COREBOOT_TABLES_H
 
+struct timestamp_entry {
+       u32     entry_id;
+       u64     entry_stamp;
+} __packed;
+
+struct timestamp_table {
+       u64     base_time;
+       u16     max_entries;
+       u16     tick_freq_mhz;
+       u32     num_entries;
+       struct timestamp_entry entries[0]; /* Variable number of entries */
+} __packed;
+
+enum timestamp_id {
+       /* coreboot-specific timestamp IDs */
+       TS_START_ROMSTAGE = 1,
+       TS_BEFORE_INITRAM = 2,
+       TS_AFTER_INITRAM = 3,
+       TS_END_ROMSTAGE = 4,
+       TS_START_VBOOT = 5,
+       TS_END_VBOOT = 6,
+       TS_START_COPYRAM = 8,
+       TS_END_COPYRAM = 9,
+       TS_START_RAMSTAGE = 10,
+       TS_START_BOOTBLOCK = 11,
+       TS_END_BOOTBLOCK = 12,
+       TS_START_COPYROM = 13,
+       TS_END_COPYROM = 14,
+       TS_START_ULZMA = 15,
+       TS_END_ULZMA = 16,
+       TS_START_ULZ4F = 17,
+       TS_END_ULZ4F = 18,
+       TS_DEVICE_ENUMERATE = 30,
+       TS_DEVICE_CONFIGURE = 40,
+       TS_DEVICE_ENABLE = 50,
+       TS_DEVICE_INITIALIZE = 60,
+       TS_DEVICE_DONE = 70,
+       TS_CBMEM_POST = 75,
+       TS_WRITE_TABLES = 80,
+       TS_FINALIZE_CHIPS = 85,
+       TS_LOAD_PAYLOAD = 90,
+       TS_ACPI_WAKE_JUMP = 98,
+       TS_SELFBOOT_JUMP = 99,
+
+       /* 500+ reserved for vendorcode extensions (500-600: google/chromeos) */
+       TS_START_COPYVER = 501,
+       TS_END_COPYVER = 502,
+       TS_START_TPMINIT = 503,
+       TS_END_TPMINIT = 504,
+       TS_START_VERIFY_SLOT = 505,
+       TS_END_VERIFY_SLOT = 506,
+       TS_START_HASH_BODY = 507,
+       TS_DONE_LOADING = 508,
+       TS_DONE_HASHING = 509,
+       TS_END_HASH_BODY = 510,
+       TS_START_COPYVPD = 550,
+       TS_END_COPYVPD_RO = 551,
+       TS_END_COPYVPD_RW = 552,
+
+       /* 940-950 reserved for vendorcode extensions (940-950: Intel ME) */
+       TS_ME_INFORM_DRAM_WAIT = 940,
+       TS_ME_INFORM_DRAM_DONE = 941,
+
+       /* 950+ reserved for vendorcode extensions (950-999: intel/fsp) */
+       TS_FSP_MEMORY_INIT_START = 950,
+       TS_FSP_MEMORY_INIT_END = 951,
+       TS_FSP_TEMP_RAM_EXIT_START = 952,
+       TS_FSP_TEMP_RAM_EXIT_END = 953,
+       TS_FSP_SILICON_INIT_START = 954,
+       TS_FSP_SILICON_INIT_END = 955,
+       TS_FSP_BEFORE_ENUMERATE = 956,
+       TS_FSP_AFTER_ENUMERATE = 957,
+       TS_FSP_BEFORE_FINALIZE = 958,
+       TS_FSP_AFTER_FINALIZE = 959,
+       TS_FSP_BEFORE_END_OF_FIRMWARE = 960,
+       TS_FSP_AFTER_END_OF_FIRMWARE = 961,
+
+       /* 1000+ reserved for payloads (1000-1200: ChromeOS depthcharge) */
+
+       /* U-Boot entry IDs start at 1000 */
+       TS_U_BOOT_INITTED = 1000, /* This is where U-Boot starts */
+
+       TS_RO_PARAMS_INIT = 1001,
+       TS_RO_VB_INIT = 1002,
+       TS_RO_VB_SELECT_FIRMWARE = 1003,
+       TS_RO_VB_SELECT_AND_LOAD_KERNEL = 1004,
+
+       TS_RW_VB_SELECT_AND_LOAD_KERNEL = 1010,
+
+       TS_VB_SELECT_AND_LOAD_KERNEL = 1020,
+       TS_VB_EC_VBOOT_DONE = 1030,
+       TS_VB_STORAGE_INIT_DONE = 1040,
+       TS_VB_READ_KERNEL_DONE = 1050,
+       TS_VB_VBOOT_DONE = 1100,
+
+       TS_START_KERNEL = 1101,
+       TS_KERNEL_DECOMPRESSION = 1102,
+       TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel */
+};
+
 struct memory_area;
 
 struct cbuint64 {
@@ -162,13 +262,14 @@ struct cb_framebuffer {
 };
 
 #define CB_TAG_GPIO                    0x0013
-#define GPIO_MAX_NAME_LENGTH           16
-
+#define CB_GPIO_ACTIVE_LOW             0
+#define CB_GPIO_ACTIVE_HIGH            1
+#define CB_GPIO_MAX_NAME_LENGTH                16
 struct cb_gpio {
        u32 port;
        u32 polarity;
        u32 value;
-       u8 name[GPIO_MAX_NAME_LENGTH];
+       u8 name[CB_GPIO_MAX_NAME_LENGTH];
 };
 
 struct cb_gpios {
@@ -181,61 +282,158 @@ struct cb_gpios {
 #define CB_TAG_FDT                     0x0014
 
 struct cb_fdt {
-       uint32_t tag;
-       uint32_t size;  /* size of the entire entry */
+       u32 tag;
+       u32 size;       /* size of the entire entry */
        /* the actual FDT gets placed here */
 };
 
 #define CB_TAG_VDAT                    0x0015
 
 struct cb_vdat {
-       uint32_t tag;
-       uint32_t size;  /* size of the entire entry */
+       u32 tag;
+       u32 size;       /* size of the entire entry */
        void *vdat_addr;
-       uint32_t vdat_size;
+       u32 vdat_size;
 };
 
 #define CB_TAG_TIMESTAMPS              0x0016
 #define CB_TAG_CBMEM_CONSOLE           0x0017
+
+struct cbmem_console {
+       u32 size;
+       u32 cursor;
+       char body[0];
+} __packed;
+
 #define CB_TAG_MRC_CACHE               0x0018
 
 struct cb_cbmem_tab {
-       uint32_t tag;
-       uint32_t size;
-       void *cbmem_tab;
+       u32 tag;
+       u32 size;
+       u64 cbmem_tab;
 };
 
 #define CB_TAG_VBNV                    0x0019
 
 struct cb_vbnv {
-       uint32_t tag;
-       uint32_t size;
-       uint32_t vbnv_start;
-       uint32_t vbnv_size;
+       u32 tag;
+       u32 size;
+       u32 vbnv_start;
+       u32 vbnv_size;
+};
+
+#define CB_TAG_VBOOT_HANDOFF           0x0020
+
+#define CB_TAG_X86_ROM_MTRR            0x0021
+struct cb_x86_rom_mtrr {
+       u32 tag;
+       u32 size;
+       /*
+        * The variable range MTRR index covering the ROM. If one wants to
+        * enable caching the ROM, the variable MTRR needs to be set to
+        * write-protect. To disable the caching after enabling set the
+        * type to uncacheable
+        */
+       u32 index;
+};
+
+#define CB_TAG_DMA                     0x0022
+#define CB_TAG_RAM_OOPS                        0x0023
+#define CB_TAG_ACPI_GNVS               0x0024
+
+#define CB_TAG_BOARD_ID                        0x0025
+struct cb_board_id {
+       u32 tag;
+       u32 size;
+       /* Board ID as retrieved from the board revision GPIOs. */
+       u32 board_id;
+};
+
+#define CB_TAG_MAC_ADDRS               0x0026
+struct mac_address {
+       u8 mac_addr[6];
+       u8 pad[2];         /* Pad it to 8 bytes to keep it simple. */
+};
+
+struct cb_macs {
+       u32 tag;
+       u32 size;
+       u32 count;
+       struct mac_address mac_addrs[0];
+};
+
+#define CB_TAG_WIFI_CALIBRATION                0x0027
+
+#define CB_TAG_RAM_CODE                        0x0028
+struct cb_ram_code {
+       u32 tag;
+       u32 size;
+       u32 ram_code;
+};
+
+#define CB_TAG_SPI_FLASH               0x0029
+struct cb_spi_flash {
+       u32 tag;
+       u32 size;
+       u32 flash_size;
+       u32 sector_size;
+       u32 erase_cmd;
+};
+
+#define CB_TAG_MTC                     0x002b
+#define CB_TAG_VPD                     0x002c
+struct lb_range {
+       u32 tag;
+       u32 size;
+       u64 range_start;
+       u32 range_size;
+};
+
+#define CB_TAG_BOOT_MEDIA_PARAMS       0x0030
+struct cb_boot_media_params {
+       u32 tag;
+       u32 size;
+       /* offsets are relative to start of boot media */
+       u64 fmap_offset;
+       u64 cbfs_offset;
+       u64 cbfs_size;
+       u64 boot_media_size;
 };
 
-#define CB_TAG_CBMEM_ENTRY 0x0031
-#define CBMEM_ID_SMBIOS    0x534d4254
+#define CB_TAG_CBMEM_ENTRY             0x0031
+#define CBMEM_ID_SMBIOS                        0x534d4254
 
 struct cb_cbmem_entry {
-       uint32_t tag;
-       uint32_t size;
-       uint64_t address;
-       uint32_t entry_size;
-       uint32_t id;
+       u32 tag;
+       u32 size;
+       u64 address;
+       u32 entry_size;
+       u32 id;
+};
+
+#define CB_TAG_TSC_INFO                        0x0032
+struct cb_tsc_info {
+       u32 tag;
+       u32 size;
+
+       u32 freq_khz;
 };
 
+#define CB_TAG_SERIALNO                        0x002a
+#define CB_MAX_SERIALNO_LENGTH         32
+
 #define CB_TAG_CMOS_OPTION_TABLE       0x00c8
 
 struct cb_cmos_option_table {
        u32 tag;
        u32 size;
        u32 header_length;
+       /* entries follow after this header */
 };
 
 #define CB_TAG_OPTION                  0x00c9
 
-#define CMOS_MAX_NAME_LENGTH           32
+#define CB_CMOS_MAX_NAME_LENGTH                32
 
 struct cb_cmos_entries {
        u32 tag;
@@ -244,34 +442,33 @@ struct cb_cmos_entries {
        u32 length;
        u32 config;
        u32 config_id;
-       u8 name[CMOS_MAX_NAME_LENGTH];
+       u8 name[CB_CMOS_MAX_NAME_LENGTH];
 };
 
 #define CB_TAG_OPTION_ENUM             0x00ca
-#define CMOS_MAX_TEXT_LENGTH           32
-
+#define CB_CMOS_MAX_TEXT_LENGTH                32
 struct cb_cmos_enums {
        u32 tag;
        u32 size;
        u32 config_id;
        u32 value;
-       u8 text[CMOS_MAX_TEXT_LENGTH];
+       u8 text[CB_CMOS_MAX_TEXT_LENGTH];
 };
 
 #define CB_TAG_OPTION_DEFAULTS         0x00cb
-#define CMOS_IMAGE_BUFFER_SIZE         128
+#define CB_CMOS_IMAGE_BUFFER_SIZE      128
 
 struct cb_cmos_defaults {
        u32 tag;
        u32 size;
        u32 name_length;
-       u8 name[CMOS_MAX_NAME_LENGTH];
-       u8 default_set[CMOS_IMAGE_BUFFER_SIZE];
+       u8 name[CB_CMOS_MAX_NAME_LENGTH];
+       u8 default_set[CB_CMOS_IMAGE_BUFFER_SIZE];
 };
 
 #define CB_TAG_OPTION_CHECKSUM         0x00cc
-#define CHECKSUM_NONE                  0
-#define CHECKSUM_PCBIOS                        1
+#define CB_CHECKSUM_NONE               0
+#define CB_CHECKSUM_PCBIOS             1
 
 struct cb_cmos_checksum {
        u32 tag;
index a66c0d2..850a0a7 100644 (file)
@@ -22,9 +22,23 @@ struct e820_entry {
 #define ISA_START_ADDRESS      0xa0000
 #define ISA_END_ADDRESS                0x100000
 
-/* Implementation defined function to install an e820 map */
+/* Implementation-defined function to install an e820 map */
 unsigned int install_e820_map(unsigned int max_entries,
                              struct e820_entry *);
+
+/**
+ * cb_install_e820_map() - Install e820 map provided by coreboot sysinfo
+ *
+ * This should be used when booting from coreboot, since in that case the
+ * memory areas are provided by coreboot in its sysinfo.
+ *
+ * @max_entries: Maximum number of entries to write
+ * @entries: Place to put entires
+ * @return number of entries written
+ */
+unsigned int cb_install_e820_map(unsigned int max_entries,
+                                struct e820_entry *entries);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_E820_H */
index 1ea141f..5d83d24 100644 (file)
 
 /* This file is included by device trees, so avoid BIT() macros */
 
+#define GPIO_DW_SIZE(x)                        (sizeof(u32) * (x))
+#define PAD_CFG_OFFSET(x, dw_num)      ((x) + GPIO_DW_SIZE(dw_num))
+#define PAD_CFG0_OFFSET(x)             PAD_CFG_OFFSET(x, 0)
+#define PAD_CFG1_OFFSET(x)             PAD_CFG_OFFSET(x, 1)
+
 #define PAD_CFG0_TX_STATE_BIT          0
 #define PAD_CFG0_TX_STATE              (1 << PAD_CFG0_TX_STATE_BIT)
 #define PAD_CFG0_RX_STATE_BIT          1
index 1bcbb49..65d9b3b 100644 (file)
@@ -15,6 +15,7 @@ ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
 endif
 obj-y  += cmd_boot.o
+obj-$(CONFIG_$(SPL_)COREBOOT_SYSINFO)  += coreboot/
 obj-$(CONFIG_SEABIOS) += coreboot_table.o
 obj-y  += early_cmos.o
 obj-y  += e820.o
index aa5f0bf..733dd71 100644 (file)
@@ -36,7 +36,7 @@ void bootm_announce_and_cleanup(void)
        printf("\nStarting kernel ...\n\n");
 
 #ifdef CONFIG_SYS_COREBOOT
-       timestamp_add_now(TS_U_BOOT_START_KERNEL);
+       timestamp_add_now(TS_START_KERNEL);
 #endif
        bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
 #if CONFIG_IS_ENABLED(BOOTSTAGE_REPORT)
diff --git a/arch/x86/lib/coreboot/Makefile b/arch/x86/lib/coreboot/Makefile
new file mode 100644 (file)
index 0000000..cb0ae1d
--- /dev/null
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier:     GPL-2.0+
+#
+# Copyright 2021 Google LLC
+#
+
+obj-y += cb_sysinfo.o
+obj-y += cb_support.o
diff --git a/arch/x86/lib/coreboot/cb_support.c b/arch/x86/lib/coreboot/cb_support.c
new file mode 100644 (file)
index 0000000..ebb45cd
--- /dev/null
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for booting from coreboot
+ *
+ * Copyright 2021 Google LLC
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <asm/e820.h>
+
+unsigned int cb_install_e820_map(unsigned int max_entries,
+                                struct e820_entry *entries)
+{
+       unsigned int num_entries;
+       int i;
+
+       num_entries = min((unsigned int)lib_sysinfo.n_memranges, max_entries);
+       if (num_entries < lib_sysinfo.n_memranges) {
+               printf("Warning: Limiting e820 map to %d entries\n",
+                      num_entries);
+       }
+       for (i = 0; i < num_entries; i++) {
+               struct memrange *memrange = &lib_sysinfo.memrange[i];
+
+               entries[i].addr = memrange->base;
+               entries[i].size = memrange->size;
+
+               /*
+                * coreboot has some extensions (type 6 & 16) to the E820 types.
+                * When we detect this, mark it as E820_RESERVED.
+                */
+               if (memrange->type == CB_MEM_VENDOR_RSVD ||
+                   memrange->type == CB_MEM_TABLE)
+                       entries[i].type = E820_RESERVED;
+               else
+                       entries[i].type = memrange->type;
+       }
+
+       return num_entries;
+}
diff --git a/arch/x86/lib/coreboot/cb_sysinfo.c b/arch/x86/lib/coreboot/cb_sysinfo.c
new file mode 100644 (file)
index 0000000..e2c65bf
--- /dev/null
@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2009 coresystems GmbH
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <init.h>
+#include <mapmem.h>
+#include <net.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This needs to be in the .data section so that it's copied over during
+ * relocation. By default it's put in the .bss section which is simply filled
+ * with zeroes when transitioning from "ROM", which is really RAM, to other
+ * RAM.
+ */
+struct sysinfo_t lib_sysinfo __attribute__((section(".data")));
+
+/*
+ * Some of this is x86 specific, and the rest of it is generic. Right now,
+ * since we only support x86, we'll avoid trying to make lots of infrastructure
+ * we don't need. If in the future, we want to use coreboot on some other
+ * architecture, then take out the generic parsing code and move it elsewhere.
+ */
+
+/* === Parsing code === */
+/* This is the generic parsing code */
+
+static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info)
+{
+       struct cb_memory *mem = (struct cb_memory *)ptr;
+       int count = MEM_RANGE_COUNT(mem);
+       int i;
+
+       if (count > SYSINFO_MAX_MEM_RANGES)
+               count = SYSINFO_MAX_MEM_RANGES;
+
+       info->n_memranges = 0;
+
+       for (i = 0; i < count; i++) {
+               struct cb_memory_range *range =
+                   (struct cb_memory_range *)MEM_RANGE_PTR(mem, i);
+
+               info->memrange[info->n_memranges].base =
+                   UNPACK_CB64(range->start);
+
+               info->memrange[info->n_memranges].size =
+                   UNPACK_CB64(range->size);
+
+               info->memrange[info->n_memranges].type = range->type;
+
+               info->n_memranges++;
+       }
+}
+
+static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info)
+{
+       struct cb_serial *ser = (struct cb_serial *)ptr;
+
+       info->serial = ser;
+}
+
+static void cb_parse_vboot_handoff(unsigned char *ptr, struct sysinfo_t *info)
+{
+       struct lb_range *vbho = (struct lb_range *)ptr;
+
+       info->vboot_handoff = (void *)(uintptr_t)vbho->range_start;
+       info->vboot_handoff_size = vbho->range_size;
+}
+
+static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
+{
+       struct lb_range *vbnv = (struct lb_range *)ptr;
+
+       info->vbnv_start = vbnv->range_start;
+       info->vbnv_size = vbnv->range_size;
+}
+
+static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info)
+{
+       struct cb_cbmem_entry *entry = (struct cb_cbmem_entry *)ptr;
+
+       if (entry->id != CBMEM_ID_SMBIOS)
+               return;
+
+       info->smbios_start = entry->address;
+       info->smbios_size = entry->entry_size;
+}
+
+static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
+{
+       int i;
+       struct cb_gpios *gpios = (struct cb_gpios *)ptr;
+
+       info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ?
+                               (gpios->count) : SYSINFO_MAX_GPIOS;
+
+       for (i = 0; i < info->num_gpios; i++)
+               info->gpios[i] = gpios->gpios[i];
+}
+
+static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info)
+{
+       struct lb_range *vdat = (struct lb_range *)ptr;
+
+       info->vdat_addr = map_sysmem(vdat->range_start, vdat->range_size);
+       info->vdat_size = vdat->range_size;
+}
+
+static void cb_parse_mac_addresses(unsigned char *ptr,
+                                  struct sysinfo_t *info)
+{
+       struct cb_macs *macs = (struct cb_macs *)ptr;
+       int i;
+
+       info->num_macs = (macs->count < ARRAY_SIZE(info->macs)) ?
+               macs->count : ARRAY_SIZE(info->macs);
+
+       for (i = 0; i < info->num_macs; i++)
+               info->macs[i] = macs->mac_addrs[i];
+}
+
+static void cb_parse_tstamp(void *ptr, struct sysinfo_t *info)
+{
+       struct cb_cbmem_tab *const cbmem = ptr;
+
+       info->tstamp_table = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_cbmem_cons(void *ptr, struct sysinfo_t *info)
+{
+       struct cb_cbmem_tab *const cbmem = ptr;
+
+       info->cbmem_cons = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_acpi_gnvs(unsigned char *ptr, struct sysinfo_t *info)
+{
+       struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+       info->acpi_gnvs = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_board_id(unsigned char *ptr, struct sysinfo_t *info)
+{
+       struct cb_board_id *const cbbid = (struct cb_board_id *)ptr;
+
+       info->board_id = cbbid->board_id;
+}
+
+static void cb_parse_ram_code(unsigned char *ptr, struct sysinfo_t *info)
+{
+       struct cb_ram_code *const ram_code = (struct cb_ram_code *)ptr;
+
+       info->ram_code = ram_code->ram_code;
+}
+
+static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info)
+{
+       /* ptr points to a coreboot table entry and is already virtual */
+       info->option_table = ptr;
+}
+
+static void cb_parse_checksum(void *ptr, struct sysinfo_t *info)
+{
+       struct cb_cmos_checksum *cmos_cksum = ptr;
+
+       info->cmos_range_start = cmos_cksum->range_start;
+       info->cmos_range_end = cmos_cksum->range_end;
+       info->cmos_checksum_location = cmos_cksum->location;
+}
+
+static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info)
+{
+       /* ptr points to a coreboot table entry and is already virtual */
+       info->framebuffer = ptr;
+}
+
+static void cb_parse_string(unsigned char *ptr, char **info)
+{
+       *info = (char *)((struct cb_string *)ptr)->string;
+}
+
+static void cb_parse_wifi_calibration(void *ptr, struct sysinfo_t *info)
+{
+       struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+       info->wifi_calibration = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_ramoops(void *ptr, struct sysinfo_t *info)
+{
+       struct lb_range *ramoops = (struct lb_range *)ptr;
+
+       info->ramoops_buffer = ramoops->range_start;
+       info->ramoops_buffer_size = ramoops->range_size;
+}
+
+static void cb_parse_mtc(void *ptr, struct sysinfo_t *info)
+{
+       struct lb_range *mtc = (struct lb_range *)ptr;
+
+       info->mtc_start = mtc->range_start;
+       info->mtc_size = mtc->range_size;
+}
+
+static void cb_parse_spi_flash(void *ptr, struct sysinfo_t *info)
+{
+       struct cb_spi_flash *flash = (struct cb_spi_flash *)ptr;
+
+       info->spi_flash.size = flash->flash_size;
+       info->spi_flash.sector_size = flash->sector_size;
+       info->spi_flash.erase_cmd = flash->erase_cmd;
+}
+
+static void cb_parse_boot_media_params(unsigned char *ptr,
+                                      struct sysinfo_t *info)
+{
+       struct cb_boot_media_params *const bmp =
+                       (struct cb_boot_media_params *)ptr;
+
+       info->fmap_offset = bmp->fmap_offset;
+       info->cbfs_offset = bmp->cbfs_offset;
+       info->cbfs_size = bmp->cbfs_size;
+       info->boot_media_size = bmp->boot_media_size;
+}
+
+static void cb_parse_vpd(void *ptr, struct sysinfo_t *info)
+{
+       struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+       info->chromeos_vpd = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_tsc_info(void *ptr, struct sysinfo_t *info)
+{
+       const struct cb_tsc_info *tsc_info = ptr;
+
+       if (tsc_info->freq_khz == 0)
+               return;
+
+       /* Honor the TSC frequency passed to the payload */
+       info->cpu_khz = tsc_info->freq_khz;
+}
+
+static void cb_parse_x86_rom_var_mtrr(void *ptr, struct sysinfo_t *info)
+{
+       struct cb_x86_rom_mtrr *rom_mtrr = ptr;
+
+       info->x86_rom_var_mtrr_index = rom_mtrr->index;
+}
+
+static void cb_parse_mrc_cache(void *ptr, struct sysinfo_t *info)
+{
+       struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+       info->mrc_cache = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+__weak void cb_parse_unhandled(u32 tag, unsigned char *ptr)
+{
+}
+
+static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
+{
+       unsigned char *ptr = addr;
+       struct cb_header *header;
+       int i;
+
+       header = (struct cb_header *)ptr;
+       if (!header->table_bytes)
+               return 0;
+
+       /* Make sure the checksums match */
+       if (!ip_checksum_ok(header, sizeof(*header)))
+               return -1;
+
+       if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) !=
+           header->table_checksum)
+               return -1;
+
+       info->header = header;
+
+       /*
+        * Board straps represented by numerical values are small numbers.
+        * Preset them to an invalid value in case the firmware does not
+        * supply the info.
+        */
+       info->board_id = ~0;
+       info->ram_code = ~0;
+
+       /* Now, walk the tables */
+       ptr += header->header_bytes;
+
+       /* Inintialize some fields to sentinel values */
+       info->vbnv_start = info->vbnv_size = (uint32_t)(-1);
+
+       for (i = 0; i < header->table_entries; i++) {
+               struct cb_record *rec = (struct cb_record *)ptr;
+
+               /* We only care about a few tags here (maybe more later) */
+               switch (rec->tag) {
+               case CB_TAG_FORWARD:
+                       return cb_parse_header(
+                               (void *)(unsigned long)
+                               ((struct cb_forward *)rec)->forward,
+                               len, info);
+                       continue;
+               case CB_TAG_MEMORY:
+                       cb_parse_memory(ptr, info);
+                       break;
+               case CB_TAG_SERIAL:
+                       cb_parse_serial(ptr, info);
+                       break;
+               case CB_TAG_VERSION:
+                       cb_parse_string(ptr, &info->cb_version);
+                       break;
+               case CB_TAG_EXTRA_VERSION:
+                       cb_parse_string(ptr, &info->extra_version);
+                       break;
+               case CB_TAG_BUILD:
+                       cb_parse_string(ptr, &info->build);
+                       break;
+               case CB_TAG_COMPILE_TIME:
+                       cb_parse_string(ptr, &info->compile_time);
+                       break;
+               case CB_TAG_COMPILE_BY:
+                       cb_parse_string(ptr, &info->compile_by);
+                       break;
+               case CB_TAG_COMPILE_HOST:
+                       cb_parse_string(ptr, &info->compile_host);
+                       break;
+               case CB_TAG_COMPILE_DOMAIN:
+                       cb_parse_string(ptr, &info->compile_domain);
+                       break;
+               case CB_TAG_COMPILER:
+                       cb_parse_string(ptr, &info->compiler);
+                       break;
+               case CB_TAG_LINKER:
+                       cb_parse_string(ptr, &info->linker);
+                       break;
+               case CB_TAG_ASSEMBLER:
+                       cb_parse_string(ptr, &info->assembler);
+                       break;
+               case CB_TAG_CMOS_OPTION_TABLE:
+                       cb_parse_optiontable(ptr, info);
+                       break;
+               case CB_TAG_OPTION_CHECKSUM:
+                       cb_parse_checksum(ptr, info);
+                       break;
+               /*
+                * FIXME we should warn on serial if coreboot set up a
+                * framebuffer buf the payload does not know about it.
+                */
+               case CB_TAG_FRAMEBUFFER:
+                       cb_parse_framebuffer(ptr, info);
+                       break;
+               case CB_TAG_MAINBOARD:
+                       info->mainboard = (struct cb_mainboard *)ptr;
+                       break;
+               case CB_TAG_GPIO:
+                       cb_parse_gpios(ptr, info);
+                       break;
+               case CB_TAG_VDAT:
+                       cb_parse_vdat(ptr, info);
+                       break;
+               case CB_TAG_VBNV:
+                       cb_parse_vbnv(ptr, info);
+                       break;
+               case CB_TAG_VBOOT_HANDOFF:
+                       cb_parse_vboot_handoff(ptr, info);
+                       break;
+               case CB_TAG_MAC_ADDRS:
+                       cb_parse_mac_addresses(ptr, info);
+                       break;
+               case CB_TAG_SERIALNO:
+                       cb_parse_string(ptr, &info->serialno);
+                       break;
+               case CB_TAG_TIMESTAMPS:
+                       cb_parse_tstamp(ptr, info);
+                       break;
+               case CB_TAG_CBMEM_CONSOLE:
+                       cb_parse_cbmem_cons(ptr, info);
+                       break;
+               case CB_TAG_ACPI_GNVS:
+                       cb_parse_acpi_gnvs(ptr, info);
+                       break;
+               case CB_TAG_CBMEM_ENTRY:
+                       cb_parse_cbmem_entry(ptr, info);
+                       break;
+               case CB_TAG_BOARD_ID:
+                       cb_parse_board_id(ptr, info);
+                       break;
+               case CB_TAG_RAM_CODE:
+                       cb_parse_ram_code(ptr, info);
+                       break;
+               case CB_TAG_WIFI_CALIBRATION:
+                       cb_parse_wifi_calibration(ptr, info);
+                       break;
+               case CB_TAG_RAM_OOPS:
+                       cb_parse_ramoops(ptr, info);
+                       break;
+               case CB_TAG_SPI_FLASH:
+                       cb_parse_spi_flash(ptr, info);
+                       break;
+               case CB_TAG_MTC:
+                       cb_parse_mtc(ptr, info);
+                       break;
+               case CB_TAG_BOOT_MEDIA_PARAMS:
+                       cb_parse_boot_media_params(ptr, info);
+                       break;
+               case CB_TAG_TSC_INFO:
+                       cb_parse_tsc_info(ptr, info);
+                       break;
+               case CB_TAG_VPD:
+                       cb_parse_vpd(ptr, info);
+                       break;
+               case CB_TAG_X86_ROM_MTRR:
+                       cb_parse_x86_rom_var_mtrr(rec, info);
+                       break;
+               case CB_TAG_MRC_CACHE:
+                       cb_parse_mrc_cache(rec, info);
+                       break;
+               default:
+                       cb_parse_unhandled(rec->tag, ptr);
+                       break;
+               }
+
+               ptr += rec->size;
+       }
+
+       return 1;
+}
+
+/* == Architecture specific == */
+/* This is the x86 specific stuff */
+
+int get_coreboot_info(struct sysinfo_t *info)
+{
+       long addr;
+       int ret;
+
+       addr = locate_coreboot_table();
+       if (addr < 0)
+               return addr;
+       ret = cb_parse_header((void *)addr, 0x1000, info);
+       if (!ret)
+               return -ENOENT;
+       gd->arch.coreboot_table = addr;
+       gd->flags |= GD_FLG_SKIP_LL_INIT;
+
+       return 0;
+}
+
+const struct sysinfo_t *cb_get_sysinfo(void)
+{
+       if (!ll_boot_init())
+               return &lib_sysinfo;
+
+       return NULL;
+}
index cc909e0..02fd05c 100644 (file)
@@ -87,7 +87,7 @@ static int fsp_video_probe(struct udevice *dev)
        int ret;
 
        if (!ll_boot_init())
-               return 0;
+               return -ENODEV;
 
        printf("Video: ");
 
index 85cae54..5afdce1 100644 (file)
@@ -84,7 +84,8 @@ static int get_cbfs_fsp(enum fsp_type_t type, ulong map_base,
        struct cbfs_priv *cbfs;
        int ret;
 
-       ret = cbfs_init_mem(map_base + cbfs_base, &cbfs);
+       ret = cbfs_init_mem(map_base + cbfs_base, CBFS_SIZE_UNKNOWN, true,
+                           &cbfs);
        if (ret)
                return ret;
        if (!ret) {
index 503f97d..b2c7658 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <init.h>
 #include <log.h>
 #include <spi_flash.h>
 #include <asm/fsp/fsp_support.h>
@@ -114,6 +115,9 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
        struct fsp_notify_params *params_ptr;
        u32 status;
 
+       if (!ll_boot_init())
+               return 0;
+
        if (!fsp_hdr)
                fsp_hdr = gd->arch.fsp_s_hdr;
 
index 066dc40..67401b9 100644 (file)
@@ -18,6 +18,9 @@ int init_cache_f_r(void)
                 IS_ENABLED(CONFIG_FSP_VERSION2);
        int ret;
 
+       if (!ll_boot_init())
+               return 0;
+
        do_mtrr &= !IS_ENABLED(CONFIG_FSP_VERSION1) &&
                !IS_ENABLED(CONFIG_SYS_SLIMBOOTLOADER);
 
@@ -31,9 +34,6 @@ int init_cache_f_r(void)
                        return ret;
        }
 
-       if (!ll_boot_init())
-               return 0;
-
        /* Initialise the CPU cache(s) */
        return init_cache();
 }
index 1bae1f4..b18c1cd 100644 (file)
@@ -96,7 +96,7 @@ static int x86_spl_init(void)
        }
 #endif
        preloader_console_init();
-#ifndef CONFIG_TPL
+#if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU)
        ret = print_cpuinfo();
        if (ret) {
                debug("%s: print_cpuinfo() failed\n", __func__);
index ac6b6ef..b3e5f9c 100644 (file)
@@ -150,5 +150,6 @@ U_BOOT_DRIVER(pci_x86) = {
        .name   = "pci_x86",
        .id     = UCLASS_SIMPLE_BUS,
        .of_match = of_match_ptr(tpl_fake_pci_ids),
+       DM_PHASE(tpl)
 };
 #endif
index 602788e..90fc8a4 100644 (file)
@@ -18,6 +18,7 @@
 #include <bootm.h>
 #include <command.h>
 #include <env.h>
+#include <init.h>
 #include <irq_func.h>
 #include <log.h>
 #include <malloc.h>
@@ -28,6 +29,7 @@
 #include <asm/byteorder.h>
 #include <asm/bootm.h>
 #include <asm/bootparam.h>
+#include <asm/global_data.h>
 #ifdef CONFIG_SYS_COREBOOT
 #include <asm/arch/timestamp.h>
 #endif
@@ -35,6 +37,8 @@
 #include <linux/ctype.h>
 #include <linux/libfdt.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /*
  * Memory lay-out:
  *
@@ -309,8 +313,13 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
        int bootproto = get_boot_protocol(hdr, false);
 
        log_debug("Setup E820 entries\n");
-       setup_base->e820_entries = install_e820_map(
-               ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
+       if (ll_boot_init()) {
+               setup_base->e820_entries = install_e820_map(
+                       ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
+       } else if (IS_ENABLED(CONFIG_COREBOOT_SYSINFO)) {
+               setup_base->e820_entries = cb_install_e820_map(
+                       ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
+       }
 
        if (bootproto == 0x0100) {
                setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC;
index e6eb403..ee006f0 100644 (file)
@@ -540,7 +540,7 @@ void board_init_f(ulong dummy)
        spl_dram_init();
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 #endif /* CONFIG_SPL_BUILD */
index 52dc5b8..89e7322 100644 (file)
@@ -9,7 +9,7 @@
 #include <netdev.h>
 #include <asm/io.h>
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 #define CRM_SWRESET    0xff101044
        writel(0x1, (void *)CRM_SWRESET);
index 8492e76..ace18b2 100644 (file)
@@ -115,7 +115,7 @@ int board_init(void)
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        /* TODO */
 }
index 01c65e4..b7eaab0 100644 (file)
@@ -63,6 +63,6 @@ int dram_init_banksize(void)
 }
 
 /* Nothing to be done here as handled by PSCI interface */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index df4cbd3..ba3278a 100644 (file)
@@ -174,7 +174,7 @@ int v2m_cfg_write(u32 devfn, u32 data)
 }
 
 /* Use the ARM Watchdog System to cause reset */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0))
                printf("Unable to reboot\n");
index 9d29490..2e42602 100644 (file)
@@ -143,7 +143,7 @@ void *board_fdt_blob_setup(void)
 #endif
 
 /* Actual reset is done via PSCI. */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
index 1bae283..c1c3dfd 100644 (file)
@@ -322,6 +322,6 @@ int board_late_init(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index c343de5..0c7f8e5 100644 (file)
@@ -47,7 +47,7 @@ int dram_init_banksize(void)
 #define RST_CA57RESCNT (RST_BASE + 0x40)
 #define RST_CODE       0xA5A5000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        writel(RST_CODE, RST_CA57RESCNT);
 }
index bfce291..e893781 100644 (file)
@@ -486,7 +486,7 @@ static void bosch_check_reset_pin(void)
                printf("Resetting ...\n");
                writel(RESET_MASK, GPIO1_BASE + OMAP_GPIO_IRQSTATUS_SET_0);
                disable_interrupts();
-               reset_cpu(0);
+               reset_cpu();
                /*NOTREACHED*/
        }
 }
index 494e457..ee586d5 100644 (file)
@@ -57,7 +57,7 @@ int dram_init_banksize(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        psci_system_reset();
 }
index 9d2df92..758a358 100644 (file)
@@ -15,9 +15,6 @@
 #include <dt-bindings/memory/bcm-ns3-mc.h>
 #include <broadcom/chimp.h>
 
-/* Default reset-level = 3 and strap-val = 0 */
-#define L3_RESET       30
-
 #define BANK_OFFSET(bank)      ((u64)BCM_NS3_DDR_INFO_BASE + 8 + ((bank) * 16))
 
 /*
@@ -188,25 +185,10 @@ ulong board_get_usable_ram_top(ulong total_size)
        return BCM_NS3_MEM_END;
 }
 
-void reset_cpu(ulong level)
+void reset_cpu(void)
 {
-       u32 reset_level, strap_val;
-
-       /* Default reset type is L3 reset */
-       if (!level) {
-               /*
-                * Encoding: U-Boot reset command expects decimal argument,
-                * Boot strap val: Bits[3:0]
-                * reset level: Bits[7:4]
-                */
-               strap_val = L3_RESET % 10;
-               level = L3_RESET / 10;
-               reset_level = level % 10;
-               psci_system_reset2(reset_level, strap_val);
-       } else {
-               /* U-Boot cmd "reset" with any arg will trigger L1 reset */
-               psci_system_reset();
-       }
+       /* Perform a level 3 reset */
+       psci_system_reset2(3, 0);
 }
 
 #ifdef CONFIG_OF_BOARD_SETUP
index f6bdf1f..ee0a341 100644 (file)
@@ -43,7 +43,7 @@ u32 get_board_rev(void)
        return 0;
 }
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 }
 
index b09f72c..a7dc5c6 100644 (file)
@@ -110,7 +110,7 @@ int dram_init(void)
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
index 8662632..33264df 100644 (file)
@@ -96,7 +96,7 @@ static void probe_sdram_size(long size)
                break;
        default:
                puts("Failed configuring DRAM, resetting...\n\n");
-               reset_cpu(0);
+               reset_cpu();
        }
        debug("%s: setting DRAM size to %ldM\n", __func__, size >> 20);
        config_ddr(303, &ioregs, &ddr3_data,
index 9aafb89..175d3ce 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 #include <common.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 #include <asm/global_data.h>
 #include <init.h>
 #include <smbios.h>
index 5c73522..f344622 100644 (file)
@@ -115,7 +115,7 @@ int dram_init(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        invoke_psci_fn_smc(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
 }
index c677220..682099a 100644 (file)
@@ -105,7 +105,7 @@ int board_init(void)
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        /* TODO */
 }
index 7179823..21cfa14 100644 (file)
@@ -129,7 +129,7 @@ int board_init(void)
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        /* TODO */
 }
index c82b532..61d0ca3 100644 (file)
@@ -425,7 +425,7 @@ void board_init_f(ulong dummy)
                    is_cpu_type(MXC_CPU_MX6SL)) {
                        printf("cpu type 0x%x doesn't support 64-bit bus\n",
                               get_cpu_type());
-                       reset_cpu(0);
+                       reset_cpu();
                }
        }
 #ifdef CONFIG_MX6SL
index 4f1dc3b..dc424f2 100644 (file)
@@ -288,8 +288,8 @@ int last_stage_init(void)
        ccdc_eth_init();
 #endif
        ret = get_tpm(&tpm);
-       if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR) ||
-           tpm_continue_self_test(tpm)) {
+       if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR) ||
+           tpm1_continue_self_test(tpm)) {
                return 1;
        }
 
index 699241b..de5411a 100644 (file)
@@ -107,8 +107,8 @@ static int get_tpm_nv_size(struct udevice *tpm, uint32_t index, uint32_t *size)
        uint8_t *ptr;
        uint16_t v16;
 
-       err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index,
-                                info, sizeof(info));
+       err = tpm1_get_capability(tpm, TPM_CAP_NV_INDEX, index, info,
+                                 sizeof(info));
        if (err) {
                printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
                       index, err);
@@ -150,8 +150,8 @@ static int find_key(struct udevice *tpm, const uint8_t auth[20],
        unsigned int i;
 
        /* fetch list of already loaded keys in the TPM */
-       err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
-                                sizeof(buf));
+       err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+                                 sizeof(buf));
        if (err)
                return -1;
        key_count = get_unaligned_be16(buf);
@@ -162,8 +162,8 @@ static int find_key(struct udevice *tpm, const uint8_t auth[20],
        /* now search a(/ the) key which we can access with the given auth */
        for (i = 0; i < key_count; ++i) {
                buf_len = sizeof(buf);
-               err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
-                                          &buf_len);
+               err = tpm1_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
+                                           &buf_len);
                if (err && err != TPM_AUTHFAIL)
                        return -1;
                if (err)
@@ -192,8 +192,8 @@ static int read_common_data(struct udevice *tpm)
        if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) ||
            size < NV_COMMON_DATA_MIN_SIZE)
                return 1;
-       err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX,
-                               buf, min(sizeof(buf), size));
+       err = tpm1_nv_read_value(tpm, NV_COMMON_DATA_INDEX, buf,
+                                min(sizeof(buf), size));
        if (err) {
                printf("tpm_nv_read_value() failed: %u\n", err);
                return 1;
@@ -270,8 +270,8 @@ static struct h_reg *access_hreg(struct udevice *tpm, uint8_t spec,
        if (mode & HREG_RD) {
                if (!result->valid) {
                        if (IS_PCR_HREG(spec)) {
-                               hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec),
-                                       result->digest, 20);
+                               hre_tpm_err = tpm1_pcr_read(tpm, HREG_IDX(spec),
+                                                           result->digest, 20);
                                result->valid = (hre_tpm_err == TPM_SUCCESS);
                        } else if (IS_FIX_HREG(spec)) {
                                switch (HREG_IDX(spec)) {
@@ -357,8 +357,8 @@ static int hre_op_loadkey(struct udevice *tpm, struct h_reg *src_reg,
                return -1;
        if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle))
                return -1;
-       hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size,
-                                        src_reg->digest, &key_handle);
+       hre_tpm_err = tpm1_load_key2_oiap(tpm, parent_handle, key, key_size,
+                                         src_reg->digest, &key_handle);
        if (hre_tpm_err) {
                hre_err = HRE_E_TPM_FAILURE;
                return -1;
@@ -474,8 +474,8 @@ do_bin_func:
        }
 
        if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
-               hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec),
-                                        dst_reg->digest, dst_reg->digest);
+               hre_tpm_err = tpm1_extend(tpm, HREG_IDX(dst_spec),
+                                         dst_reg->digest, dst_reg->digest);
                if (hre_tpm_err) {
                        hre_err = HRE_E_TPM_FAILURE;
                        return NULL;
index 853981a..7020fae 100644 (file)
@@ -23,15 +23,15 @@ int flush_keys(struct udevice *tpm)
        uint i;
 
        /* fetch list of already loaded keys in the TPM */
-       err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
-                                sizeof(buf));
+       err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+                                 sizeof(buf));
        if (err)
                return -1;
        key_count = get_unaligned_be16(buf);
        ptr = buf + 2;
        for (i = 0; i < key_count; ++i, ptr += 4) {
-               err = tpm_flush_specific(tpm, get_unaligned_be32(ptr),
-                                        TPM_RT_KEY);
+               err = tpm1_flush_specific(tpm, get_unaligned_be32(ptr),
+                                         TPM_RT_KEY);
                if (err && err != TPM_KEY_OWNER_CONTROL)
                        return err;
        }
index 4e974c5..3d4a7e5 100644 (file)
@@ -145,8 +145,8 @@ int last_stage_init(void)
        env_set_ulong("fpga_hw_rev", fpga_hw_rev);
 
        ret = get_tpm(&tpm);
-       if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR) ||
-           tpm_continue_self_test(tpm)) {
+       if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR) ||
+           tpm1_continue_self_test(tpm)) {
                printf("TPM init failed\n");
        }
 
index 1b5aa90..87b346a 100644 (file)
@@ -273,8 +273,8 @@ static int get_tpm_nv_size(struct udevice *tpm, uint32_t index, uint32_t *size)
        uint8_t *ptr;
        uint16_t v16;
 
-       err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index,
-                                info, sizeof(info));
+       err = tpm1_get_capability(tpm, TPM_CAP_NV_INDEX, index, info,
+                                 sizeof(info));
        if (err) {
                printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
                       index, err);
@@ -315,8 +315,8 @@ static int find_key(struct udevice *tpm, const uint8_t auth[20],
        unsigned int i;
 
        /* fetch list of already loaded keys in the TPM */
-       err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
-                                sizeof(buf));
+       err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+                                 sizeof(buf));
        if (err)
                return -1;
        key_count = get_unaligned_be16(buf);
@@ -327,8 +327,8 @@ static int find_key(struct udevice *tpm, const uint8_t auth[20],
        /* now search a(/ the) key which we can access with the given auth */
        for (i = 0; i < key_count; ++i) {
                buf_len = sizeof(buf);
-               err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
-                                          &buf_len);
+               err = tpm1_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
+                                           &buf_len);
                if (err && err != TPM_AUTHFAIL)
                        return -1;
                if (err)
@@ -356,8 +356,8 @@ static int read_common_data(struct udevice *tpm)
        if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) ||
            size < NV_COMMON_DATA_MIN_SIZE)
                return 1;
-       err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX,
-                               buf, min(sizeof(buf), size));
+       err = tpm1_nv_read_value(tpm, NV_COMMON_DATA_INDEX, buf,
+                                min(sizeof(buf), size));
        if (err) {
                printf("tpm_nv_read_value() failed: %u\n", err);
                return 1;
@@ -508,8 +508,8 @@ static struct h_reg *access_hreg(struct udevice *tpm, uint8_t spec,
        if (mode & HREG_RD) {
                if (!result->valid) {
                        if (IS_PCR_HREG(spec)) {
-                               hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec),
-                                       result->digest, 20);
+                               hre_tpm_err = tpm1_pcr_read(tpm, HREG_IDX(spec),
+                                                           result->digest, 20);
                                result->valid = (hre_tpm_err == TPM_SUCCESS);
                        } else if (IS_FIX_HREG(spec)) {
                                switch (HREG_IDX(spec)) {
@@ -601,8 +601,8 @@ static int hre_op_loadkey(struct udevice *tpm, struct h_reg *src_reg,
                return -1;
        if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle))
                return -1;
-       hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size,
-                                        src_reg->digest, &key_handle);
+       hre_tpm_err = tpm1_load_key2_oiap(tpm, parent_handle, key, key_size,
+                                         src_reg->digest, &key_handle);
        if (hre_tpm_err) {
                hre_err = HRE_E_TPM_FAILURE;
                return -1;
@@ -718,8 +718,8 @@ do_bin_func:
        }
 
        if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
-               hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec),
-                                        dst_reg->digest, dst_reg->digest);
+               hre_tpm_err = tpm1_extend(tpm, HREG_IDX(dst_spec),
+                                         dst_reg->digest, dst_reg->digest);
                if (hre_tpm_err) {
                        hre_err = HRE_E_TPM_FAILURE;
                        return NULL;
@@ -964,10 +964,10 @@ static int first_stage_actions(struct udevice *tpm)
 
        puts("CCDM S1: start actions\n");
 #ifndef CCDM_SECOND_STAGE
-       if (tpm_continue_self_test(tpm))
+       if (tpm1_continue_self_test(tpm))
                goto failure;
 #else
-       tpm_continue_self_test(tpm);
+       tpm1_continue_self_test(tpm);
 #endif
        mdelay(37);
 
@@ -1003,7 +1003,7 @@ static int first_stage_init(void)
 
        puts("CCDM S1\n");
        ret = get_tpm(&tpm);
-       if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR))
+       if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR))
                return 1;
        ret = first_stage_actions(tpm);
 #ifndef CCDM_SECOND_STAGE
@@ -1061,7 +1061,7 @@ static int second_stage_init(void)
        ret = get_tpm(&tpm);
        if (ret || tpm_init(tpm))
                return 1;
-       err = tpm_startup(tpm, TPM_ST_CLEAR);
+       err = tpm1_startup(tpm, TPM_ST_CLEAR);
        if (err != TPM_INVALID_POSTINIT)
                did_first_stage_run = false;
 
index 2e6f905..52c80f7 100644 (file)
@@ -436,7 +436,7 @@ static int get_boardmem_size(struct spi_flash *spi)
        return 1024;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
index f9fb3f1..3f9235c 100644 (file)
@@ -3,9 +3,12 @@
  * Copyright 2019 Google LLC
  */
 
+#define LOG_CATEGORY   UCLASS_SYSINFO
+
 #include <common.h>
 #include <bloblist.h>
 #include <command.h>
+#include <cros_ec.h>
 #include <dm.h>
 #include <log.h>
 #include <sysinfo.h>
@@ -15,6 +18,7 @@
 #include <asm/intel_gnvs.h>
 #include <asm/intel_pinctrl.h>
 #include <dm/acpi.h>
+#include <linux/delay.h>
 #include "variant_gpio.h"
 
 struct cros_gpio_info {
@@ -29,10 +33,125 @@ int arch_misc_init(void)
        return 0;
 }
 
-/* This function is needed if CONFIG_CMDLINE is not enabled */
-int board_run_command(const char *cmdline)
+static int get_memconfig(struct udevice *dev)
 {
-       printf("No command line\n");
+       struct gpio_desc gpios[4];
+       int cfg;
+       int ret;
+
+       ret = gpio_request_list_by_name(dev, "memconfig-gpios", gpios,
+                                       ARRAY_SIZE(gpios),
+                                       GPIOD_IS_IN | GPIOD_PULL_UP);
+       if (ret < 0) {
+               log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
+               return ret;
+       }
+
+       /* Give the lines time to settle */
+       udelay(10);
+
+       ret = dm_gpio_get_values_as_int(gpios, ARRAY_SIZE(gpios));
+       if (ret < 0)
+               return log_msg_ret("get", ret);
+       cfg = ret;
+
+       ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
+       if (ret)
+               return log_msg_ret("free", ret);
+
+       return cfg;
+}
+
+/**
+ * get_skuconfig() - Get the SKU number either from pins or the EC
+ *
+ * Two options are supported:
+ *     skuconfig-gpios - two pins in the device tree (tried first)
+ *     EC              - reading from the EC (backup)
+ *
+ * @dev: sysinfo device to use
+ * @return SKU ID, or -ve error if not found
+ */
+static int get_skuconfig(struct udevice *dev)
+{
+       struct gpio_desc gpios[2];
+       int cfg;
+       int ret;
+
+       ret = gpio_request_list_by_name(dev, "skuconfig-gpios", gpios,
+                                       ARRAY_SIZE(gpios),
+                                       GPIOD_IS_IN);
+       if (ret != ARRAY_SIZE(gpios)) {
+               struct udevice *cros_ec;
+
+               log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
+
+               /* Try the EC */
+               ret = uclass_first_device_err(UCLASS_CROS_EC, &cros_ec);
+               if (ret < 0) {
+                       log_err("Cannot find EC for SKU details\n");
+                       return log_msg_ret("sku", ret);
+               }
+               ret = cros_ec_get_sku_id(cros_ec);
+               if (ret < 0) {
+                       log_err("Cannot read SKU details\n");
+                       return log_msg_ret("sku", ret);
+               }
+
+               return ret;
+       }
+
+       ret = dm_gpio_get_values_as_int_base3(gpios, ARRAY_SIZE(gpios));
+       if (ret < 0)
+               return log_msg_ret("get", ret);
+       cfg = ret;
+
+       ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
+       if (ret)
+               return log_msg_ret("free", ret);
+
+       return cfg;
+}
+
+static int coral_get_str(struct udevice *dev, int id, size_t size, char *val)
+{
+       int ret;
+
+       if (IS_ENABLED(CONFIG_SPL_BUILD))
+               return -ENOSYS;
+
+       switch (id) {
+       case SYSINFO_ID_SMBIOS_SYSTEM_VERSION:
+       case SYSINFO_ID_SMBIOS_BASEBOARD_VERSION: {
+               ret = get_skuconfig(dev);
+
+               if (ret < 0)
+                       return ret;
+               if (size < 15)
+                       return -ENOSPC;
+               sprintf(val, "rev%d", ret);
+               break;
+       }
+       case SYSINFO_ID_BOARD_MODEL: {
+               int mem_config, sku_config;
+               const char *model;
+
+               ret = get_memconfig(dev);
+               if (ret < 0)
+                       log_warning("Unable to read memconfig (err=%d)\n", ret);
+               mem_config = ret;
+               ret = get_skuconfig(dev);
+               if (ret < 0)
+                       log_warning("Unable to read skuconfig (err=%d)\n", ret);
+               sku_config = ret;
+               model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+               snprintf(val, size, "%s (memconfig %d, SKU %d)", model,
+                        mem_config, sku_config);
+               break;
+       }
+       default:
+               return -ENOENT;
+       }
 
        return 0;
 }
@@ -45,12 +164,15 @@ int chromeos_get_gpio(const struct udevice *dev, const char *prop,
        int ret;
 
        ret = gpio_request_by_name((struct udevice *)dev, prop, 0, &desc, 0);
-       if (ret == -ENOTBLK)
+       if (ret == -ENOTBLK) {
                info->gpio_num = CROS_GPIO_VIRTUAL;
-       else if (ret)
+               log_debug("GPIO '%s' is virtual\n", prop);
+       } else if (ret) {
                return log_msg_ret("gpio", ret);
-       else
+       } else {
                info->gpio_num = desc.offset;
+               dm_gpio_free((struct udevice *)dev, &desc);
+       }
        info->linux_name = dev_read_string(desc.dev, "linux-name");
        if (!info->linux_name)
                return log_msg_ret("linux-name", -ENOENT);
@@ -63,6 +185,8 @@ int chromeos_get_gpio(const struct udevice *dev, const char *prop,
        }
        info->flags = desc.flags & GPIOD_ACTIVE_LOW ? CROS_GPIO_ACTIVE_LOW :
                CROS_GPIO_ACTIVE_HIGH;
+       if (!ret)
+               dm_gpio_free(desc.dev, &desc);
 
        return 0;
 }
@@ -81,11 +205,11 @@ static int chromeos_acpi_gpio_generate(const struct udevice *dev,
        ret = chromeos_get_gpio(dev, "write-protect-gpios", CROS_GPIO_WP,
                                &info[1]);
        if (ret)
-               return log_msg_ret("rec", ret);
+               return log_msg_ret("wp", ret);
        ret = chromeos_get_gpio(dev, "phase-enforce-gpios", CROS_GPIO_PE,
                                &info[2]);
        if (ret)
-               return log_msg_ret("rec", ret);
+               return log_msg_ret("phase", ret);
        acpigen_write_scope(ctx, "\\");
        acpigen_write_name(ctx, "OIPG");
        acpigen_write_package(ctx, count);
@@ -145,6 +269,7 @@ struct acpi_ops coral_acpi_ops = {
 };
 
 struct sysinfo_ops coral_sysinfo_ops = {
+       .get_str        = coral_get_str,
 };
 
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
index f516d88..403e241 100644 (file)
 /* Determine if board is in final shipping mode. */
 #define GPIO_SHIP_MODE GPIO_10
 
-/*  Memory SKU GPIOs. */
-#define MEM_CONFIG3    GPIO_45
-#define MEM_CONFIG2    GPIO_38
-#define MEM_CONFIG1    GPIO_102
-#define MEM_CONFIG0    GPIO_101
-
 /* DMIC_CONFIG_PIN: High for 1-DMIC and low for 4-DMIC's */
 #define DMIC_CONFIG_PIN        GPIO_17
 
index a790d45..906bd9b 100644 (file)
@@ -128,7 +128,7 @@ static int is_highbank(void)
        return (midr & 0xfff0) == 0xc090;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        writel(HB_PWR_HARD_RESET, HB_SREG_A9_PWR_REQ);
        if (is_highbank())
index afe324c..c9a2d60 100644 (file)
@@ -486,7 +486,7 @@ int dram_init_banksize(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        writel(0x48698284, &ao_sc->stat0);
        wfi();
index 62073aa..f41fabb 100644 (file)
@@ -185,7 +185,7 @@ int board_init(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        psci_system_reset();
 }
index fda9a34..6cc79d9 100644 (file)
@@ -60,7 +60,7 @@ int checkboard(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        psci_system_reset();
 }
diff --git a/board/hoperun/hihope-rzg2/Kconfig b/board/hoperun/hihope-rzg2/Kconfig
new file mode 100644 (file)
index 0000000..ee422ba
--- /dev/null
@@ -0,0 +1,15 @@
+if TARGET_HIHOPE_RZG2
+
+config SYS_SOC
+       default "rmobile"
+
+config SYS_BOARD
+       default "hihope-rzg2"
+
+config SYS_VENDOR
+       default "hoperun"
+
+config SYS_CONFIG_NAME
+       default "hihope-rzg2"
+
+endif
diff --git a/board/hoperun/hihope-rzg2/MAINTAINERS b/board/hoperun/hihope-rzg2/MAINTAINERS
new file mode 100644 (file)
index 0000000..e3702fd
--- /dev/null
@@ -0,0 +1,6 @@
+HIHOPE_RZG2 BOARD
+M:     Biju Das <biju.das.jz@bp.renesas.com>
+S:     Maintained
+F:     board/hoperun/hihope-rzg2/
+F:     include/configs/hihope-rzg2.h
+F:     configs/hihope_rzg2_defconfig
diff --git a/board/hoperun/hihope-rzg2/Makefile b/board/hoperun/hihope-rzg2/Makefile
new file mode 100644 (file)
index 0000000..e989e7a
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# board/hoperun/hihope-rzg2/Makefile
+#
+# Copyright (C) 2021 Renesas Electronics Corporation
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y  := hihope-rzg2.o ../../renesas/rcar-common/common.o
diff --git a/board/hoperun/hihope-rzg2/hihope-rzg2.c b/board/hoperun/hihope-rzg2/hihope-rzg2.c
new file mode 100644 (file)
index 0000000..c1bfdcb
--- /dev/null
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * board/hoperun/hihope-rzg2/hihope-rzg2.c
+ *     This file is HiHope RZ/G2[HMN] board support.
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ */
+
+#include <common.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/arch/rmobile.h>
+#include <asm/arch/rcar-mstp.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/libfdt.h>
+
+#define RST_BASE       0xE6160000
+#define RST_CA57RESCNT (RST_BASE + 0x40)
+#define RST_CA53RESCNT (RST_BASE + 0x44)
+#define RST_CA57_CODE  0xA5A5000F
+#define RST_CA53_CODE  0x5A5A000F
+
+DECLARE_GLOBAL_DATA_PTR;
+#define HSUSB_MSTP704          BIT(4)  /* HSUSB */
+
+/* HSUSB block registers */
+#define HSUSB_REG_LPSTS                        0xE6590102
+#define HSUSB_REG_LPSTS_SUSPM_NORMAL   BIT(14)
+#define HSUSB_REG_UGCTRL2              0xE6590184
+#define HSUSB_REG_UGCTRL2_USB0SEL_EHCI 0x10
+#define HSUSB_REG_UGCTRL2_RESERVED_3   0x1 /* bit[3:0] should be B'0001 */
+
+#define PRR_REGISTER (0xFFF00044)
+
+int board_init(void)
+{
+       u32 i;
+
+       /* address of boot parameters */
+       gd->bd->bi_boot_params = CONFIG_SYS_TEXT_BASE + 0x50000;
+
+       /* Configure the HSUSB block */
+       mstp_clrbits_le32(SMSTPCR7, SMSTPCR7, HSUSB_MSTP704);
+       /*
+        * We need to add a barrier instruction after HSUSB module stop release.
+        * This barrier instruction can be either reading back the same MSTP
+        * register or any other register in the same IP block. So like linux
+        * adding check for MSTPSR register, which indicates the clock has been
+        * started.
+        */
+       for (i = 1000; i > 0; --i) {
+               if (!(readl(MSTPSR7) & HSUSB_MSTP704))
+                       break;
+               cpu_relax();
+       }
+
+       /* Select EHCI/OHCI host module for USB2.0 ch0 */
+       writel(HSUSB_REG_UGCTRL2_USB0SEL_EHCI | HSUSB_REG_UGCTRL2_RESERVED_3,
+              HSUSB_REG_UGCTRL2);
+       /* low power status */
+       setbits_le16(HSUSB_REG_LPSTS, HSUSB_REG_LPSTS_SUSPM_NORMAL);
+
+       return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+       unsigned long midr, cputype;
+
+       asm volatile("mrs %0, midr_el1" : "=r" (midr));
+       cputype = (midr >> 4) & 0xfff;
+
+       if (cputype == 0xd03)
+               writel(RST_CA53_CODE, RST_CA53RESCNT);
+       else
+               writel(RST_CA57_CODE, RST_CA57RESCNT);
+}
+
+#if defined(CONFIG_MULTI_DTB_FIT)
+/* If the firmware passed a device tree, use it for board identification. */
+extern u64 rcar_atf_boot_args[];
+
+static bool is_hoperun_hihope_rzg2_board(const char *board_name)
+{
+       void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
+       bool ret = false;
+
+       if ((fdt_magic(atf_fdt_blob) == FDT_MAGIC) &&
+           (fdt_node_check_compatible(atf_fdt_blob, 0, board_name) == 0))
+               ret = true;
+
+       return ret;
+}
+
+int board_fit_config_name_match(const char *name)
+{
+       if (is_hoperun_hihope_rzg2_board("hoperun,hihope-rzg2m") &&
+           !strcmp(name, "r8a774a1-hihope-rzg2m-u-boot"))
+               return 0;
+
+       if (is_hoperun_hihope_rzg2_board("hoperun,hihope-rzg2n") &&
+           !strcmp(name, "r8a774b1-hihope-rzg2n-u-boot"))
+               return 0;
+
+       if (is_hoperun_hihope_rzg2_board("hoperun,hihope-rzg2h") &&
+           !strcmp(name, "r8a774e1-hihope-rzg2h-u-boot"))
+               return 0;
+
+       return -1;
+}
+#endif
index 02c87a0..dccf469 100644 (file)
@@ -366,7 +366,7 @@ int board_eth_init(struct bd_info *bis)
        return ret;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        /* Soft Power On Reset */
        writel((1 << 31), RESCNT2);
index b8658c8..39f70f5 100644 (file)
@@ -376,7 +376,7 @@ void board_boot_order(u32 *spl_boot_list)
 #endif
 }
 
-void reset_cpu(ulong addr) {}
+void reset_cpu(void) {}
 
 #ifdef CONFIG_SPL_LOAD_FIT
 int board_fit_config_name_match(const char *name)
diff --git a/board/mediatek/mt8183/Kconfig b/board/mediatek/mt8183/Kconfig
new file mode 100644 (file)
index 0000000..b75c3b8
--- /dev/null
@@ -0,0 +1,13 @@
+if TARGET_MT8183
+
+config SYS_BOARD
+       default "mt8183"
+
+config SYS_CONFIG_NAME
+       default "mt8183"
+
+config MTK_BROM_HEADER_INFO
+       string
+       default "media=emmc"
+
+endif
diff --git a/board/mediatek/mt8183/MAINTAINERS b/board/mediatek/mt8183/MAINTAINERS
new file mode 100644 (file)
index 0000000..a49995e
--- /dev/null
@@ -0,0 +1,6 @@
+MT8183 Pumpkin
+M:     Fabien Parent <fparent@baylibre.com>
+S:     Maintained
+F:     board/mediatek/mt8183
+F:     include/configs/mt8183.h
+F:     configs/mt8183_pumpkin_defconfig
diff --git a/board/mediatek/mt8183/Makefile b/board/mediatek/mt8183/Makefile
new file mode 100644 (file)
index 0000000..90b5b72
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier:     GPL-2.0
+
+obj-y += mt8183_pumpkin.o
diff --git a/board/mediatek/mt8183/mt8183_pumpkin.c b/board/mediatek/mt8183/mt8183_pumpkin.c
new file mode 100644 (file)
index 0000000..db613eb
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 BayLibre SAS
+ * Author: Fabien Parent <fparent@baylibre.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <net.h>
+
+int board_init(void)
+{
+       struct udevice *dev;
+       int ret;
+
+       if (CONFIG_IS_ENABLED(USB_GADGET)) {
+               ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, 0, &dev);
+               if (ret) {
+                       pr_err("%s: Cannot find USB device\n", __func__);
+                       return ret;
+               }
+       }
+
+       if (CONFIG_IS_ENABLED(USB_ETHER))
+               usb_ether_init();
+
+       return 0;
+}
similarity index 76%
rename from board/mediatek/pumpkin/Kconfig
rename to board/mediatek/mt8516/Kconfig
index 34b1c0b..a87d387 100644 (file)
@@ -1,10 +1,10 @@
 if TARGET_MT8516
 
 config SYS_BOARD
-       default "pumpkin"
+       default "mt8516"
 
 config SYS_CONFIG_NAME
-       default "pumpkin"
+       default "mt8516"
 
 config MTK_BROM_HEADER_INFO
        string
diff --git a/board/mediatek/mt8516/MAINTAINERS b/board/mediatek/mt8516/MAINTAINERS
new file mode 100644 (file)
index 0000000..2f0d8f6
--- /dev/null
@@ -0,0 +1,6 @@
+MT8516 Pumpkin
+M:     Fabien Parent <fparent@baylibre.com>
+S:     Maintained
+F:     board/mediatek/mt8516
+F:     include/configs/mt8516.h
+F:     configs/mt8516_pumpkin_defconfig
diff --git a/board/mediatek/mt8516/Makefile b/board/mediatek/mt8516/Makefile
new file mode 100644 (file)
index 0000000..1d4815d
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier:     GPL-2.0
+
+obj-y += mt8516_pumpkin.o
similarity index 85%
rename from board/mediatek/pumpkin/pumpkin.c
rename to board/mediatek/mt8516/mt8516_pumpkin.c
index 37daf1c..42f3863 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <net.h>
 
 int board_init(void)
 {
@@ -24,5 +25,8 @@ int board_late_init(void)
                }
        }
 
+       if (CONFIG_IS_ENABLED(USB_ETHER))
+               usb_ether_init();
+
        return 0;
 }
diff --git a/board/mediatek/pumpkin/MAINTAINERS b/board/mediatek/pumpkin/MAINTAINERS
deleted file mode 100644 (file)
index 16beadc..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-Pumpkin
-M:     Fabien Parent <fparent@baylibre.com>
-S:     Maintained
-F:     board/mediatek/pumpkin
-F:     include/configs/pumpkin.h
-F:     configs/pumpkin_defconfig
index 8a82a45..ef13f7c 100644 (file)
@@ -42,7 +42,7 @@ int board_init(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct arm_smccc_res res;
 
index 646013c..0d282de 100644 (file)
@@ -203,7 +203,7 @@ int ft_board_setup(void *blob, struct bd_info *bd)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        psci_system_reset();
 }
index 877e34c..4ccb1a0 100644 (file)
@@ -127,7 +127,7 @@ int board_init(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        psci_system_reset();
 }
index 854c476..3b60afc 100644 (file)
@@ -111,7 +111,7 @@ int board_phy_config(struct phy_device *phydev)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct udevice *dev;
        const u8 pmic_bus = 7;
index 2de236f..cdaa04e 100644 (file)
@@ -408,6 +408,6 @@ void board_boot_order(u32 *spl_boot_list)
        spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index 9671382..a365269 100644 (file)
@@ -360,7 +360,7 @@ int dram_init_banksize(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct udevice *dev;
        const u8 pmic_bus = 6;
index 4454061..e930de3 100644 (file)
@@ -34,7 +34,7 @@ int board_init(void)
 #define RST_CA57_CODE  0xA5A5000F
 #define RST_CA53_CODE  0x5A5A000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        unsigned long midr, cputype;
 
index ffd52eb..1d76f95 100644 (file)
@@ -75,7 +75,7 @@ int board_init(void)
 #define RST_CA53RESCNT (RST_BASE + 0x44)
 #define RST_CA53_CODE  0x5A5A000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        writel(RST_CA53_CODE, RST_CA53RESCNT);
 }
index f9e553f..bb32e3d 100644 (file)
@@ -78,7 +78,7 @@ int board_init(void)
 #define RST_CA57_CODE  0xA5A5000F
 #define RST_CA53_CODE  0x5A5A000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        unsigned long midr, cputype;
 
index 82cd2a5..9d4af8d 100644 (file)
@@ -42,7 +42,7 @@ int board_init(void)
 #define RST_CA53RESCNT (RST_BASE + 0x44)
 #define RST_CA53_CODE  0x5A5A000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        writel(RST_CA53_CODE, RST_CA53RESCNT);
 }
index 56cdc73..51768c3 100644 (file)
@@ -117,7 +117,7 @@ int board_phy_config(struct phy_device *phydev)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct udevice *dev;
        const u8 pmic_bus = 6;
index 624ba5d..c0bf720 100644 (file)
@@ -405,6 +405,6 @@ void board_boot_order(u32 *spl_boot_list)
        spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index ac989eb..199ec4a 100644 (file)
@@ -40,7 +40,7 @@ int dram_init_banksize(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        /* Dummy read (must read WRCSR:WOVF at least once before clearing) */
        readb(RZA1_WDT_BASE + WRCSR);
index b0a66ea..7e94bd8 100644 (file)
@@ -119,7 +119,7 @@ int board_phy_config(struct phy_device *phydev)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct udevice *dev;
        const u8 pmic_bus = 6;
index 449bbfa..b377f70 100644 (file)
@@ -407,6 +407,6 @@ void board_boot_order(u32 *spl_boot_list)
        spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index add4eef..87c5e01 100644 (file)
@@ -128,7 +128,7 @@ int board_phy_config(struct phy_device *phydev)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct udevice *dev;
        const u8 pmic_bus = 2;
index 1ca857c..d3d397e 100644 (file)
@@ -393,6 +393,6 @@ void board_boot_order(u32 *spl_boot_list)
        spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index b3e4c08..b0f8505 100644 (file)
@@ -117,7 +117,7 @@ int board_phy_config(struct phy_device *phydev)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct udevice *dev;
        const u8 pmic_bus = 6;
index f10c6cf..8595770 100644 (file)
@@ -488,6 +488,6 @@ void board_boot_order(u32 *spl_boot_list)
        spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index fd6e505..b02a946 100644 (file)
@@ -55,6 +55,6 @@ void s_init(void)
 {
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index 08ed725..071076a 100644 (file)
@@ -76,7 +76,7 @@ int board_init(void)
 #define RST_RSTOUTCR   (RST_BASE + 0x58)
 #define RST_CODE       0xA5A5000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 #if defined(CONFIG_SYS_I2C) && defined(CONFIG_SYS_I2C_SH)
        i2c_reg_write(CONFIG_SYS_I2C_POWERIC_ADDR, 0x20, 0x80);
index 05af5f4..4558070 100644 (file)
@@ -112,7 +112,7 @@ int board_phy_config(struct phy_device *phydev)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct udevice *dev;
        const u8 pmic_bus = 1;
index f10f84a..afb9f85 100644 (file)
@@ -422,6 +422,6 @@ void board_boot_order(u32 *spl_boot_list)
        spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index b56ed17..ac8048c 100644 (file)
@@ -163,7 +163,7 @@ U_BOOT_CMD(
        "cpld write addr val\n"
 );
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        cpld_write(CPLD_ADDR_RESET, 1);
 }
index 57c1fab..c37c055 100644 (file)
@@ -474,6 +474,6 @@ void board_boot_order(u32 *spl_boot_list)
        spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index 433be48..d32561c 100644 (file)
@@ -20,6 +20,13 @@ F:   board/sandbox/
 F:     include/configs/sandbox_spl.h
 F:     configs/sandbox_spl_defconfig
 
+SANDBOX NOINST BOARD
+M:     Simon Glass <sjg@chromium.org>
+S:     Maintained
+F:     board/sandbox/
+F:     include/configs/sandbox_spl.h
+F:     configs/sandbox_noinst_defconfig
+
 SANDBOX FLAT TREE BOARD
 M:     Simon Glass <sjg@chromium.org>
 S:     Maintained
index 3c63d45..902b99e 100644 (file)
@@ -48,6 +48,7 @@ unsigned long timer_read_counter(void)
 static enum env_location env_locations[] = {
        ENVL_NOWHERE,
        ENVL_EXT4,
+       ENVL_FAT,
 };
 
 enum env_location env_get_location(enum env_operation op, int prio)
index 56973a1..dcbab8e 100644 (file)
@@ -232,7 +232,7 @@ static int setup_fec(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/silinux/ek874/Kconfig b/board/silinux/ek874/Kconfig
new file mode 100644 (file)
index 0000000..60b390a
--- /dev/null
@@ -0,0 +1,15 @@
+if TARGET_SILINUX_EK874
+
+config SYS_SOC
+       default "rmobile"
+
+config SYS_BOARD
+       default "ek874"
+
+config SYS_VENDOR
+       default "silinux"
+
+config SYS_CONFIG_NAME
+       default "silinux-ek874"
+
+endif
diff --git a/board/silinux/ek874/MAINTAINERS b/board/silinux/ek874/MAINTAINERS
new file mode 100644 (file)
index 0000000..57a71b8
--- /dev/null
@@ -0,0 +1,6 @@
+SILINUX_EK874 BOARD
+M:     Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+S:     Maintained
+F:     board/silinux/ek874/
+F:     include/configs/silinux-ek874.h
+F:     configs/silinux_ek874_defconfig
diff --git a/board/silinux/ek874/Makefile b/board/silinux/ek874/Makefile
new file mode 100644 (file)
index 0000000..4c8f092
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# board/silinux/ek874/Makefile
+#
+# Copyright (C) 2021 Renesas Electronics Corporation
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+ifdef CONFIG_SPL_BUILD
+obj-y  := ../../renesas/rcar-common/gen3-spl.o
+else
+obj-y  := ek874.o ../../renesas/rcar-common/common.o
+endif
diff --git a/board/silinux/ek874/ek874.c b/board/silinux/ek874/ek874.c
new file mode 100644 (file)
index 0000000..5a219cd
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * board/silinux/ek874/ek874.c
+ *     This file is ek874 board support.
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ */
+
+#include <common.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+
+#define RST_BASE       0xE6160000
+#define RST_CA53RESCNT (RST_BASE + 0x44)
+#define RST_CA53_CODE  0x5A5A000F
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+       /* address of boot parameters */
+       gd->bd->bi_boot_params = CONFIG_SYS_TEXT_BASE + 0x50000;
+
+       return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+       writel(RST_CA53_CODE, RST_CA53RESCNT);
+}
index 997120e..a3cee23 100644 (file)
@@ -98,7 +98,7 @@ int board_early_init_r(void)
 /* Bits in CREG_BOOT register */
 #define CREG_BOOT_WP_BIT       BIT(8)
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        writel(1, CREG_IP_SW_RESET);
        while (1)
index c605136..650958f 100644 (file)
@@ -151,7 +151,7 @@ int mach_cpu_init(void)
 
 #define IOTDK_RESET_SEQ                0x55AA6699
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        writel(IOTDK_RESET_SEQ, RESET_REG);
 }
index 3807779..251f5a1 100644 (file)
@@ -147,7 +147,7 @@ void board_init_f(ulong dummy)
        board_init_r(NULL, 0);
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
index bed0f21..df5f058 100644 (file)
@@ -127,7 +127,7 @@ void board_init_f(ulong dummy)
        board_init_r(NULL, 0);
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
index 76faa6e..04877fc 100644 (file)
@@ -117,7 +117,7 @@ int board_init(void)
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        /* TODO */
 }
index b6f3bdd..ac3bac6 100644 (file)
@@ -127,7 +127,7 @@ int board_init(void)
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        /* TODO */
 }
index 0c857b5..74060da 100644 (file)
@@ -1139,7 +1139,7 @@ int board_fit_config_name_match(const char *name)
 }
 #endif
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
index 562199a..169d4d0 100644 (file)
@@ -129,7 +129,7 @@ int board_init(void)
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        /* TODO */
 }
index 74d59e5..c0e7754 100644 (file)
@@ -1081,7 +1081,7 @@ void board_init_f(ulong dummy)
        board_init_r(NULL, 0);
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
index 8f7ef99..301b07d 100644 (file)
@@ -237,7 +237,7 @@ int power_init_board(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct udevice *dev;
 
index 7d0d782..21363d8 100644 (file)
@@ -171,7 +171,7 @@ int dram_init_banksize(void)
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
index c644fe8..e2f9d13 100644 (file)
@@ -242,6 +242,6 @@ int dram_init(void)
        return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
index d3eb713..2d93b20 100644 (file)
@@ -8,77 +8,88 @@
 
 static unsigned long psu_pll_init_data(void)
 {
-       psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4E2C62U);
-       psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00013C00U);
+       psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4B0C62U);
+       psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00014600U);
        psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000008U);
        psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000001U);
        psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000000U);
        mask_poll(0xFF5E0040, 0x00000002U);
        psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000000U);
-       psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000200U);
-       psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E4B0C82U);
-       psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00015A00U);
+       psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFF5E0038, 0x8000FFFFU, 0x00000000U);
+       psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012300U);
+       psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E672C6CU);
+       psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00002D00U);
        psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000008U);
        psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000001U);
        psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000000U);
        mask_poll(0xFF5E0040, 0x00000001U);
        psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000000U);
        psu_mask_write(0xFF5E0044, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFF5E0028, 0x8000FFFFU, 0x00000000U);
        psu_mask_write(0xFD1A0024, 0xFE7FEDEFU, 0x7E4B0C62U);
-       psu_mask_write(0xFD1A0020, 0x00717F00U, 0x00014200U);
+       psu_mask_write(0xFD1A0020, 0x00717F00U, 0x00014800U);
        psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000008U);
        psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000001U);
        psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000000U);
        mask_poll(0xFD1A0044, 0x00000001U);
        psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000000U);
        psu_mask_write(0xFD1A0048, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFD1A0028, 0x8000FFFFU, 0x00000000U);
        psu_mask_write(0xFD1A0030, 0xFE7FEDEFU, 0x7E4B0C62U);
-       psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00014800U);
+       psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00014000U);
        psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000008U);
        psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000001U);
        psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000000U);
        mask_poll(0xFD1A0044, 0x00000002U);
        psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000000U);
        psu_mask_write(0xFD1A004C, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFD1A0034, 0x8000FFFFU, 0x00000000U);
        psu_mask_write(0xFD1A003C, 0xFE7FEDEFU, 0x7E4B0C62U);
-       psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00014000U);
+       psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00014700U);
        psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000008U);
        psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000001U);
        psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000000U);
        mask_poll(0xFD1A0044, 0x00000004U);
        psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000000U);
-       psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000200U);
+       psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFD1A0040, 0x8000FFFFU, 0x00000000U);
 
        return 1;
 }
 
 static unsigned long psu_clock_init_data(void)
 {
+       psu_mask_write(0xFF5E0054, 0x063F3F07U, 0x06010C00U);
+       psu_mask_write(0xFF180308, 0x00000060U, 0x00000060U);
+       psu_mask_write(0xFF5E0100, 0x013F3F07U, 0x01010600U);
+       psu_mask_write(0xFF5E0060, 0x023F3F07U, 0x02010600U);
+       psu_mask_write(0xFF5E004C, 0x023F3F07U, 0x020F0500U);
        psu_mask_write(0xFF5E0068, 0x013F3F07U, 0x01010C00U);
-       psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010502U);
+       psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010800U);
        psu_mask_write(0xFF18030C, 0x00020000U, 0x00000000U);
        psu_mask_write(0xFF5E0074, 0x013F3F07U, 0x01010F00U);
        psu_mask_write(0xFF5E0120, 0x013F3F07U, 0x01010F00U);
        psu_mask_write(0xFF5E0090, 0x01003F07U, 0x01000302U);
-       psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000400U);
-       psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000900U);
+       psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000602U);
+       psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000800U);
        psu_mask_write(0xFF5E00A8, 0x01003F07U, 0x01000302U);
        psu_mask_write(0xFF5E00AC, 0x01003F07U, 0x01000F02U);
        psu_mask_write(0xFF5E00B0, 0x01003F07U, 0x01000602U);
        psu_mask_write(0xFF5E00B8, 0x01003F07U, 0x01000302U);
-       psu_mask_write(0xFF5E00C0, 0x013F3F07U, 0x01010A02U);
-       psu_mask_write(0xFF5E00C4, 0x013F3F07U, 0x01010402U);
-       psu_mask_write(0xFF5E00C8, 0x013F3F07U, 0x01010802U);
+       psu_mask_write(0xFF5E00C0, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E00C4, 0x013F3F07U, 0x01010400U);
+       psu_mask_write(0xFF5E00C8, 0x013F3F07U, 0x01010C00U);
+       psu_mask_write(0xFF5E00CC, 0x013F3F07U, 0x01010400U);
        psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01011D02U);
        psu_mask_write(0xFF5E0104, 0x00000007U, 0x00000000U);
-       psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000104U);
+       psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000F00U);
        psu_mask_write(0xFD1A0060, 0x03003F07U, 0x03000100U);
        psu_mask_write(0xFD1A0068, 0x01003F07U, 0x01000200U);
-       psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000600U);
-       psu_mask_write(0xFD1A0084, 0x07003F07U, 0x07000203U);
-       psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000203U);
-       psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000203U);
-       psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000202U);
+       psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000200U);
+       psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000203U);
        psu_mask_write(0xFD1A00C4, 0x01003F07U, 0x01000502U);
        psu_mask_write(0xFD1A00F8, 0x00003F07U, 0x00000200U);
        psu_mask_write(0xFF180380, 0x000000FFU, 0x00000000U);
@@ -94,50 +105,50 @@ static unsigned long psu_ddr_init_data(void)
        psu_mask_write(0xFD1A0108, 0x00000008U, 0x00000008U);
        psu_mask_write(0xFD070000, 0xE30FBE3DU, 0x81040001U);
        psu_mask_write(0xFD070010, 0x8000F03FU, 0x00000030U);
-       psu_mask_write(0xFD070020, 0x000003F3U, 0x00000100U);
+       psu_mask_write(0xFD070020, 0x000003F3U, 0x00000200U);
        psu_mask_write(0xFD070024, 0xFFFFFFFFU, 0x00800000U);
        psu_mask_write(0xFD070030, 0x0000007FU, 0x00000000U);
-       psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00403210U);
+       psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00408410U);
        psu_mask_write(0xFD070050, 0x00F1F1F4U, 0x00210000U);
        psu_mask_write(0xFD070054, 0x0FFF0FFFU, 0x00000000U);
        psu_mask_write(0xFD070060, 0x00000073U, 0x00000001U);
-       psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x00308034U);
+       psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x0081808BU);
        psu_mask_write(0xFD070070, 0x00000017U, 0x00000010U);
        psu_mask_write(0xFD070074, 0x00000003U, 0x00000000U);
        psu_mask_write(0xFD0700C4, 0x3F000391U, 0x10000200U);
        psu_mask_write(0xFD0700C8, 0x01FF1F3FU, 0x0030051FU);
-       psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00020063U);
-       psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x00290000U);
-       psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00000E05U);
-       psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x05200004U);
-       psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00020106U);
+       psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x006A0000U);
+       psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00002305U);
+       psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x01240004U);
+       psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00280000U);
        psu_mask_write(0xFD0700E4, 0x00FF03FFU, 0x00110004U);
        psu_mask_write(0xFD0700E8, 0xFFFFFFFFU, 0x00000000U);
        psu_mask_write(0xFD0700EC, 0xFFFF0000U, 0x00000000U);
        psu_mask_write(0xFD0700F0, 0x0000003FU, 0x00000010U);
        psu_mask_write(0xFD0700F4, 0x00000FFFU, 0x0000066FU);
-       psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x07080D07U);
-       psu_mask_write(0xFD070104, 0x001F1F7FU, 0x0005020BU);
-       psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x03030607U);
-       psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x00502006U);
-       psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x13020206U);
-       psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x03030202U);
-       psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010003U);
-       psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000303U);
-       psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x02020909U);
+       psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x0F102412U);
+       psu_mask_write(0xFD070104, 0x001F1F7FU, 0x000D041AU);
+       psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x0507070BU);
+       psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x00502008U);
+       psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x07020408U);
+       psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x06060403U);
+       psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010004U);
+       psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000606U);
+       psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x03030909U);
        psu_mask_write(0xFD070124, 0x40070F3FU, 0x0004040DU);
        psu_mask_write(0xFD07012C, 0x7F1F031FU, 0x440C011CU);
        psu_mask_write(0xFD070130, 0x00030F1FU, 0x00020608U);
-       psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x80800020U);
-       psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x02009896U);
-       psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x04828202U);
+       psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x80AB002BU);
+       psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x020196E6U);
+       psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x048A8207U);
        psu_mask_write(0xFD070194, 0xF31F0F0FU, 0x00020304U);
        psu_mask_write(0xFD070198, 0x0FF1F1F1U, 0x07000101U);
        psu_mask_write(0xFD07019C, 0x000000F1U, 0x00000021U);
        psu_mask_write(0xFD0701A0, 0xC3FF03FFU, 0x00400003U);
        psu_mask_write(0xFD0701A4, 0x00FF00FFU, 0x00C800FFU);
        psu_mask_write(0xFD0701B0, 0x00000007U, 0x00000000U);
-       psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000000U);
+       psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000805U);
        psu_mask_write(0xFD0701C0, 0x00000007U, 0x00000000U);
        psu_mask_write(0xFD070200, 0x0000001FU, 0x0000001FU);
        psu_mask_write(0xFD070204, 0x001F1F1FU, 0x00080808U);
@@ -151,7 +162,7 @@ static unsigned long psu_ddr_init_data(void)
        psu_mask_write(0xFD070224, 0x0F0F0F0FU, 0x07070707U);
        psu_mask_write(0xFD070228, 0x0F0F0F0FU, 0x07070707U);
        psu_mask_write(0xFD07022C, 0x0000000FU, 0x00000007U);
-       psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x06000604U);
+       psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x06000610U);
        psu_mask_write(0xFD070244, 0x00003333U, 0x00000001U);
        psu_mask_write(0xFD070250, 0x7FFF3F07U, 0x01002001U);
        psu_mask_write(0xFD070264, 0xFF00FFFFU, 0x08000040U);
@@ -209,30 +220,30 @@ static unsigned long psu_ddr_init_data(void)
        psu_mask_write(0xFD072190, 0x1FBFBF3FU, 0x07828002U);
        psu_mask_write(0xFD1A0108, 0x0000000CU, 0x00000000U);
        psu_mask_write(0xFD080010, 0xFFFFFFFFU, 0x07001E00U);
-       psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F05D90U);
+       psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F10010U);
        psu_mask_write(0xFD08001C, 0xFFFFFFFFU, 0x55AA5480U);
        psu_mask_write(0xFD080024, 0xFFFFFFFFU, 0x010100F4U);
-       psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x1900C810U);
-       psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0x4E200708U);
-       psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x06124000U);
-       psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04061U);
+       psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x42C21590U);
+       psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0xD05612C0U);
+       psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04161U);
        psu_mask_write(0xFD0800C0, 0xFFFFFFFFU, 0x00000000U);
-       psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000DAU);
+       psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000E3U);
        psu_mask_write(0xFD080100, 0xFFFFFFFFU, 0x0800040BU);
-       psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x040E0A04U);
-       psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x28100004U);
+       psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x08240E08U);
+       psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x28200404U);
        psu_mask_write(0xFD080118, 0xFFFFFFFFU, 0x000F0200U);
        psu_mask_write(0xFD08011C, 0xFFFFFFFFU, 0x82000800U);
-       psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x00682B0AU);
-       psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00152504U);
-       psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000506U);
+       psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x01162B1AU);
+       psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00330E08U);
+       psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000A0EU);
        psu_mask_write(0xFD080140, 0xFFFFFFFFU, 0x08400020U);
        psu_mask_write(0xFD080144, 0xFFFFFFFFU, 0x00000C80U);
        psu_mask_write(0xFD080150, 0xFFFFFFFFU, 0x00000000U);
        psu_mask_write(0xFD080154, 0xFFFFFFFFU, 0x00000000U);
-       psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000520U);
+       psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000124U);
        psu_mask_write(0xFD080184, 0xFFFFFFFFU, 0x00000004U);
-       psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000028U);
        psu_mask_write(0xFD08018C, 0xFFFFFFFFU, 0x00000000U);
        psu_mask_write(0xFD080190, 0xFFFFFFFFU, 0x00000000U);
        psu_mask_write(0xFD080194, 0xFFFFFFFFU, 0x00000000U);
@@ -261,7 +272,7 @@ static unsigned long psu_ddr_init_data(void)
        psu_mask_write(0xFD08055C, 0xFFFFFFFFU, 0x00000000U);
        psu_mask_write(0xFD080560, 0xFFFFFFFFU, 0x00000000U);
        psu_mask_write(0xFD080564, 0xFFFFFFFFU, 0x00000000U);
-       psu_mask_write(0xFD080680, 0xFFFFFFFFU, 0x0088E858U);
+       psu_mask_write(0xFD080680, 0xFFFFFFFFU, 0x008AA858U);
        psu_mask_write(0xFD080684, 0xFFFFFFFFU, 0x000077BBU);
        psu_mask_write(0xFD080694, 0xFFFFFFFFU, 0x01E10210U);
        psu_mask_write(0xFD080698, 0xFFFFFFFFU, 0x01E10000U);
@@ -281,13 +292,13 @@ static unsigned long psu_ddr_init_data(void)
        psu_mask_write(0xFD080900, 0xFFFFFFFFU, 0x40800604U);
        psu_mask_write(0xFD080904, 0xFFFFFFFFU, 0x00007FFFU);
        psu_mask_write(0xFD08090C, 0xFFFFFFFFU, 0x3F000008U);
-       psu_mask_write(0xFD080910, 0xFFFFFFFFU, 0x0E00B00CU);
+       psu_mask_write(0xFD080910, 0xFFFFFFFFU, 0x0E00B004U);
        psu_mask_write(0xFD080914, 0xFFFFFFFFU, 0x09093030U);
        psu_mask_write(0xFD080918, 0xFFFFFFFFU, 0x09092B2BU);
        psu_mask_write(0xFD080A00, 0xFFFFFFFFU, 0x40800604U);
        psu_mask_write(0xFD080A04, 0xFFFFFFFFU, 0x00007FFFU);
        psu_mask_write(0xFD080A0C, 0xFFFFFFFFU, 0x3F000008U);
-       psu_mask_write(0xFD080A10, 0xFFFFFFFFU, 0x0E00B00CU);
+       psu_mask_write(0xFD080A10, 0xFFFFFFFFU, 0x0E00B004U);
        psu_mask_write(0xFD080A14, 0xFFFFFFFFU, 0x09093030U);
        psu_mask_write(0xFD080A18, 0xFFFFFFFFU, 0x09092B2BU);
        psu_mask_write(0xFD080B00, 0xFFFFFFFFU, 0x40800604U);
@@ -318,7 +329,7 @@ static unsigned long psu_ddr_init_data(void)
        psu_mask_write(0xFD080E10, 0xFFFFFFFFU, 0x0E00B00CU);
        psu_mask_write(0xFD080E14, 0xFFFFFFFFU, 0x09093030U);
        psu_mask_write(0xFD080E18, 0xFFFFFFFFU, 0x09092B2BU);
-       psu_mask_write(0xFD080F00, 0xFFFFFFFFU, 0x40803660U);
+       psu_mask_write(0xFD080F00, 0xFFFFFFFFU, 0x80803660U);
        psu_mask_write(0xFD080F04, 0xFFFFFFFFU, 0x55556000U);
        psu_mask_write(0xFD080F08, 0xFFFFFFFFU, 0xAAAAAAAAU);
        psu_mask_write(0xFD080F0C, 0xFFFFFFFFU, 0x0029A4A4U);
@@ -326,36 +337,55 @@ static unsigned long psu_ddr_init_data(void)
        psu_mask_write(0xFD080F14, 0xFFFFFFFFU, 0x09093030U);
        psu_mask_write(0xFD080F18, 0xFFFFFFFFU, 0x09092B2BU);
        psu_mask_write(0xFD081400, 0xFFFFFFFFU, 0x2A019FFEU);
-       psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x06124000U);
+       psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x01100000U);
        psu_mask_write(0xFD08141C, 0xFFFFFFFFU, 0x01264300U);
        psu_mask_write(0xFD08142C, 0xFFFFFFFFU, 0x00041800U);
        psu_mask_write(0xFD081430, 0xFFFFFFFFU, 0x70000000U);
        psu_mask_write(0xFD081440, 0xFFFFFFFFU, 0x2A019FFEU);
-       psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x06124000U);
+       psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x01100000U);
        psu_mask_write(0xFD08145C, 0xFFFFFFFFU, 0x01264300U);
        psu_mask_write(0xFD08146C, 0xFFFFFFFFU, 0x00041800U);
        psu_mask_write(0xFD081470, 0xFFFFFFFFU, 0x70000000U);
        psu_mask_write(0xFD081480, 0xFFFFFFFFU, 0x2A019FFEU);
-       psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x06124000U);
+       psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x01100000U);
        psu_mask_write(0xFD08149C, 0xFFFFFFFFU, 0x01264300U);
        psu_mask_write(0xFD0814AC, 0xFFFFFFFFU, 0x00041800U);
        psu_mask_write(0xFD0814B0, 0xFFFFFFFFU, 0x70000000U);
        psu_mask_write(0xFD0814C0, 0xFFFFFFFFU, 0x2A019FFEU);
-       psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x06124000U);
+       psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x01100000U);
        psu_mask_write(0xFD0814DC, 0xFFFFFFFFU, 0x01264300U);
        psu_mask_write(0xFD0814EC, 0xFFFFFFFFU, 0x00041800U);
        psu_mask_write(0xFD0814F0, 0xFFFFFFFFU, 0x70000000U);
        psu_mask_write(0xFD081500, 0xFFFFFFFFU, 0x15019FFEU);
-       psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x06124000U);
-       psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x21100000U);
+       psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01266300U);
        psu_mask_write(0xFD08152C, 0xFFFFFFFFU, 0x00041800U);
-       psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70000000U);
-       psu_mask_write(0xFD0817C4, 0xFFFFFFFFU, 0x06124000U);
+       psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70400000U);
        psu_mask_write(0xFD0817DC, 0xFFFFFFFFU, 0x012643C4U);
 
        return 1;
 }
 
+static unsigned long psu_ddr_qos_init_data(void)
+{
+       psu_mask_write(0xFD360008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD36001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD370008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD37001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD380008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD38001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD390008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD39001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3A0008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3A001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3B0008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3B001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFF9B0008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFF9B001C, 0x0000000FU, 0x00000000U);
+
+       return 1;
+}
+
 static unsigned long psu_mio_init_data(void)
 {
        psu_mask_write(0xFF180000, 0x000000FEU, 0x00000002U);
@@ -378,8 +408,20 @@ static unsigned long psu_mio_init_data(void)
        psu_mask_write(0xFF1800C4, 0x000000FEU, 0x00000010U);
        psu_mask_write(0xFF1800C8, 0x000000FEU, 0x00000010U);
        psu_mask_write(0xFF1800CC, 0x000000FEU, 0x00000010U);
-       psu_mask_write(0xFF180204, 0x0000007FU, 0x00000002U);
-       psu_mask_write(0xFF180208, 0x000FFF8CU, 0x00003004U);
+       psu_mask_write(0xFF1800D0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800D4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800D8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800DC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800EC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800FC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF180204, 0x00000073U, 0x00000002U);
+       psu_mask_write(0xFF180208, 0xFFFFFF8CU, 0x00B03004U);
        psu_mask_write(0xFF180138, 0x03FFFFFFU, 0x03FFFFFFU);
        psu_mask_write(0xFF18013C, 0x03FFFFFFU, 0x03FFFFFFU);
        psu_mask_write(0xFF180140, 0x03FFFFFFU, 0x00000000U);
@@ -405,35 +447,49 @@ static unsigned long psu_mio_init_data(void)
 
 static unsigned long psu_peripherals_pre_init_data(void)
 {
-       psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x00012302U);
+       psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012302U);
+       psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000001U);
 
        return 1;
 }
 
 static unsigned long psu_peripherals_init_data(void)
 {
-       psu_mask_write(0xFD1A0100, 0x0000807CU, 0x00000000U);
+       psu_mask_write(0xFD1A0100, 0x00008044U, 0x00000000U);
        psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
        psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
+       psu_mask_write(0xFF5E0230, 0x00000002U, 0x00000000U);
        psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
        psu_mask_write(0xFF180390, 0x00000004U, 0x00000004U);
+       psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+       psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000140U);
+       psu_mask_write(0xFF9D0080, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF9D007C, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000000U);
        psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U);
        psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U);
-       psu_mask_write(0xFF180320, 0x33800000U, 0x02800000U);
+       psu_mask_write(0xFF180320, 0x33840000U, 0x02840000U);
        psu_mask_write(0xFF18031C, 0x7FFE0000U, 0x64500000U);
        psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U);
        psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U);
        psu_mask_write(0xFF5E0238, 0x00000200U, 0x00000000U);
        psu_mask_write(0xFF5E0238, 0x00008000U, 0x00000000U);
-       psu_mask_write(0xFF5E0238, 0x00000800U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00007800U, 0x00000000U);
        psu_mask_write(0xFF5E0238, 0x00000002U, 0x00000000U);
        psu_mask_write(0xFF5E0238, 0x00040000U, 0x00000000U);
        psu_mask_write(0xFF4B0024, 0x000000FFU, 0x000000FFU);
        psu_mask_write(0xFFCA5000, 0x00001FFFU, 0x00000000U);
        psu_mask_write(0xFD5C0060, 0x000F000FU, 0x00000000U);
        psu_mask_write(0xFFA60040, 0x80000000U, 0x80000000U);
-       psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x01FC9F08U);
+       psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x05F5E100U);
        psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+       mask_delay(1);
+       psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000002U);
+
+       mask_delay(5);
+       psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
 
        return 1;
 }
@@ -459,15 +515,21 @@ static unsigned long psu_ddr_phybringup_data(void)
 
                while ((Xil_In32(0xFD080030) & 0x1) != 1)
                        ;
-
-               pll_locked = (Xil_In32(0xFD080030) & 0x80000000) >> 31;
-               pll_locked &= (Xil_In32(0xFD0807E0) & 0x10000) >> 16;
+               pll_locked = (Xil_In32(0xFD080030) & 0x80000000)
+                   >> 31;
+               pll_locked &= (Xil_In32(0xFD0807E0) & 0x10000)
+                   >> 16;
                pll_locked &= (Xil_In32(0xFD0809E0) & 0x10000) >> 16;
-               pll_locked &= (Xil_In32(0xFD080BE0) & 0x10000) >> 16;
-               pll_locked &= (Xil_In32(0xFD080DE0) & 0x10000) >> 16;
+               pll_locked &= (Xil_In32(0xFD080BE0) & 0x10000)
+                   >> 16;
+               pll_locked &= (Xil_In32(0xFD080DE0) & 0x10000)
+                   >> 16;
                pll_retry--;
        }
-       Xil_Out32(0xFD0800C0, Xil_In32(0xFD0800C0) | (pll_retry << 16));
+       Xil_Out32(0xFD0800C4, Xil_In32(0xFD0800C4) | (pll_retry << 16));
+       if (!pll_locked)
+               return 0;
+
        Xil_Out32(0xFD080004U, 0x00040063U);
 
        while ((Xil_In32(0xFD080030U) & 0x0000000FU) != 0x0000000FU)
@@ -485,7 +547,10 @@ static unsigned long psu_ddr_phybringup_data(void)
        regval = Xil_In32(0xFD080030);
        while (regval != 0x80000FFF)
                regval = Xil_In32(0xFD080030);
-       Xil_Out32(0xFD070180U, 0x00800020U);
+       regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+       if (regval != 0)
+               return 0;
+       Xil_Out32(0xFD070180U, 0x00AB002BU);
        Xil_Out32(0xFD070060U, 0x00000000U);
        prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000000U);
 
@@ -511,6 +576,7 @@ int psu_init(void)
        init_peripheral();
 
        status &= psu_afi_config();
+       psu_ddr_qos_init_data();
 
        if (status == 0)
                return 1;
diff --git a/board/xilinx/zynqmp/zynqmp-zcu208-revA/psu_init_gpl.c b/board/xilinx/zynqmp/zynqmp-zcu208-revA/psu_init_gpl.c
new file mode 100644 (file)
index 0000000..f07e60a
--- /dev/null
@@ -0,0 +1,1880 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (c) Copyright 2015 Xilinx, Inc. All rights reserved.
+ */
+
+#include <asm/arch/psu_init_gpl.h>
+#include <xil_io.h>
+
+static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate,
+                          u32 lane2_protocol, u32 lane2_rate,
+                          u32 lane1_protocol, u32 lane1_rate,
+                          u32 lane0_protocol, u32 lane0_rate);
+
+static unsigned long psu_pll_init_data(void)
+{
+       psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4B0C82U);
+       psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00015A00U);
+       psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000000U);
+       mask_poll(0xFF5E0040, 0x00000002U);
+       psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012300U);
+       psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E4B0C82U);
+       psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00015A00U);
+       psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000000U);
+       mask_poll(0xFF5E0040, 0x00000001U);
+       psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFF5E0044, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFD1A0024, 0xFE7FEDEFU, 0x7E4B0C62U);
+       psu_mask_write(0xFD1A0020, 0x00717F00U, 0x00014800U);
+       psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000000U);
+       mask_poll(0xFD1A0044, 0x00000001U);
+       psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD1A0048, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFD1A0030, 0xFE7FEDEFU, 0x7E4B0C62U);
+       psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00013F00U);
+       psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000000U);
+       mask_poll(0xFD1A0044, 0x00000002U);
+       psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD1A004C, 0x00003F00U, 0x00000200U);
+       psu_mask_write(0xFD1A003C, 0xFE7FEDEFU, 0x7E4B0C82U);
+       psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00015A00U);
+       psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000000U);
+       mask_poll(0xFD1A0044, 0x00000004U);
+       psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000300U);
+
+       return 1;
+}
+
+static unsigned long psu_clock_init_data(void)
+{
+       psu_mask_write(0xFF5E005C, 0x063F3F07U, 0x06010C00U);
+       psu_mask_write(0xFF5E0100, 0x013F3F07U, 0x01010600U);
+       psu_mask_write(0xFF5E0060, 0x023F3F07U, 0x02010600U);
+       psu_mask_write(0xFF5E004C, 0x023F3F07U, 0x02031900U);
+       psu_mask_write(0xFF5E0068, 0x013F3F07U, 0x01010C00U);
+       psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010800U);
+       psu_mask_write(0xFF18030C, 0x00020000U, 0x00000000U);
+       psu_mask_write(0xFF5E0074, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0120, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0124, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0090, 0x01003F07U, 0x01000302U);
+       psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000602U);
+       psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000800U);
+       psu_mask_write(0xFF5E00A8, 0x01003F07U, 0x01000302U);
+       psu_mask_write(0xFF5E00AC, 0x01003F07U, 0x01000F02U);
+       psu_mask_write(0xFF5E00B0, 0x01003F07U, 0x01000602U);
+       psu_mask_write(0xFF5E00B8, 0x01003F07U, 0x01000302U);
+       psu_mask_write(0xFF5E00C0, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01011E02U);
+       psu_mask_write(0xFF5E0104, 0x00000007U, 0x00000000U);
+       psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000F00U);
+       psu_mask_write(0xFD1A00A0, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A0060, 0x03003F07U, 0x03000100U);
+       psu_mask_write(0xFD1A0068, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000200U);
+       psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000203U);
+       psu_mask_write(0xFD1A00C4, 0x01003F07U, 0x01000502U);
+       psu_mask_write(0xFD1A00F8, 0x00003F07U, 0x00000200U);
+       psu_mask_write(0xFF180380, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD610100, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFF180300, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFF410050, 0x00000001U, 0x00000000U);
+
+       return 1;
+}
+
+static unsigned long psu_ddr_init_data(void)
+{
+       psu_mask_write(0xFD1A0108, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD070000, 0xE30FBE3DU, 0x81040010U);
+       psu_mask_write(0xFD070010, 0x8000F03FU, 0x00000030U);
+       psu_mask_write(0xFD070020, 0x000003F3U, 0x00000200U);
+       psu_mask_write(0xFD070024, 0xFFFFFFFFU, 0x00800000U);
+       psu_mask_write(0xFD070030, 0x0000007FU, 0x00000000U);
+       psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00408210U);
+       psu_mask_write(0xFD070050, 0x00F1F1F4U, 0x00210000U);
+       psu_mask_write(0xFD070054, 0x0FFF0FFFU, 0x00000000U);
+       psu_mask_write(0xFD070060, 0x00000073U, 0x00000001U);
+       psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x007F80B8U);
+       psu_mask_write(0xFD070070, 0x00000017U, 0x00000010U);
+       psu_mask_write(0xFD070074, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD0700C4, 0x3F000391U, 0x10000200U);
+       psu_mask_write(0xFD0700C8, 0x01FF1F3FU, 0x0040051FU);
+       psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00020102U);
+       psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x00020000U);
+       psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00002205U);
+       psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x07300301U);
+       psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00100200U);
+       psu_mask_write(0xFD0700E4, 0x00FF03FFU, 0x00210004U);
+       psu_mask_write(0xFD0700E8, 0xFFFFFFFFU, 0x000006C0U);
+       psu_mask_write(0xFD0700EC, 0xFFFF0000U, 0x08190000U);
+       psu_mask_write(0xFD0700F0, 0x0000003FU, 0x00000010U);
+       psu_mask_write(0xFD0700F4, 0x00000FFFU, 0x0000066FU);
+       psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x0F102311U);
+       psu_mask_write(0xFD070104, 0x001F1F7FU, 0x00040419U);
+       psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x0608070CU);
+       psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x0050400CU);
+       psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x08030409U);
+       psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x06060403U);
+       psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010004U);
+       psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000606U);
+       psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x04040D07U);
+       psu_mask_write(0xFD070124, 0x40070F3FU, 0x00020309U);
+       psu_mask_write(0xFD07012C, 0x7F1F031FU, 0x1207010EU);
+       psu_mask_write(0xFD070130, 0x00030F1FU, 0x00020608U);
+       psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x81000040U);
+       psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x0201908AU);
+       psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x048B8208U);
+       psu_mask_write(0xFD070194, 0xF31F0F0FU, 0x00030304U);
+       psu_mask_write(0xFD070198, 0x0FF1F1F1U, 0x07000101U);
+       psu_mask_write(0xFD07019C, 0x000000F1U, 0x00000021U);
+       psu_mask_write(0xFD0701A0, 0xC3FF03FFU, 0x00400003U);
+       psu_mask_write(0xFD0701A4, 0x00FF00FFU, 0x00C800FFU);
+       psu_mask_write(0xFD0701B0, 0x00000007U, 0x00000000U);
+       psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000906U);
+       psu_mask_write(0xFD0701C0, 0x00000007U, 0x00000001U);
+       psu_mask_write(0xFD070200, 0x0000001FU, 0x0000001FU);
+       psu_mask_write(0xFD070204, 0x001F1F1FU, 0x001F0909U);
+       psu_mask_write(0xFD070208, 0x0F0F0F0FU, 0x01010100U);
+       psu_mask_write(0xFD07020C, 0x0F0F0F0FU, 0x01010101U);
+       psu_mask_write(0xFD070210, 0x00000F0FU, 0x00000F0FU);
+       psu_mask_write(0xFD070214, 0x0F0F0F0FU, 0x070F0707U);
+       psu_mask_write(0xFD070218, 0x8F0F0F0FU, 0x07070707U);
+       psu_mask_write(0xFD07021C, 0x00000F0FU, 0x00000F0FU);
+       psu_mask_write(0xFD070220, 0x00001F1FU, 0x00001F01U);
+       psu_mask_write(0xFD070224, 0x0F0F0F0FU, 0x07070707U);
+       psu_mask_write(0xFD070228, 0x0F0F0F0FU, 0x07070707U);
+       psu_mask_write(0xFD07022C, 0x0000000FU, 0x00000007U);
+       psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x0600060CU);
+       psu_mask_write(0xFD070244, 0x00003333U, 0x00000001U);
+       psu_mask_write(0xFD070250, 0x7FFF3F07U, 0x01002001U);
+       psu_mask_write(0xFD070264, 0xFF00FFFFU, 0x08000040U);
+       psu_mask_write(0xFD07026C, 0xFF00FFFFU, 0x08000040U);
+       psu_mask_write(0xFD070280, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD070284, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD070288, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD07028C, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD070290, 0x0000FFFFU, 0x00000000U);
+       psu_mask_write(0xFD070294, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD070300, 0x00000011U, 0x00000000U);
+       psu_mask_write(0xFD07030C, 0x80000033U, 0x00000000U);
+       psu_mask_write(0xFD070320, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFD070400, 0x00000111U, 0x00000001U);
+       psu_mask_write(0xFD070404, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070408, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070490, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD070494, 0x0033000FU, 0x0020000BU);
+       psu_mask_write(0xFD070498, 0x07FF07FFU, 0x00000000U);
+       psu_mask_write(0xFD0704B4, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD0704B8, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070540, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD070544, 0x03330F0FU, 0x02000B03U);
+       psu_mask_write(0xFD070548, 0x07FF07FFU, 0x00000000U);
+       psu_mask_write(0xFD070564, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070568, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD0705F0, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD0705F4, 0x03330F0FU, 0x02000B03U);
+       psu_mask_write(0xFD0705F8, 0x07FF07FFU, 0x00000000U);
+       psu_mask_write(0xFD070614, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070618, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD0706A0, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD0706A4, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD0706A8, 0x07FF07FFU, 0x0000004FU);
+       psu_mask_write(0xFD0706AC, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD0706B0, 0x000007FFU, 0x0000004FU);
+       psu_mask_write(0xFD0706C4, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD0706C8, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070750, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD070754, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD070758, 0x07FF07FFU, 0x0000004FU);
+       psu_mask_write(0xFD07075C, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD070760, 0x000007FFU, 0x0000004FU);
+       psu_mask_write(0xFD070774, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070778, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070800, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD070804, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD070808, 0x07FF07FFU, 0x0000004FU);
+       psu_mask_write(0xFD07080C, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD070810, 0x000007FFU, 0x0000004FU);
+       psu_mask_write(0xFD070F04, 0x000001FFU, 0x00000000U);
+       psu_mask_write(0xFD070F08, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD070F0C, 0x000001FFU, 0x00000010U);
+       psu_mask_write(0xFD070F10, 0x000000FFU, 0x0000000FU);
+       psu_mask_write(0xFD072190, 0x1FBFBF3FU, 0x07828002U);
+       psu_mask_write(0xFD1A0108, 0x0000000CU, 0x00000000U);
+       psu_mask_write(0xFD080010, 0xFFFFFFFFU, 0x07001E00U);
+       psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F0FC00U);
+       psu_mask_write(0xFD08001C, 0xFFFFFFFFU, 0x55AA5480U);
+       psu_mask_write(0xFD080024, 0xFFFFFFFFU, 0x010100F4U);
+       psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x41A20D10U);
+       psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0xCD141275U);
+       psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04161U);
+       psu_mask_write(0xFD0800C0, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000E3U);
+       psu_mask_write(0xFD080100, 0xFFFFFFFFU, 0x0800040CU);
+       psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x07220F08U);
+       psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x28200008U);
+       psu_mask_write(0xFD080118, 0xFFFFFFFFU, 0x000F0300U);
+       psu_mask_write(0xFD08011C, 0xFFFFFFFFU, 0x83000800U);
+       psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x01702B07U);
+       psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00310F08U);
+       psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000B0FU);
+       psu_mask_write(0xFD080140, 0xFFFFFFFFU, 0x08400020U);
+       psu_mask_write(0xFD080144, 0xFFFFFFFFU, 0x00000C80U);
+       psu_mask_write(0xFD080150, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080154, 0xFFFFFFFFU, 0x00000200U);
+       psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000630U);
+       psu_mask_write(0xFD080184, 0xFFFFFFFFU, 0x00000301U);
+       psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000010U);
+       psu_mask_write(0xFD08018C, 0xFFFFFFFFU, 0x00000200U);
+       psu_mask_write(0xFD080190, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080194, 0xFFFFFFFFU, 0x000006C0U);
+       psu_mask_write(0xFD080198, 0xFFFFFFFFU, 0x00000819U);
+       psu_mask_write(0xFD0801AC, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD0801B0, 0xFFFFFFFFU, 0x0000004DU);
+       psu_mask_write(0xFD0801B4, 0xFFFFFFFFU, 0x00000008U);
+       psu_mask_write(0xFD0801B8, 0xFFFFFFFFU, 0x0000004DU);
+       psu_mask_write(0xFD0801D8, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080200, 0xFFFFFFFFU, 0x800091C7U);
+       psu_mask_write(0xFD080204, 0xFFFFFFFFU, 0x00010236U);
+       psu_mask_write(0xFD080240, 0xFFFFFFFFU, 0x00141054U);
+       psu_mask_write(0xFD080250, 0xFFFFFFFFU, 0x00088000U);
+       psu_mask_write(0xFD080414, 0xFFFFFFFFU, 0x12341000U);
+       psu_mask_write(0xFD0804F4, 0xFFFFFFFFU, 0x00000005U);
+       psu_mask_write(0xFD080500, 0xFFFFFFFFU, 0x30000028U);
+       psu_mask_write(0xFD080508, 0xFFFFFFFFU, 0x0A000000U);
+       psu_mask_write(0xFD08050C, 0xFFFFFFFFU, 0x00000009U);
+       psu_mask_write(0xFD080510, 0xFFFFFFFFU, 0x0A000000U);
+       psu_mask_write(0xFD080520, 0xFFFFFFFFU, 0x0300B0CEU);
+       psu_mask_write(0xFD080528, 0xFFFFFFFFU, 0xF9032019U);
+       psu_mask_write(0xFD08052C, 0xFFFFFFFFU, 0x07F001E3U);
+       psu_mask_write(0xFD080544, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080548, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080558, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD08055C, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080560, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080564, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080680, 0xFFFFFFFFU, 0x008A8A58U);
+       psu_mask_write(0xFD080684, 0xFFFFFFFFU, 0x000079DDU);
+       psu_mask_write(0xFD080694, 0xFFFFFFFFU, 0x01E10210U);
+       psu_mask_write(0xFD080698, 0xFFFFFFFFU, 0x01E10000U);
+       psu_mask_write(0xFD0806A4, 0xFFFFFFFFU, 0x00087BDBU);
+       psu_mask_write(0xFD080700, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080704, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD08070C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080710, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080714, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080718, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080800, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080804, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD08080C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080810, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080814, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080818, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080900, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080904, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD08090C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080910, 0xFFFFFFFFU, 0x0E00B004U);
+       psu_mask_write(0xFD080914, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080918, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080A00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080A04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD080A0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080A10, 0xFFFFFFFFU, 0x0E00B004U);
+       psu_mask_write(0xFD080A14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080A18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080B00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080B04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD080B08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080B0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080B10, 0xFFFFFFFFU, 0x0E00B004U);
+       psu_mask_write(0xFD080B14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080B18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080C00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080C04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD080C08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080C0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080C10, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080C14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080C18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080D00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080D04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD080D08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080D0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080D10, 0xFFFFFFFFU, 0x0E00B004U);
+       psu_mask_write(0xFD080D14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080D18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080E00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080E04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD080E08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080E0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080E10, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080E14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080E18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080F00, 0xFFFFFFFFU, 0x80803660U);
+       psu_mask_write(0xFD080F04, 0xFFFFFFFFU, 0x55556000U);
+       psu_mask_write(0xFD080F08, 0xFFFFFFFFU, 0xAAAAAAAAU);
+       psu_mask_write(0xFD080F0C, 0xFFFFFFFFU, 0x0029A4A4U);
+       psu_mask_write(0xFD080F10, 0xFFFFFFFFU, 0x0C00B000U);
+       psu_mask_write(0xFD080F14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080F18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD081400, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD08141C, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD08142C, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD081430, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD081440, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD08145C, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD08146C, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD081470, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD081480, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD08149C, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD0814AC, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD0814B0, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD0814C0, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD0814DC, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD0814EC, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD0814F0, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD081500, 0xFFFFFFFFU, 0x15019FFEU);
+       psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x21100000U);
+       psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01266300U);
+       psu_mask_write(0xFD08152C, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70400000U);
+       psu_mask_write(0xFD0817DC, 0xFFFFFFFFU, 0x012643C4U);
+
+       return 1;
+}
+
+static unsigned long psu_ddr_qos_init_data(void)
+{
+       psu_mask_write(0xFD360008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD36001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD370008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD37001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD380008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD38001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD390008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD39001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3A0008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3A001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3B0008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3B001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFF9B0008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFF9B001C, 0x0000000FU, 0x00000000U);
+
+       return 1;
+}
+
+static unsigned long psu_mio_init_data(void)
+{
+       psu_mask_write(0xFF180000, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180004, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180008, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18000C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180010, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180014, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180018, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18001C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180020, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180024, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180028, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18002C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180030, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180034, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180038, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF18003C, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF180040, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF180044, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF180048, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF18004C, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180050, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180054, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180058, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18005C, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180060, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180064, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180068, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18006C, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180070, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180074, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180078, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18007C, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180080, 0x000000FEU, 0x00000008U);
+       psu_mask_write(0xFF180084, 0x000000FEU, 0x00000008U);
+       psu_mask_write(0xFF180098, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18009C, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800A0, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800A4, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800A8, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800AC, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF1800B0, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF1800B4, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800B8, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800BC, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800C0, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800C4, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800C8, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800CC, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800D0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800D4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800D8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800DC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800EC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800FC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF180100, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180104, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180108, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18010C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180110, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180114, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180118, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18011C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180120, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180124, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180128, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18012C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180130, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180134, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180204, 0xFFFFFFFFU, 0x00040000U);
+       psu_mask_write(0xFF180208, 0xFFFFFFFFU, 0x00B02000U);
+       psu_mask_write(0xFF18020C, 0x00003FFFU, 0x00000FC0U);
+       psu_mask_write(0xFF180138, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF18013C, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180140, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF180144, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180148, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF18014C, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF180154, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180158, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF18015C, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF180160, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180164, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180168, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF180170, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180174, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180178, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF18017C, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180180, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180184, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF180200, 0x0000000FU, 0x00000000U);
+
+       return 1;
+}
+
+static unsigned long psu_peripherals_pre_init_data(void)
+{
+       psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012302U);
+       psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000001U);
+
+       return 1;
+}
+
+static unsigned long psu_peripherals_init_data(void)
+{
+       psu_mask_write(0xFD1A0100, 0x00008046U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
+       psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
+       psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFF180390, 0x00000004U, 0x00000004U);
+       psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U);
+       psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U);
+       psu_mask_write(0xFF180320, 0x33840000U, 0x02840000U);
+       psu_mask_write(0xFF18031C, 0x7FFE0000U, 0x64500000U);
+       psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000600U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00008000U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00007800U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000002U, 0x00000000U);
+       psu_mask_write(0xFF000034, 0x000000FFU, 0x00000006U);
+       psu_mask_write(0xFF000018, 0x0000FFFFU, 0x0000007CU);
+       psu_mask_write(0xFF000000, 0x000001FFU, 0x00000017U);
+       psu_mask_write(0xFF000004, 0x000003FFU, 0x00000020U);
+       psu_mask_write(0xFF5E0238, 0x00040000U, 0x00000000U);
+       psu_mask_write(0xFF4B0024, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFFCA5000, 0x00001FFFU, 0x00000000U);
+       psu_mask_write(0xFD5C0060, 0x000F000FU, 0x00000000U);
+       psu_mask_write(0xFFA60040, 0x80000000U, 0x80000000U);
+       psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x05F5DD18U);
+       psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+       mask_delay(1);
+       psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000002U);
+
+       mask_delay(5);
+       psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+       return 1;
+}
+
+static unsigned long psu_serdes_init_data(void)
+{
+       psu_mask_write(0xFD410008, 0x0000001FU, 0x00000008U);
+       psu_mask_write(0xFD41000C, 0x0000001FU, 0x0000000FU);
+       psu_mask_write(0xFD402868, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD40286C, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD40A094, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD40A368, 0x000000FFU, 0x00000038U);
+       psu_mask_write(0xFD40A36C, 0x00000007U, 0x00000003U);
+       psu_mask_write(0xFD40E368, 0x000000FFU, 0x000000E0U);
+       psu_mask_write(0xFD40E36C, 0x00000007U, 0x00000003U);
+       psu_mask_write(0xFD40A370, 0x000000FFU, 0x000000F4U);
+       psu_mask_write(0xFD40A374, 0x000000FFU, 0x00000031U);
+       psu_mask_write(0xFD40A378, 0x000000FFU, 0x00000002U);
+       psu_mask_write(0xFD40A37C, 0x00000033U, 0x00000030U);
+       psu_mask_write(0xFD40E370, 0x000000FFU, 0x000000C9U);
+       psu_mask_write(0xFD40E374, 0x000000FFU, 0x000000D2U);
+       psu_mask_write(0xFD40E378, 0x000000FFU, 0x00000001U);
+       psu_mask_write(0xFD40E37C, 0x000000B3U, 0x000000B0U);
+       psu_mask_write(0xFD40906C, 0x00000003U, 0x00000003U);
+       psu_mask_write(0xFD4080F4, 0x00000003U, 0x00000003U);
+       psu_mask_write(0xFD40E360, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40D06C, 0x0000000FU, 0x0000000FU);
+       psu_mask_write(0xFD40C0F4, 0x0000000BU, 0x0000000BU);
+       psu_mask_write(0xFD4090CC, 0x00000020U, 0x00000020U);
+       psu_mask_write(0xFD401074, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD405074, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD409074, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD40D074, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD401994, 0x00000007U, 0x00000007U);
+       psu_mask_write(0xFD405994, 0x00000007U, 0x00000007U);
+       psu_mask_write(0xFD40989C, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD4098F8, 0x000000FFU, 0x0000001AU);
+       psu_mask_write(0xFD4098FC, 0x000000FFU, 0x0000001AU);
+       psu_mask_write(0xFD409990, 0x000000FFU, 0x00000010U);
+       psu_mask_write(0xFD409924, 0x000000FFU, 0x000000FEU);
+       psu_mask_write(0xFD409928, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD409900, 0x000000FFU, 0x0000001AU);
+       psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD409980, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD409914, 0x000000FFU, 0x000000F7U);
+       psu_mask_write(0xFD409918, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD409940, 0x000000FFU, 0x000000F7U);
+       psu_mask_write(0xFD409944, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD409994, 0x00000007U, 0x00000007U);
+       psu_mask_write(0xFD40D89C, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD40D8F8, 0x000000FFU, 0x0000007DU);
+       psu_mask_write(0xFD40D8FC, 0x000000FFU, 0x0000007DU);
+       psu_mask_write(0xFD40D990, 0x000000FFU, 0x00000001U);
+       psu_mask_write(0xFD40D924, 0x000000FFU, 0x0000009CU);
+       psu_mask_write(0xFD40D928, 0x000000FFU, 0x00000039U);
+       psu_mask_write(0xFD40D98C, 0x000000F0U, 0x00000020U);
+       psu_mask_write(0xFD40D900, 0x000000FFU, 0x0000007DU);
+       psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000064U);
+       psu_mask_write(0xFD40D980, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD40D914, 0x000000FFU, 0x000000F7U);
+       psu_mask_write(0xFD40D918, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD40D940, 0x000000FFU, 0x000000F7U);
+       psu_mask_write(0xFD40D944, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD40D994, 0x00000007U, 0x00000007U);
+       psu_mask_write(0xFD40107C, 0x0000000FU, 0x00000001U);
+       psu_mask_write(0xFD40507C, 0x0000000FU, 0x00000001U);
+       psu_mask_write(0xFD40907C, 0x0000000FU, 0x00000001U);
+       psu_mask_write(0xFD40D07C, 0x0000000FU, 0x00000001U);
+       psu_mask_write(0xFD4019A4, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD401038, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40102C, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD4059A4, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD405038, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40502C, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD4099A4, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD409038, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40902C, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40D9A4, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD40D038, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40D02C, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD4019AC, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD4059AC, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD4099AC, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD40D9AC, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD401978, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD405978, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD409978, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD40D978, 0x00000010U, 0x00000010U);
+
+       serdes_illcalib(2, 3, 3, 0, 0, 0, 0, 0);
+       psu_mask_write(0xFD410014, 0x00000077U, 0x00000023U);
+       psu_mask_write(0xFD40C1D8, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD40DC14, 0x000000FFU, 0x000000E6U);
+       psu_mask_write(0xFD40DC40, 0x0000001FU, 0x0000000CU);
+       psu_mask_write(0xFD40D94C, 0x00000020U, 0x00000020U);
+       psu_mask_write(0xFD40D950, 0x00000007U, 0x00000006U);
+       psu_mask_write(0xFD40C048, 0x000000FFU, 0x00000001U);
+
+       return 1;
+}
+
+static unsigned long psu_resetout_init_data(void)
+{
+       psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+       psu_mask_write(0xFF9D0080, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF9D007C, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000000U);
+       psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD3D0100, 0x00000003U, 0x00000003U);
+       psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000000U);
+       psu_mask_write(0xFE20C200, 0x00023FFFU, 0x00022457U);
+       psu_mask_write(0xFE20C630, 0x003FFF00U, 0x00000000U);
+       psu_mask_write(0xFE20C11C, 0x00000600U, 0x00000600U);
+       psu_mask_write(0xFE20C12C, 0x00004000U, 0x00004000U);
+       psu_mask_write(0xFD480064, 0x00000200U, 0x00000200U);
+       mask_poll(0xFD40A3E4, 0x00000010U);
+       mask_poll(0xFD40E3E4, 0x00000010U);
+       psu_mask_write(0xFD0C00AC, 0xFFFFFFFFU, 0x28184018U);
+       psu_mask_write(0xFD0C00B0, 0xFFFFFFFFU, 0x0E081406U);
+       psu_mask_write(0xFD0C00B4, 0xFFFFFFFFU, 0x064A0813U);
+       psu_mask_write(0xFD0C00B8, 0xFFFFFFFFU, 0x3FFC96A4U);
+
+       return 1;
+}
+
+static unsigned long psu_resetin_init_data(void)
+{
+       psu_mask_write(0xFF5E023C, 0x00000540U, 0x00000540U);
+       psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000002U);
+
+       return 1;
+}
+
+static unsigned long psu_afi_config(void)
+{
+       psu_mask_write(0xFD1A0100, 0x00001F80U, 0x00000000U);
+       psu_mask_write(0xFF5E023C, 0x00080000U, 0x00000000U);
+       psu_mask_write(0xFD615000, 0x00000300U, 0x00000200U);
+       psu_mask_write(0xFD360000, 0x00000003U, 0x00000002U);
+       psu_mask_write(0xFD370000, 0x00000003U, 0x00000002U);
+       psu_mask_write(0xFD360014, 0x00000003U, 0x00000002U);
+       psu_mask_write(0xFD370014, 0x00000003U, 0x00000002U);
+
+       return 1;
+}
+
+static unsigned long psu_ddr_phybringup_data(void)
+{
+       unsigned int regval = 0;
+       unsigned int pll_retry = 10;
+       unsigned int pll_locked = 0;
+       int cur_R006_tREFPRD;
+
+       while ((pll_retry > 0) && (!pll_locked)) {
+               Xil_Out32(0xFD080004, 0x00040010);
+               Xil_Out32(0xFD080004, 0x00040011);
+
+               while ((Xil_In32(0xFD080030) & 0x1) != 1)
+                       ;
+               pll_locked = (Xil_In32(0xFD080030) & 0x80000000)
+                   >> 31;
+               pll_locked &= (Xil_In32(0xFD0807E0) & 0x10000)
+                   >> 16;
+               pll_locked &= (Xil_In32(0xFD0809E0) & 0x10000) >> 16;
+               pll_locked &= (Xil_In32(0xFD080BE0) & 0x10000)
+                   >> 16;
+               pll_locked &= (Xil_In32(0xFD080DE0) & 0x10000)
+                   >> 16;
+               pll_retry--;
+       }
+       Xil_Out32(0xFD0800C4, Xil_In32(0xFD0800C4) | (pll_retry << 16));
+       if (!pll_locked)
+               return 0;
+
+       Xil_Out32(0xFD080004U, 0x00040063U);
+
+       while ((Xil_In32(0xFD080030U) & 0x0000000FU) != 0x0000000FU)
+               ;
+       prog_reg(0xFD080004U, 0x00000001U, 0x00000000U, 0x00000001U);
+
+       while ((Xil_In32(0xFD080030U) & 0x000000FFU) != 0x0000001FU)
+               ;
+       Xil_Out32(0xFD0701B0U, 0x00000001U);
+       Xil_Out32(0xFD070320U, 0x00000001U);
+       while ((Xil_In32(0xFD070004U) & 0x0000000FU) != 0x00000001U)
+               ;
+       prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000001U);
+       Xil_Out32(0xFD080004, 0x0004FE01);
+       regval = Xil_In32(0xFD080030);
+       while (regval != 0x80000FFF)
+               regval = Xil_In32(0xFD080030);
+       regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+       if (regval != 0)
+               return 0;
+
+       Xil_Out32(0xFD080200U, 0x100091C7U);
+
+       cur_R006_tREFPRD = (Xil_In32(0xFD080018U) & 0x0003FFFFU) >> 0x00000000U;
+       prog_reg(0xFD080018, 0x3FFFF, 0x0, cur_R006_tREFPRD);
+
+       prog_reg(0xFD08001CU, 0x00000018U, 0x00000003U, 0x00000003U);
+       prog_reg(0xFD08142CU, 0x00000030U, 0x00000004U, 0x00000003U);
+       prog_reg(0xFD08146CU, 0x00000030U, 0x00000004U, 0x00000003U);
+       prog_reg(0xFD0814ACU, 0x00000030U, 0x00000004U, 0x00000003U);
+       prog_reg(0xFD0814ECU, 0x00000030U, 0x00000004U, 0x00000003U);
+       prog_reg(0xFD08152CU, 0x00000030U, 0x00000004U, 0x00000003U);
+
+       Xil_Out32(0xFD080004, 0x00060001);
+       regval = Xil_In32(0xFD080030);
+       while ((regval & 0x80004001) != 0x80004001)
+               regval = Xil_In32(0xFD080030);
+
+       regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+       if (regval != 0)
+               return 0;
+
+       prog_reg(0xFD08001CU, 0x00000018U, 0x00000003U, 0x00000000U);
+       prog_reg(0xFD08142CU, 0x00000030U, 0x00000004U, 0x00000000U);
+       prog_reg(0xFD08146CU, 0x00000030U, 0x00000004U, 0x00000000U);
+       prog_reg(0xFD0814ACU, 0x00000030U, 0x00000004U, 0x00000000U);
+       prog_reg(0xFD0814ECU, 0x00000030U, 0x00000004U, 0x00000000U);
+       prog_reg(0xFD08152CU, 0x00000030U, 0x00000004U, 0x00000000U);
+
+       Xil_Out32(0xFD080200U, 0x800091C7U);
+       prog_reg(0xFD080018, 0x3FFFF, 0x0, cur_R006_tREFPRD);
+
+       Xil_Out32(0xFD080004, 0x0000C001);
+       regval = Xil_In32(0xFD080030);
+       while ((regval & 0x80000C01) != 0x80000C01)
+               regval = Xil_In32(0xFD080030);
+
+       Xil_Out32(0xFD070180U, 0x01000040U);
+       Xil_Out32(0xFD070060U, 0x00000000U);
+       prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000000U);
+
+       return 1;
+}
+
+static int serdes_rst_seq(u32 lane3_protocol, u32 lane3_rate,
+                         u32 lane2_protocol, u32 lane2_rate,
+                         u32 lane1_protocol, u32 lane1_rate,
+                         u32 lane0_protocol, u32 lane0_rate)
+{
+       Xil_Out32(0xFD410098, 0x00000000);
+       Xil_Out32(0xFD401010, 0x00000040);
+       Xil_Out32(0xFD405010, 0x00000040);
+       Xil_Out32(0xFD409010, 0x00000040);
+       Xil_Out32(0xFD40D010, 0x00000040);
+       Xil_Out32(0xFD402084, 0x00000080);
+       Xil_Out32(0xFD406084, 0x00000080);
+       Xil_Out32(0xFD40A084, 0x00000080);
+       Xil_Out32(0xFD40E084, 0x00000080);
+       Xil_Out32(0xFD410098, 0x00000004);
+       mask_delay(50);
+       if (lane0_rate == 1)
+               Xil_Out32(0xFD410098, 0x0000000E);
+       Xil_Out32(0xFD410098, 0x00000006);
+       if (lane0_rate == 1) {
+               Xil_Out32(0xFD40000C, 0x00000004);
+               Xil_Out32(0xFD40400C, 0x00000004);
+               Xil_Out32(0xFD40800C, 0x00000004);
+               Xil_Out32(0xFD40C00C, 0x00000004);
+               Xil_Out32(0xFD410098, 0x00000007);
+               mask_delay(400);
+               Xil_Out32(0xFD40000C, 0x0000000C);
+               Xil_Out32(0xFD40400C, 0x0000000C);
+               Xil_Out32(0xFD40800C, 0x0000000C);
+               Xil_Out32(0xFD40C00C, 0x0000000C);
+               mask_delay(15);
+               Xil_Out32(0xFD410098, 0x0000000F);
+               mask_delay(100);
+       }
+       if (lane0_protocol != 0)
+               mask_poll(0xFD4023E4, 0x00000010U);
+       if (lane1_protocol != 0)
+               mask_poll(0xFD4063E4, 0x00000010U);
+       if (lane2_protocol != 0)
+               mask_poll(0xFD40A3E4, 0x00000010U);
+       if (lane3_protocol != 0)
+               mask_poll(0xFD40E3E4, 0x00000010U);
+       mask_delay(50);
+       Xil_Out32(0xFD401010, 0x000000C0);
+       Xil_Out32(0xFD405010, 0x000000C0);
+       Xil_Out32(0xFD409010, 0x000000C0);
+       Xil_Out32(0xFD40D010, 0x000000C0);
+       Xil_Out32(0xFD401010, 0x00000080);
+       Xil_Out32(0xFD405010, 0x00000080);
+       Xil_Out32(0xFD409010, 0x00000080);
+       Xil_Out32(0xFD40D010, 0x00000080);
+
+       Xil_Out32(0xFD402084, 0x000000C0);
+       Xil_Out32(0xFD406084, 0x000000C0);
+       Xil_Out32(0xFD40A084, 0x000000C0);
+       Xil_Out32(0xFD40E084, 0x000000C0);
+       mask_delay(50);
+       Xil_Out32(0xFD402084, 0x00000080);
+       Xil_Out32(0xFD406084, 0x00000080);
+       Xil_Out32(0xFD40A084, 0x00000080);
+       Xil_Out32(0xFD40E084, 0x00000080);
+       mask_delay(50);
+       Xil_Out32(0xFD401010, 0x00000000);
+       Xil_Out32(0xFD405010, 0x00000000);
+       Xil_Out32(0xFD409010, 0x00000000);
+       Xil_Out32(0xFD40D010, 0x00000000);
+       Xil_Out32(0xFD402084, 0x00000000);
+       Xil_Out32(0xFD406084, 0x00000000);
+       Xil_Out32(0xFD40A084, 0x00000000);
+       Xil_Out32(0xFD40E084, 0x00000000);
+       mask_delay(500);
+       return 1;
+}
+
+static int serdes_bist_static_settings(u32 lane_active)
+{
+       if (lane_active == 0) {
+               Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) & 0xFFFFFF1F));
+               Xil_Out32(0xFD403068, 0x1);
+               Xil_Out32(0xFD40306C, 0x1);
+               Xil_Out32(0xFD4010AC, 0x0020);
+               Xil_Out32(0xFD403008, 0x0);
+               Xil_Out32(0xFD40300C, 0xF4);
+               Xil_Out32(0xFD403010, 0x0);
+               Xil_Out32(0xFD403014, 0x0);
+               Xil_Out32(0xFD403018, 0x00);
+               Xil_Out32(0xFD40301C, 0xFB);
+               Xil_Out32(0xFD403020, 0xFF);
+               Xil_Out32(0xFD403024, 0x0);
+               Xil_Out32(0xFD403028, 0x00);
+               Xil_Out32(0xFD40302C, 0x00);
+               Xil_Out32(0xFD403030, 0x4A);
+               Xil_Out32(0xFD403034, 0x4A);
+               Xil_Out32(0xFD403038, 0x4A);
+               Xil_Out32(0xFD40303C, 0x4A);
+               Xil_Out32(0xFD403040, 0x0);
+               Xil_Out32(0xFD403044, 0x14);
+               Xil_Out32(0xFD403048, 0x02);
+               Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) & 0xFFFFFF1F));
+       }
+       if (lane_active == 1) {
+               Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) & 0xFFFFFF1F));
+               Xil_Out32(0xFD407068, 0x1);
+               Xil_Out32(0xFD40706C, 0x1);
+               Xil_Out32(0xFD4050AC, 0x0020);
+               Xil_Out32(0xFD407008, 0x0);
+               Xil_Out32(0xFD40700C, 0xF4);
+               Xil_Out32(0xFD407010, 0x0);
+               Xil_Out32(0xFD407014, 0x0);
+               Xil_Out32(0xFD407018, 0x00);
+               Xil_Out32(0xFD40701C, 0xFB);
+               Xil_Out32(0xFD407020, 0xFF);
+               Xil_Out32(0xFD407024, 0x0);
+               Xil_Out32(0xFD407028, 0x00);
+               Xil_Out32(0xFD40702C, 0x00);
+               Xil_Out32(0xFD407030, 0x4A);
+               Xil_Out32(0xFD407034, 0x4A);
+               Xil_Out32(0xFD407038, 0x4A);
+               Xil_Out32(0xFD40703C, 0x4A);
+               Xil_Out32(0xFD407040, 0x0);
+               Xil_Out32(0xFD407044, 0x14);
+               Xil_Out32(0xFD407048, 0x02);
+               Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) & 0xFFFFFF1F));
+       }
+
+       if (lane_active == 2) {
+               Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) & 0xFFFFFF1F));
+               Xil_Out32(0xFD40B068, 0x1);
+               Xil_Out32(0xFD40B06C, 0x1);
+               Xil_Out32(0xFD4090AC, 0x0020);
+               Xil_Out32(0xFD40B008, 0x0);
+               Xil_Out32(0xFD40B00C, 0xF4);
+               Xil_Out32(0xFD40B010, 0x0);
+               Xil_Out32(0xFD40B014, 0x0);
+               Xil_Out32(0xFD40B018, 0x00);
+               Xil_Out32(0xFD40B01C, 0xFB);
+               Xil_Out32(0xFD40B020, 0xFF);
+               Xil_Out32(0xFD40B024, 0x0);
+               Xil_Out32(0xFD40B028, 0x00);
+               Xil_Out32(0xFD40B02C, 0x00);
+               Xil_Out32(0xFD40B030, 0x4A);
+               Xil_Out32(0xFD40B034, 0x4A);
+               Xil_Out32(0xFD40B038, 0x4A);
+               Xil_Out32(0xFD40B03C, 0x4A);
+               Xil_Out32(0xFD40B040, 0x0);
+               Xil_Out32(0xFD40B044, 0x14);
+               Xil_Out32(0xFD40B048, 0x02);
+               Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) & 0xFFFFFF1F));
+       }
+
+       if (lane_active == 3) {
+               Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) & 0xFFFFFF1F));
+               Xil_Out32(0xFD40F068, 0x1);
+               Xil_Out32(0xFD40F06C, 0x1);
+               Xil_Out32(0xFD40D0AC, 0x0020);
+               Xil_Out32(0xFD40F008, 0x0);
+               Xil_Out32(0xFD40F00C, 0xF4);
+               Xil_Out32(0xFD40F010, 0x0);
+               Xil_Out32(0xFD40F014, 0x0);
+               Xil_Out32(0xFD40F018, 0x00);
+               Xil_Out32(0xFD40F01C, 0xFB);
+               Xil_Out32(0xFD40F020, 0xFF);
+               Xil_Out32(0xFD40F024, 0x0);
+               Xil_Out32(0xFD40F028, 0x00);
+               Xil_Out32(0xFD40F02C, 0x00);
+               Xil_Out32(0xFD40F030, 0x4A);
+               Xil_Out32(0xFD40F034, 0x4A);
+               Xil_Out32(0xFD40F038, 0x4A);
+               Xil_Out32(0xFD40F03C, 0x4A);
+               Xil_Out32(0xFD40F040, 0x0);
+               Xil_Out32(0xFD40F044, 0x14);
+               Xil_Out32(0xFD40F048, 0x02);
+               Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) & 0xFFFFFF1F));
+       }
+       return 1;
+}
+
+static int serdes_bist_run(u32 lane_active)
+{
+       if (lane_active == 0) {
+               psu_mask_write(0xFD410044, 0x00000003U, 0x00000000U);
+               psu_mask_write(0xFD410040, 0x00000003U, 0x00000000U);
+               psu_mask_write(0xFD410038, 0x00000007U, 0x00000001U);
+               Xil_Out32(0xFD4010AC, 0x0020);
+               Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) | 0x1));
+       }
+       if (lane_active == 1) {
+               psu_mask_write(0xFD410044, 0x0000000CU, 0x00000000U);
+               psu_mask_write(0xFD410040, 0x0000000CU, 0x00000000U);
+               psu_mask_write(0xFD410038, 0x00000070U, 0x00000010U);
+               Xil_Out32(0xFD4050AC, 0x0020);
+               Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) | 0x1));
+       }
+       if (lane_active == 2) {
+               psu_mask_write(0xFD410044, 0x00000030U, 0x00000000U);
+               psu_mask_write(0xFD410040, 0x00000030U, 0x00000000U);
+               psu_mask_write(0xFD41003C, 0x00000007U, 0x00000001U);
+               Xil_Out32(0xFD4090AC, 0x0020);
+               Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) | 0x1));
+       }
+       if (lane_active == 3) {
+               psu_mask_write(0xFD410040, 0x000000C0U, 0x00000000U);
+               psu_mask_write(0xFD410044, 0x000000C0U, 0x00000000U);
+               psu_mask_write(0xFD41003C, 0x00000070U, 0x00000010U);
+               Xil_Out32(0xFD40D0AC, 0x0020);
+               Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) | 0x1));
+       }
+       mask_delay(100);
+       return 1;
+}
+
+static int serdes_bist_result(u32 lane_active)
+{
+       u32 pkt_cnt_l0, pkt_cnt_h0, err_cnt_l0, err_cnt_h0;
+
+       if (lane_active == 0) {
+               pkt_cnt_l0 = Xil_In32(0xFD40304C);
+               pkt_cnt_h0 = Xil_In32(0xFD403050);
+               err_cnt_l0 = Xil_In32(0xFD403054);
+               err_cnt_h0 = Xil_In32(0xFD403058);
+       }
+       if (lane_active == 1) {
+               pkt_cnt_l0 = Xil_In32(0xFD40704C);
+               pkt_cnt_h0 = Xil_In32(0xFD407050);
+               err_cnt_l0 = Xil_In32(0xFD407054);
+               err_cnt_h0 = Xil_In32(0xFD407058);
+       }
+       if (lane_active == 2) {
+               pkt_cnt_l0 = Xil_In32(0xFD40B04C);
+               pkt_cnt_h0 = Xil_In32(0xFD40B050);
+               err_cnt_l0 = Xil_In32(0xFD40B054);
+               err_cnt_h0 = Xil_In32(0xFD40B058);
+       }
+       if (lane_active == 3) {
+               pkt_cnt_l0 = Xil_In32(0xFD40F04C);
+               pkt_cnt_h0 = Xil_In32(0xFD40F050);
+               err_cnt_l0 = Xil_In32(0xFD40F054);
+               err_cnt_h0 = Xil_In32(0xFD40F058);
+       }
+       if (lane_active == 0)
+               Xil_Out32(0xFD403004, 0x0);
+       if (lane_active == 1)
+               Xil_Out32(0xFD407004, 0x0);
+       if (lane_active == 2)
+               Xil_Out32(0xFD40B004, 0x0);
+       if (lane_active == 3)
+               Xil_Out32(0xFD40F004, 0x0);
+       if (err_cnt_l0 > 0 || err_cnt_h0 > 0 ||
+           (pkt_cnt_l0 == 0 && pkt_cnt_h0 == 0))
+               return 0;
+       return 1;
+}
+
+static int serdes_illcalib_pcie_gen1(u32 lane3_protocol, u32 lane3_rate,
+                                    u32 lane2_protocol, u32 lane2_rate,
+                                    u32 lane1_protocol, u32 lane1_rate,
+                                    u32 lane0_protocol, u32 lane0_rate,
+                                    u32 gen2_calib)
+{
+       u64 tempbistresult;
+       u32 currbistresult[4];
+       u32 prevbistresult[4];
+       u32 itercount = 0;
+       u32 ill12_val[4], ill1_val[4];
+       u32 loop = 0;
+       u32 iterresult[8];
+       u32 meancount[4];
+       u32 bistpasscount[4];
+       u32 meancountalt[4];
+       u32 meancountalt_bistpasscount[4];
+       u32 lane0_active;
+       u32 lane1_active;
+       u32 lane2_active;
+       u32 lane3_active;
+
+       lane0_active = (lane0_protocol == 1);
+       lane1_active = (lane1_protocol == 1);
+       lane2_active = (lane2_protocol == 1);
+       lane3_active = (lane3_protocol == 1);
+       for (loop = 0; loop <= 3; loop++) {
+               iterresult[loop] = 0;
+               iterresult[loop + 4] = 0;
+               meancountalt[loop] = 0;
+               meancountalt_bistpasscount[loop] = 0;
+               meancount[loop] = 0;
+               prevbistresult[loop] = 0;
+               bistpasscount[loop] = 0;
+       }
+       itercount = 0;
+       if (lane0_active)
+               serdes_bist_static_settings(0);
+       if (lane1_active)
+               serdes_bist_static_settings(1);
+       if (lane2_active)
+               serdes_bist_static_settings(2);
+       if (lane3_active)
+               serdes_bist_static_settings(3);
+       do {
+               if (gen2_calib != 1) {
+                       if (lane0_active == 1)
+                               ill1_val[0] = ((0x04 + itercount * 8) % 0x100);
+                       if (lane0_active == 1)
+                               ill12_val[0] =
+                                   ((0x04 + itercount * 8) >=
+                                    0x100) ? 0x10 : 0x00;
+                       if (lane1_active == 1)
+                               ill1_val[1] = ((0x04 + itercount * 8) % 0x100);
+                       if (lane1_active == 1)
+                               ill12_val[1] =
+                                   ((0x04 + itercount * 8) >=
+                                    0x100) ? 0x10 : 0x00;
+                       if (lane2_active == 1)
+                               ill1_val[2] = ((0x04 + itercount * 8) % 0x100);
+                       if (lane2_active == 1)
+                               ill12_val[2] =
+                                   ((0x04 + itercount * 8) >=
+                                    0x100) ? 0x10 : 0x00;
+                       if (lane3_active == 1)
+                               ill1_val[3] = ((0x04 + itercount * 8) % 0x100);
+                       if (lane3_active == 1)
+                               ill12_val[3] =
+                                   ((0x04 + itercount * 8) >=
+                                    0x100) ? 0x10 : 0x00;
+
+                       if (lane0_active == 1)
+                               Xil_Out32(0xFD401924, ill1_val[0]);
+                       if (lane0_active == 1)
+                               psu_mask_write(0xFD401990, 0x000000F0U,
+                                              ill12_val[0]);
+                       if (lane1_active == 1)
+                               Xil_Out32(0xFD405924, ill1_val[1]);
+                       if (lane1_active == 1)
+                               psu_mask_write(0xFD405990, 0x000000F0U,
+                                              ill12_val[1]);
+                       if (lane2_active == 1)
+                               Xil_Out32(0xFD409924, ill1_val[2]);
+                       if (lane2_active == 1)
+                               psu_mask_write(0xFD409990, 0x000000F0U,
+                                              ill12_val[2]);
+                       if (lane3_active == 1)
+                               Xil_Out32(0xFD40D924, ill1_val[3]);
+                       if (lane3_active == 1)
+                               psu_mask_write(0xFD40D990, 0x000000F0U,
+                                              ill12_val[3]);
+               }
+               if (gen2_calib == 1) {
+                       if (lane0_active == 1)
+                               ill1_val[0] = ((0x104 + itercount * 8) % 0x100);
+                       if (lane0_active == 1)
+                               ill12_val[0] =
+                                   ((0x104 + itercount * 8) >=
+                                    0x200) ? 0x02 : 0x01;
+                       if (lane1_active == 1)
+                               ill1_val[1] = ((0x104 + itercount * 8) % 0x100);
+                       if (lane1_active == 1)
+                               ill12_val[1] =
+                                   ((0x104 + itercount * 8) >=
+                                    0x200) ? 0x02 : 0x01;
+                       if (lane2_active == 1)
+                               ill1_val[2] = ((0x104 + itercount * 8) % 0x100);
+                       if (lane2_active == 1)
+                               ill12_val[2] =
+                                   ((0x104 + itercount * 8) >=
+                                    0x200) ? 0x02 : 0x01;
+                       if (lane3_active == 1)
+                               ill1_val[3] = ((0x104 + itercount * 8) % 0x100);
+                       if (lane3_active == 1)
+                               ill12_val[3] =
+                                   ((0x104 + itercount * 8) >=
+                                    0x200) ? 0x02 : 0x01;
+
+                       if (lane0_active == 1)
+                               Xil_Out32(0xFD401928, ill1_val[0]);
+                       if (lane0_active == 1)
+                               psu_mask_write(0xFD401990, 0x0000000FU,
+                                              ill12_val[0]);
+                       if (lane1_active == 1)
+                               Xil_Out32(0xFD405928, ill1_val[1]);
+                       if (lane1_active == 1)
+                               psu_mask_write(0xFD405990, 0x0000000FU,
+                                              ill12_val[1]);
+                       if (lane2_active == 1)
+                               Xil_Out32(0xFD409928, ill1_val[2]);
+                       if (lane2_active == 1)
+                               psu_mask_write(0xFD409990, 0x0000000FU,
+                                              ill12_val[2]);
+                       if (lane3_active == 1)
+                               Xil_Out32(0xFD40D928, ill1_val[3]);
+                       if (lane3_active == 1)
+                               psu_mask_write(0xFD40D990, 0x0000000FU,
+                                              ill12_val[3]);
+               }
+
+               if (lane0_active == 1)
+                       psu_mask_write(0xFD401018, 0x00000030U, 0x00000010U);
+               if (lane1_active == 1)
+                       psu_mask_write(0xFD405018, 0x00000030U, 0x00000010U);
+               if (lane2_active == 1)
+                       psu_mask_write(0xFD409018, 0x00000030U, 0x00000010U);
+               if (lane3_active == 1)
+                       psu_mask_write(0xFD40D018, 0x00000030U, 0x00000010U);
+               if (lane0_active == 1)
+                       currbistresult[0] = 0;
+               if (lane1_active == 1)
+                       currbistresult[1] = 0;
+               if (lane2_active == 1)
+                       currbistresult[2] = 0;
+               if (lane3_active == 1)
+                       currbistresult[3] = 0;
+               serdes_rst_seq(lane3_protocol, lane3_rate, lane2_protocol,
+                              lane2_rate, lane1_protocol, lane1_rate,
+                              lane0_protocol, lane0_rate);
+               if (lane3_active == 1)
+                       serdes_bist_run(3);
+               if (lane2_active == 1)
+                       serdes_bist_run(2);
+               if (lane1_active == 1)
+                       serdes_bist_run(1);
+               if (lane0_active == 1)
+                       serdes_bist_run(0);
+               tempbistresult = 0;
+               if (lane3_active == 1)
+                       tempbistresult = tempbistresult | serdes_bist_result(3);
+               tempbistresult = tempbistresult << 1;
+               if (lane2_active == 1)
+                       tempbistresult = tempbistresult | serdes_bist_result(2);
+               tempbistresult = tempbistresult << 1;
+               if (lane1_active == 1)
+                       tempbistresult = tempbistresult | serdes_bist_result(1);
+               tempbistresult = tempbistresult << 1;
+               if (lane0_active == 1)
+                       tempbistresult = tempbistresult | serdes_bist_result(0);
+               Xil_Out32(0xFD410098, 0x0);
+               Xil_Out32(0xFD410098, 0x2);
+
+               if (itercount < 32) {
+                       iterresult[0] =
+                           ((iterresult[0] << 1) |
+                            ((tempbistresult & 0x1) == 0x1));
+                       iterresult[1] =
+                           ((iterresult[1] << 1) |
+                            ((tempbistresult & 0x2) == 0x2));
+                       iterresult[2] =
+                           ((iterresult[2] << 1) |
+                            ((tempbistresult & 0x4) == 0x4));
+                       iterresult[3] =
+                           ((iterresult[3] << 1) |
+                            ((tempbistresult & 0x8) == 0x8));
+               } else {
+                       iterresult[4] =
+                           ((iterresult[4] << 1) |
+                            ((tempbistresult & 0x1) == 0x1));
+                       iterresult[5] =
+                           ((iterresult[5] << 1) |
+                            ((tempbistresult & 0x2) == 0x2));
+                       iterresult[6] =
+                           ((iterresult[6] << 1) |
+                            ((tempbistresult & 0x4) == 0x4));
+                       iterresult[7] =
+                           ((iterresult[7] << 1) |
+                            ((tempbistresult & 0x8) == 0x8));
+               }
+               currbistresult[0] =
+                   currbistresult[0] | ((tempbistresult & 0x1) == 1);
+               currbistresult[1] =
+                   currbistresult[1] | ((tempbistresult & 0x2) == 0x2);
+               currbistresult[2] =
+                   currbistresult[2] | ((tempbistresult & 0x4) == 0x4);
+               currbistresult[3] =
+                   currbistresult[3] | ((tempbistresult & 0x8) == 0x8);
+
+               for (loop = 0; loop <= 3; loop++) {
+                       if (currbistresult[loop] == 1 && prevbistresult[loop] == 1)
+                               bistpasscount[loop] = bistpasscount[loop] + 1;
+                       if (bistpasscount[loop] < 4 &&
+                           currbistresult[loop] == 0 && itercount > 2) {
+                               if (meancountalt_bistpasscount[loop] <
+                                   bistpasscount[loop]) {
+                                       meancountalt_bistpasscount[loop] =
+                                           bistpasscount[loop];
+                                       meancountalt[loop] =
+                                           ((itercount - 1) -
+                                            ((bistpasscount[loop] + 1) / 2));
+                               }
+                               bistpasscount[loop] = 0;
+                       }
+                       if (meancount[loop] == 0 && bistpasscount[loop] >= 4 &&
+                           (currbistresult[loop] == 0 || itercount == 63) &&
+                           prevbistresult[loop] == 1)
+                               meancount[loop] =
+                                   (itercount - 1) -
+                                   ((bistpasscount[loop] + 1) / 2);
+                       prevbistresult[loop] = currbistresult[loop];
+               }
+       } while (++itercount < 64);
+
+       for (loop = 0; loop <= 3; loop++) {
+               if (lane0_active == 0 && loop == 0)
+                       continue;
+               if (lane1_active == 0 && loop == 1)
+                       continue;
+               if (lane2_active == 0 && loop == 2)
+                       continue;
+               if (lane3_active == 0 && loop == 3)
+                       continue;
+
+               if (meancount[loop] == 0)
+                       meancount[loop] = meancountalt[loop];
+
+               if (gen2_calib != 1) {
+                       ill1_val[loop] = ((0x04 + meancount[loop] * 8) % 0x100);
+                       ill12_val[loop] =
+                           ((0x04 + meancount[loop] * 8) >=
+                            0x100) ? 0x10 : 0x00;
+                       Xil_Out32(0xFFFE0000 + loop * 4, iterresult[loop]);
+                       Xil_Out32(0xFFFE0010 + loop * 4, iterresult[loop + 4]);
+                       Xil_Out32(0xFFFE0020 + loop * 4, bistpasscount[loop]);
+                       Xil_Out32(0xFFFE0030 + loop * 4, meancount[loop]);
+               }
+               if (gen2_calib == 1) {
+                       ill1_val[loop] =
+                           ((0x104 + meancount[loop] * 8) % 0x100);
+                       ill12_val[loop] =
+                           ((0x104 + meancount[loop] * 8) >=
+                            0x200) ? 0x02 : 0x01;
+                       Xil_Out32(0xFFFE0040 + loop * 4, iterresult[loop]);
+                       Xil_Out32(0xFFFE0050 + loop * 4, iterresult[loop + 4]);
+                       Xil_Out32(0xFFFE0060 + loop * 4, bistpasscount[loop]);
+                       Xil_Out32(0xFFFE0070 + loop * 4, meancount[loop]);
+               }
+       }
+       if (gen2_calib != 1) {
+               if (lane0_active == 1)
+                       Xil_Out32(0xFD401924, ill1_val[0]);
+               if (lane0_active == 1)
+                       psu_mask_write(0xFD401990, 0x000000F0U, ill12_val[0]);
+               if (lane1_active == 1)
+                       Xil_Out32(0xFD405924, ill1_val[1]);
+               if (lane1_active == 1)
+                       psu_mask_write(0xFD405990, 0x000000F0U, ill12_val[1]);
+               if (lane2_active == 1)
+                       Xil_Out32(0xFD409924, ill1_val[2]);
+               if (lane2_active == 1)
+                       psu_mask_write(0xFD409990, 0x000000F0U, ill12_val[2]);
+               if (lane3_active == 1)
+                       Xil_Out32(0xFD40D924, ill1_val[3]);
+               if (lane3_active == 1)
+                       psu_mask_write(0xFD40D990, 0x000000F0U, ill12_val[3]);
+       }
+       if (gen2_calib == 1) {
+               if (lane0_active == 1)
+                       Xil_Out32(0xFD401928, ill1_val[0]);
+               if (lane0_active == 1)
+                       psu_mask_write(0xFD401990, 0x0000000FU, ill12_val[0]);
+               if (lane1_active == 1)
+                       Xil_Out32(0xFD405928, ill1_val[1]);
+               if (lane1_active == 1)
+                       psu_mask_write(0xFD405990, 0x0000000FU, ill12_val[1]);
+               if (lane2_active == 1)
+                       Xil_Out32(0xFD409928, ill1_val[2]);
+               if (lane2_active == 1)
+                       psu_mask_write(0xFD409990, 0x0000000FU, ill12_val[2]);
+               if (lane3_active == 1)
+                       Xil_Out32(0xFD40D928, ill1_val[3]);
+               if (lane3_active == 1)
+                       psu_mask_write(0xFD40D990, 0x0000000FU, ill12_val[3]);
+       }
+
+       if (lane0_active == 1)
+               psu_mask_write(0xFD401018, 0x00000030U, 0x00000000U);
+       if (lane1_active == 1)
+               psu_mask_write(0xFD405018, 0x00000030U, 0x00000000U);
+       if (lane2_active == 1)
+               psu_mask_write(0xFD409018, 0x00000030U, 0x00000000U);
+       if (lane3_active == 1)
+               psu_mask_write(0xFD40D018, 0x00000030U, 0x00000000U);
+
+       Xil_Out32(0xFD410098, 0);
+       if (lane0_active == 1) {
+               Xil_Out32(0xFD403004, 0);
+               Xil_Out32(0xFD403008, 0);
+               Xil_Out32(0xFD40300C, 0);
+               Xil_Out32(0xFD403010, 0);
+               Xil_Out32(0xFD403014, 0);
+               Xil_Out32(0xFD403018, 0);
+               Xil_Out32(0xFD40301C, 0);
+               Xil_Out32(0xFD403020, 0);
+               Xil_Out32(0xFD403024, 0);
+               Xil_Out32(0xFD403028, 0);
+               Xil_Out32(0xFD40302C, 0);
+               Xil_Out32(0xFD403030, 0);
+               Xil_Out32(0xFD403034, 0);
+               Xil_Out32(0xFD403038, 0);
+               Xil_Out32(0xFD40303C, 0);
+               Xil_Out32(0xFD403040, 0);
+               Xil_Out32(0xFD403044, 0);
+               Xil_Out32(0xFD403048, 0);
+               Xil_Out32(0xFD40304C, 0);
+               Xil_Out32(0xFD403050, 0);
+               Xil_Out32(0xFD403054, 0);
+               Xil_Out32(0xFD403058, 0);
+               Xil_Out32(0xFD403068, 1);
+               Xil_Out32(0xFD40306C, 0);
+               Xil_Out32(0xFD4010AC, 0);
+               psu_mask_write(0xFD410044, 0x00000003U, 0x00000001U);
+               psu_mask_write(0xFD410040, 0x00000003U, 0x00000001U);
+               psu_mask_write(0xFD410038, 0x00000007U, 0x00000000U);
+       }
+       if (lane1_active == 1) {
+               Xil_Out32(0xFD407004, 0);
+               Xil_Out32(0xFD407008, 0);
+               Xil_Out32(0xFD40700C, 0);
+               Xil_Out32(0xFD407010, 0);
+               Xil_Out32(0xFD407014, 0);
+               Xil_Out32(0xFD407018, 0);
+               Xil_Out32(0xFD40701C, 0);
+               Xil_Out32(0xFD407020, 0);
+               Xil_Out32(0xFD407024, 0);
+               Xil_Out32(0xFD407028, 0);
+               Xil_Out32(0xFD40702C, 0);
+               Xil_Out32(0xFD407030, 0);
+               Xil_Out32(0xFD407034, 0);
+               Xil_Out32(0xFD407038, 0);
+               Xil_Out32(0xFD40703C, 0);
+               Xil_Out32(0xFD407040, 0);
+               Xil_Out32(0xFD407044, 0);
+               Xil_Out32(0xFD407048, 0);
+               Xil_Out32(0xFD40704C, 0);
+               Xil_Out32(0xFD407050, 0);
+               Xil_Out32(0xFD407054, 0);
+               Xil_Out32(0xFD407058, 0);
+               Xil_Out32(0xFD407068, 1);
+               Xil_Out32(0xFD40706C, 0);
+               Xil_Out32(0xFD4050AC, 0);
+               psu_mask_write(0xFD410044, 0x0000000CU, 0x00000004U);
+               psu_mask_write(0xFD410040, 0x0000000CU, 0x00000004U);
+               psu_mask_write(0xFD410038, 0x00000070U, 0x00000000U);
+       }
+       if (lane2_active == 1) {
+               Xil_Out32(0xFD40B004, 0);
+               Xil_Out32(0xFD40B008, 0);
+               Xil_Out32(0xFD40B00C, 0);
+               Xil_Out32(0xFD40B010, 0);
+               Xil_Out32(0xFD40B014, 0);
+               Xil_Out32(0xFD40B018, 0);
+               Xil_Out32(0xFD40B01C, 0);
+               Xil_Out32(0xFD40B020, 0);
+               Xil_Out32(0xFD40B024, 0);
+               Xil_Out32(0xFD40B028, 0);
+               Xil_Out32(0xFD40B02C, 0);
+               Xil_Out32(0xFD40B030, 0);
+               Xil_Out32(0xFD40B034, 0);
+               Xil_Out32(0xFD40B038, 0);
+               Xil_Out32(0xFD40B03C, 0);
+               Xil_Out32(0xFD40B040, 0);
+               Xil_Out32(0xFD40B044, 0);
+               Xil_Out32(0xFD40B048, 0);
+               Xil_Out32(0xFD40B04C, 0);
+               Xil_Out32(0xFD40B050, 0);
+               Xil_Out32(0xFD40B054, 0);
+               Xil_Out32(0xFD40B058, 0);
+               Xil_Out32(0xFD40B068, 1);
+               Xil_Out32(0xFD40B06C, 0);
+               Xil_Out32(0xFD4090AC, 0);
+               psu_mask_write(0xFD410044, 0x00000030U, 0x00000010U);
+               psu_mask_write(0xFD410040, 0x00000030U, 0x00000010U);
+               psu_mask_write(0xFD41003C, 0x00000007U, 0x00000000U);
+       }
+       if (lane3_active == 1) {
+               Xil_Out32(0xFD40F004, 0);
+               Xil_Out32(0xFD40F008, 0);
+               Xil_Out32(0xFD40F00C, 0);
+               Xil_Out32(0xFD40F010, 0);
+               Xil_Out32(0xFD40F014, 0);
+               Xil_Out32(0xFD40F018, 0);
+               Xil_Out32(0xFD40F01C, 0);
+               Xil_Out32(0xFD40F020, 0);
+               Xil_Out32(0xFD40F024, 0);
+               Xil_Out32(0xFD40F028, 0);
+               Xil_Out32(0xFD40F02C, 0);
+               Xil_Out32(0xFD40F030, 0);
+               Xil_Out32(0xFD40F034, 0);
+               Xil_Out32(0xFD40F038, 0);
+               Xil_Out32(0xFD40F03C, 0);
+               Xil_Out32(0xFD40F040, 0);
+               Xil_Out32(0xFD40F044, 0);
+               Xil_Out32(0xFD40F048, 0);
+               Xil_Out32(0xFD40F04C, 0);
+               Xil_Out32(0xFD40F050, 0);
+               Xil_Out32(0xFD40F054, 0);
+               Xil_Out32(0xFD40F058, 0);
+               Xil_Out32(0xFD40F068, 1);
+               Xil_Out32(0xFD40F06C, 0);
+               Xil_Out32(0xFD40D0AC, 0);
+               psu_mask_write(0xFD410044, 0x000000C0U, 0x00000040U);
+               psu_mask_write(0xFD410040, 0x000000C0U, 0x00000040U);
+               psu_mask_write(0xFD41003C, 0x00000070U, 0x00000000U);
+       }
+       return 1;
+}
+
+static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate,
+                          u32 lane2_protocol, u32 lane2_rate,
+                          u32 lane1_protocol, u32 lane1_rate,
+                          u32 lane0_protocol, u32 lane0_rate)
+{
+       unsigned int rdata = 0;
+       unsigned int sata_gen2 = 1;
+       unsigned int temp_ill12 = 0;
+       unsigned int temp_PLL_REF_SEL_OFFSET;
+       unsigned int temp_TM_IQ_ILL1;
+       unsigned int temp_TM_E_ILL1;
+       unsigned int temp_tx_dig_tm_61;
+       unsigned int temp_tm_dig_6;
+       unsigned int temp_pll_fbdiv_frac_3_msb_offset;
+
+       if (lane0_protocol == 2 || lane0_protocol == 1) {
+               Xil_Out32(0xFD401910, 0xF3);
+               Xil_Out32(0xFD40193C, 0xF3);
+               Xil_Out32(0xFD401914, 0xF3);
+               Xil_Out32(0xFD401940, 0xF3);
+       }
+       if (lane1_protocol == 2 || lane1_protocol == 1) {
+               Xil_Out32(0xFD405910, 0xF3);
+               Xil_Out32(0xFD40593C, 0xF3);
+               Xil_Out32(0xFD405914, 0xF3);
+               Xil_Out32(0xFD405940, 0xF3);
+       }
+       if (lane2_protocol == 2 || lane2_protocol == 1) {
+               Xil_Out32(0xFD409910, 0xF3);
+               Xil_Out32(0xFD40993C, 0xF3);
+               Xil_Out32(0xFD409914, 0xF3);
+               Xil_Out32(0xFD409940, 0xF3);
+       }
+       if (lane3_protocol == 2 || lane3_protocol == 1) {
+               Xil_Out32(0xFD40D910, 0xF3);
+               Xil_Out32(0xFD40D93C, 0xF3);
+               Xil_Out32(0xFD40D914, 0xF3);
+               Xil_Out32(0xFD40D940, 0xF3);
+       }
+
+       if (sata_gen2 == 1) {
+               if (lane0_protocol == 2) {
+                       temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD402360);
+                       Xil_Out32(0xFD402360, 0x0);
+                       temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410000);
+                       psu_mask_write(0xFD410000, 0x0000001FU, 0x0000000DU);
+                       temp_TM_IQ_ILL1 = Xil_In32(0xFD4018F8);
+                       temp_TM_E_ILL1 = Xil_In32(0xFD401924);
+                       Xil_Out32(0xFD4018F8, 0x78);
+                       temp_tx_dig_tm_61 = Xil_In32(0xFD4000F4);
+                       temp_tm_dig_6 = Xil_In32(0xFD40106C);
+                       psu_mask_write(0xFD4000F4, 0x0000000BU, 0x00000000U);
+                       psu_mask_write(0xFD40106C, 0x0000000FU, 0x00000000U);
+                       temp_ill12 = Xil_In32(0xFD401990) & 0xF0;
+
+                       serdes_illcalib_pcie_gen1(0, 0, 0, 0, 0, 0, 1, 0, 0);
+
+                       Xil_Out32(0xFD402360, temp_pll_fbdiv_frac_3_msb_offset);
+                       Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+                       Xil_Out32(0xFD4018F8, temp_TM_IQ_ILL1);
+                       Xil_Out32(0xFD4000F4, temp_tx_dig_tm_61);
+                       Xil_Out32(0xFD40106C, temp_tm_dig_6);
+                       Xil_Out32(0xFD401928, Xil_In32(0xFD401924));
+                       temp_ill12 =
+                           temp_ill12 | (Xil_In32(0xFD401990) >> 4 & 0xF);
+                       Xil_Out32(0xFD401990, temp_ill12);
+                       Xil_Out32(0xFD401924, temp_TM_E_ILL1);
+               }
+               if (lane1_protocol == 2) {
+                       temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD406360);
+                       Xil_Out32(0xFD406360, 0x0);
+                       temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410004);
+                       psu_mask_write(0xFD410004, 0x0000001FU, 0x0000000DU);
+                       temp_TM_IQ_ILL1 = Xil_In32(0xFD4058F8);
+                       temp_TM_E_ILL1 = Xil_In32(0xFD405924);
+                       Xil_Out32(0xFD4058F8, 0x78);
+                       temp_tx_dig_tm_61 = Xil_In32(0xFD4040F4);
+                       temp_tm_dig_6 = Xil_In32(0xFD40506C);
+                       psu_mask_write(0xFD4040F4, 0x0000000BU, 0x00000000U);
+                       psu_mask_write(0xFD40506C, 0x0000000FU, 0x00000000U);
+                       temp_ill12 = Xil_In32(0xFD405990) & 0xF0;
+
+                       serdes_illcalib_pcie_gen1(0, 0, 0, 0, 1, 0, 0, 0, 0);
+
+                       Xil_Out32(0xFD406360, temp_pll_fbdiv_frac_3_msb_offset);
+                       Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+                       Xil_Out32(0xFD4058F8, temp_TM_IQ_ILL1);
+                       Xil_Out32(0xFD4040F4, temp_tx_dig_tm_61);
+                       Xil_Out32(0xFD40506C, temp_tm_dig_6);
+                       Xil_Out32(0xFD405928, Xil_In32(0xFD405924));
+                       temp_ill12 =
+                           temp_ill12 | (Xil_In32(0xFD405990) >> 4 & 0xF);
+                       Xil_Out32(0xFD405990, temp_ill12);
+                       Xil_Out32(0xFD405924, temp_TM_E_ILL1);
+               }
+               if (lane2_protocol == 2) {
+                       temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD40A360);
+                       Xil_Out32(0xFD40A360, 0x0);
+                       temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410008);
+                       psu_mask_write(0xFD410008, 0x0000001FU, 0x0000000DU);
+                       temp_TM_IQ_ILL1 = Xil_In32(0xFD4098F8);
+                       temp_TM_E_ILL1 = Xil_In32(0xFD409924);
+                       Xil_Out32(0xFD4098F8, 0x78);
+                       temp_tx_dig_tm_61 = Xil_In32(0xFD4080F4);
+                       temp_tm_dig_6 = Xil_In32(0xFD40906C);
+                       psu_mask_write(0xFD4080F4, 0x0000000BU, 0x00000000U);
+                       psu_mask_write(0xFD40906C, 0x0000000FU, 0x00000000U);
+                       temp_ill12 = Xil_In32(0xFD409990) & 0xF0;
+
+                       serdes_illcalib_pcie_gen1(0, 0, 1, 0, 0, 0, 0, 0, 0);
+
+                       Xil_Out32(0xFD40A360, temp_pll_fbdiv_frac_3_msb_offset);
+                       Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+                       Xil_Out32(0xFD4098F8, temp_TM_IQ_ILL1);
+                       Xil_Out32(0xFD4080F4, temp_tx_dig_tm_61);
+                       Xil_Out32(0xFD40906C, temp_tm_dig_6);
+                       Xil_Out32(0xFD409928, Xil_In32(0xFD409924));
+                       temp_ill12 =
+                           temp_ill12 | (Xil_In32(0xFD409990) >> 4 & 0xF);
+                       Xil_Out32(0xFD409990, temp_ill12);
+                       Xil_Out32(0xFD409924, temp_TM_E_ILL1);
+               }
+               if (lane3_protocol == 2) {
+                       temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD40E360);
+                       Xil_Out32(0xFD40E360, 0x0);
+                       temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD41000C);
+                       psu_mask_write(0xFD41000C, 0x0000001FU, 0x0000000DU);
+                       temp_TM_IQ_ILL1 = Xil_In32(0xFD40D8F8);
+                       temp_TM_E_ILL1 = Xil_In32(0xFD40D924);
+                       Xil_Out32(0xFD40D8F8, 0x78);
+                       temp_tx_dig_tm_61 = Xil_In32(0xFD40C0F4);
+                       temp_tm_dig_6 = Xil_In32(0xFD40D06C);
+                       psu_mask_write(0xFD40C0F4, 0x0000000BU, 0x00000000U);
+                       psu_mask_write(0xFD40D06C, 0x0000000FU, 0x00000000U);
+                       temp_ill12 = Xil_In32(0xFD40D990) & 0xF0;
+
+                       serdes_illcalib_pcie_gen1(1, 0, 0, 0, 0, 0, 0, 0, 0);
+
+                       Xil_Out32(0xFD40E360, temp_pll_fbdiv_frac_3_msb_offset);
+                       Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+                       Xil_Out32(0xFD40D8F8, temp_TM_IQ_ILL1);
+                       Xil_Out32(0xFD40C0F4, temp_tx_dig_tm_61);
+                       Xil_Out32(0xFD40D06C, temp_tm_dig_6);
+                       Xil_Out32(0xFD40D928, Xil_In32(0xFD40D924));
+                       temp_ill12 =
+                           temp_ill12 | (Xil_In32(0xFD40D990) >> 4 & 0xF);
+                       Xil_Out32(0xFD40D990, temp_ill12);
+                       Xil_Out32(0xFD40D924, temp_TM_E_ILL1);
+               }
+               rdata = Xil_In32(0xFD410098);
+               rdata = (rdata & 0xDF);
+               Xil_Out32(0xFD410098, rdata);
+       }
+
+       if (lane0_protocol == 2 && lane0_rate == 3) {
+               psu_mask_write(0xFD40198C, 0x000000F0U, 0x00000020U);
+               psu_mask_write(0xFD40192C, 0x000000FFU, 0x00000094U);
+       }
+       if (lane1_protocol == 2 && lane1_rate == 3) {
+               psu_mask_write(0xFD40598C, 0x000000F0U, 0x00000020U);
+               psu_mask_write(0xFD40592C, 0x000000FFU, 0x00000094U);
+       }
+       if (lane2_protocol == 2 && lane2_rate == 3) {
+               psu_mask_write(0xFD40998C, 0x000000F0U, 0x00000020U);
+               psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000094U);
+       }
+       if (lane3_protocol == 2 && lane3_rate == 3) {
+               psu_mask_write(0xFD40D98C, 0x000000F0U, 0x00000020U);
+               psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000094U);
+       }
+
+       if (lane0_protocol == 1) {
+               if (lane0_rate == 0) {
+                       serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+                                                 lane2_protocol, lane2_rate,
+                                                 lane1_protocol, lane1_rate,
+                                                 lane0_protocol, 0, 0);
+               } else {
+                       serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+                                                 lane2_protocol, lane2_rate,
+                                                 lane1_protocol, lane1_rate,
+                                                 lane0_protocol, 0, 0);
+                       serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+                                                 lane2_protocol, lane2_rate,
+                                                 lane1_protocol, lane1_rate,
+                                                 lane0_protocol, lane0_rate,
+                                                 1);
+               }
+       }
+
+       if (lane0_protocol == 3)
+               Xil_Out32(0xFD401914, 0xF3);
+       if (lane0_protocol == 3)
+               Xil_Out32(0xFD401940, 0xF3);
+       if (lane0_protocol == 3)
+               Xil_Out32(0xFD401990, 0x20);
+       if (lane0_protocol == 3)
+               Xil_Out32(0xFD401924, 0x37);
+
+       if (lane1_protocol == 3)
+               Xil_Out32(0xFD405914, 0xF3);
+       if (lane1_protocol == 3)
+               Xil_Out32(0xFD405940, 0xF3);
+       if (lane1_protocol == 3)
+               Xil_Out32(0xFD405990, 0x20);
+       if (lane1_protocol == 3)
+               Xil_Out32(0xFD405924, 0x37);
+
+       if (lane2_protocol == 3)
+               Xil_Out32(0xFD409914, 0xF3);
+       if (lane2_protocol == 3)
+               Xil_Out32(0xFD409940, 0xF3);
+       if (lane2_protocol == 3)
+               Xil_Out32(0xFD409990, 0x20);
+       if (lane2_protocol == 3)
+               Xil_Out32(0xFD409924, 0x37);
+
+       if (lane3_protocol == 3)
+               Xil_Out32(0xFD40D914, 0xF3);
+       if (lane3_protocol == 3)
+               Xil_Out32(0xFD40D940, 0xF3);
+       if (lane3_protocol == 3)
+               Xil_Out32(0xFD40D990, 0x20);
+       if (lane3_protocol == 3)
+               Xil_Out32(0xFD40D924, 0x37);
+
+       return 1;
+}
+
+static int serdes_enb_coarse_saturation(void)
+{
+       Xil_Out32(0xFD402094, 0x00000010);
+       Xil_Out32(0xFD406094, 0x00000010);
+       Xil_Out32(0xFD40A094, 0x00000010);
+       Xil_Out32(0xFD40E094, 0x00000010);
+       return 1;
+}
+
+static int serdes_fixcal_code(void)
+{
+       int maskstatus = 1;
+       unsigned int rdata = 0;
+       unsigned int match_pmos_code[23];
+       unsigned int match_nmos_code[23];
+       unsigned int match_ical_code[7];
+       unsigned int match_rcal_code[7];
+       unsigned int p_code = 0;
+       unsigned int n_code = 0;
+       unsigned int i_code = 0;
+       unsigned int r_code = 0;
+       unsigned int repeat_count = 0;
+       unsigned int L3_TM_CALIB_DIG20 = 0;
+       unsigned int L3_TM_CALIB_DIG19 = 0;
+       unsigned int L3_TM_CALIB_DIG18 = 0;
+       unsigned int L3_TM_CALIB_DIG16 = 0;
+       unsigned int L3_TM_CALIB_DIG15 = 0;
+       unsigned int L3_TM_CALIB_DIG14 = 0;
+       int i = 0;
+       int count = 0;
+
+       rdata = Xil_In32(0xFD40289C);
+       rdata = rdata & ~0x03;
+       rdata = rdata | 0x1;
+       Xil_Out32(0xFD40289C, rdata);
+
+       do {
+               if (count == 1100000)
+                       break;
+               rdata = Xil_In32(0xFD402B1C);
+               count++;
+       } while ((rdata & 0x0000000E) != 0x0000000E);
+
+       for (i = 0; i < 23; i++) {
+               match_pmos_code[i] = 0;
+               match_nmos_code[i] = 0;
+       }
+       for (i = 0; i < 7; i++) {
+               match_ical_code[i] = 0;
+               match_rcal_code[i] = 0;
+       }
+
+       do {
+               Xil_Out32(0xFD410010, 0x00000000);
+               Xil_Out32(0xFD410014, 0x00000000);
+
+               Xil_Out32(0xFD410010, 0x00000001);
+               Xil_Out32(0xFD410014, 0x00000000);
+
+               maskstatus = mask_poll(0xFD40EF14, 0x2);
+               if (maskstatus == 0) {
+                       xil_printf("#SERDES initialization timed out\n\r");
+                       return maskstatus;
+               }
+
+               p_code = mask_read(0xFD40EF18, 0xFFFFFFFF);
+               n_code = mask_read(0xFD40EF1C, 0xFFFFFFFF);
+               ;
+               i_code = mask_read(0xFD40EF24, 0xFFFFFFFF);
+               r_code = mask_read(0xFD40EF28, 0xFFFFFFFF);
+               ;
+
+               if (p_code >= 0x26 && p_code <= 0x3C)
+                       match_pmos_code[p_code - 0x26] += 1;
+
+               if (n_code >= 0x26 && n_code <= 0x3C)
+                       match_nmos_code[n_code - 0x26] += 1;
+
+               if (i_code >= 0xC && i_code <= 0x12)
+                       match_ical_code[i_code - 0xc] += 1;
+
+               if (r_code >= 0x6 && r_code <= 0xC)
+                       match_rcal_code[r_code - 0x6] += 1;
+
+       } while (repeat_count++ < 10);
+
+       for (i = 0; i < 23; i++) {
+               if (match_pmos_code[i] >= match_pmos_code[0]) {
+                       match_pmos_code[0] = match_pmos_code[i];
+                       p_code = 0x26 + i;
+               }
+               if (match_nmos_code[i] >= match_nmos_code[0]) {
+                       match_nmos_code[0] = match_nmos_code[i];
+                       n_code = 0x26 + i;
+               }
+       }
+
+       for (i = 0; i < 7; i++) {
+               if (match_ical_code[i] >= match_ical_code[0]) {
+                       match_ical_code[0] = match_ical_code[i];
+                       i_code = 0xC + i;
+               }
+               if (match_rcal_code[i] >= match_rcal_code[0]) {
+                       match_rcal_code[0] = match_rcal_code[i];
+                       r_code = 0x6 + i;
+               }
+       }
+
+       L3_TM_CALIB_DIG20 = mask_read(0xFD40EC50, 0xFFFFFFF0);
+       L3_TM_CALIB_DIG20 = L3_TM_CALIB_DIG20 | 0x8 | ((p_code >> 2) & 0x7);
+
+       L3_TM_CALIB_DIG19 = mask_read(0xFD40EC4C, 0xFFFFFF18);
+       L3_TM_CALIB_DIG19 = L3_TM_CALIB_DIG19 | ((p_code & 0x3) << 6)
+           | 0x20 | 0x4 | ((n_code >> 3) & 0x3);
+
+       L3_TM_CALIB_DIG18 = mask_read(0xFD40EC48, 0xFFFFFF0F);
+       L3_TM_CALIB_DIG18 = L3_TM_CALIB_DIG18 | ((n_code & 0x7) << 5) | 0x10;
+
+       L3_TM_CALIB_DIG16 = mask_read(0xFD40EC40, 0xFFFFFFF8);
+       L3_TM_CALIB_DIG16 = L3_TM_CALIB_DIG16 | ((r_code >> 1) & 0x7);
+
+       L3_TM_CALIB_DIG15 = mask_read(0xFD40EC3C, 0xFFFFFF30);
+       L3_TM_CALIB_DIG15 = L3_TM_CALIB_DIG15 | ((r_code & 0x1) << 7)
+           | 0x40 | 0x8 | ((i_code >> 1) & 0x7);
+
+       L3_TM_CALIB_DIG14 = mask_read(0xFD40EC38, 0xFFFFFF3F);
+       L3_TM_CALIB_DIG14 = L3_TM_CALIB_DIG14 | ((i_code & 0x1) << 7) | 0x40;
+
+       Xil_Out32(0xFD40EC50, L3_TM_CALIB_DIG20);
+       Xil_Out32(0xFD40EC4C, L3_TM_CALIB_DIG19);
+       Xil_Out32(0xFD40EC48, L3_TM_CALIB_DIG18);
+       Xil_Out32(0xFD40EC40, L3_TM_CALIB_DIG16);
+       Xil_Out32(0xFD40EC3C, L3_TM_CALIB_DIG15);
+       Xil_Out32(0xFD40EC38, L3_TM_CALIB_DIG14);
+       return maskstatus;
+}
+
+static int init_serdes(void)
+{
+       int status = 1;
+
+       status &= psu_resetin_init_data();
+
+       status &= serdes_fixcal_code();
+       status &= serdes_enb_coarse_saturation();
+
+       status &= psu_serdes_init_data();
+       status &= psu_resetout_init_data();
+
+       return status;
+}
+
+static void init_peripheral(void)
+{
+       psu_mask_write(0xFD5F0018, 0x8000001FU, 0x8000001FU);
+}
+
+int psu_init(void)
+{
+       int status = 1;
+
+       status &= psu_mio_init_data();
+       status &= psu_peripherals_pre_init_data();
+       status &= psu_pll_init_data();
+       status &= psu_clock_init_data();
+       status &= psu_ddr_init_data();
+       status &= psu_ddr_phybringup_data();
+       status &= psu_peripherals_init_data();
+       status &= init_serdes();
+       init_peripheral();
+
+       status &= psu_afi_config();
+       psu_ddr_qos_init_data();
+
+       if (status == 0)
+               return 1;
+       return 0;
+}
diff --git a/board/xilinx/zynqmp/zynqmp-zcu216-revA/psu_init_gpl.c b/board/xilinx/zynqmp/zynqmp-zcu216-revA/psu_init_gpl.c
new file mode 100644 (file)
index 0000000..fc3605d
--- /dev/null
@@ -0,0 +1,1882 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (c) Copyright 2015 Xilinx, Inc. All rights reserved.
+ */
+
+#include <asm/arch/psu_init_gpl.h>
+#include <xil_io.h>
+
+static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate,
+                          u32 lane2_protocol, u32 lane2_rate,
+                          u32 lane1_protocol, u32 lane1_rate,
+                          u32 lane0_protocol, u32 lane0_rate);
+
+static unsigned long psu_pll_init_data(void)
+{
+       psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4B0C82U);
+       psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00015A00U);
+       psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000000U);
+       mask_poll(0xFF5E0040, 0x00000002U);
+       psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012300U);
+       psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E4B0C82U);
+       psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00015A00U);
+       psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000000U);
+       mask_poll(0xFF5E0040, 0x00000001U);
+       psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFF5E0044, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFD1A0024, 0xFE7FEDEFU, 0x7E4B0C62U);
+       psu_mask_write(0xFD1A0020, 0x00717F00U, 0x00014800U);
+       psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000000U);
+       mask_poll(0xFD1A0044, 0x00000001U);
+       psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD1A0048, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFD1A0030, 0xFE7FEDEFU, 0x7E4B0C62U);
+       psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00013F00U);
+       psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000000U);
+       mask_poll(0xFD1A0044, 0x00000002U);
+       psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD1A004C, 0x00003F00U, 0x00000200U);
+       psu_mask_write(0xFD1A003C, 0xFE7FEDEFU, 0x7E4B0C82U);
+       psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00015A00U);
+       psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000000U);
+       mask_poll(0xFD1A0044, 0x00000004U);
+       psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000300U);
+
+       return 1;
+}
+
+static unsigned long psu_clock_init_data(void)
+{
+       psu_mask_write(0xFF5E005C, 0x063F3F07U, 0x06010C00U);
+       psu_mask_write(0xFF5E0100, 0x013F3F07U, 0x01010600U);
+       psu_mask_write(0xFF5E0060, 0x023F3F07U, 0x02010600U);
+       psu_mask_write(0xFF5E004C, 0x023F3F07U, 0x02031900U);
+       psu_mask_write(0xFF5E0068, 0x013F3F07U, 0x01010C00U);
+       psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010800U);
+       psu_mask_write(0xFF18030C, 0x00020000U, 0x00000000U);
+       psu_mask_write(0xFF5E0074, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0120, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0124, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0090, 0x01003F07U, 0x01000302U);
+       psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000602U);
+       psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000800U);
+       psu_mask_write(0xFF5E00A8, 0x01003F07U, 0x01000302U);
+       psu_mask_write(0xFF5E00AC, 0x01003F07U, 0x01000F02U);
+       psu_mask_write(0xFF5E00B0, 0x01003F07U, 0x01000602U);
+       psu_mask_write(0xFF5E00B8, 0x01003F07U, 0x01000302U);
+       psu_mask_write(0xFF5E00C0, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01011E02U);
+       psu_mask_write(0xFF5E0104, 0x00000007U, 0x00000000U);
+       psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000F00U);
+       psu_mask_write(0xFD1A00A0, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A0060, 0x03003F07U, 0x03000100U);
+       psu_mask_write(0xFD1A0068, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000200U);
+       psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000203U);
+       psu_mask_write(0xFD1A00C4, 0x01003F07U, 0x01000502U);
+       psu_mask_write(0xFD1A00F8, 0x00003F07U, 0x00000200U);
+       psu_mask_write(0xFF180380, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD610100, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFF180300, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFF410050, 0x00000001U, 0x00000000U);
+
+       return 1;
+}
+
+static unsigned long psu_ddr_init_data(void)
+{
+       psu_mask_write(0xFD1A0108, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD070000, 0xE30FBE3DU, 0x81040010U);
+       psu_mask_write(0xFD070010, 0x8000F03FU, 0x00000030U);
+       psu_mask_write(0xFD070020, 0x000003F3U, 0x00000200U);
+       psu_mask_write(0xFD070024, 0xFFFFFFFFU, 0x00800000U);
+       psu_mask_write(0xFD070030, 0x0000007FU, 0x00000000U);
+       psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00408210U);
+       psu_mask_write(0xFD070050, 0x00F1F1F4U, 0x00210000U);
+       psu_mask_write(0xFD070054, 0x0FFF0FFFU, 0x00000000U);
+       psu_mask_write(0xFD070060, 0x00000073U, 0x00000001U);
+       psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x007F80B8U);
+       psu_mask_write(0xFD070070, 0x00000017U, 0x00000010U);
+       psu_mask_write(0xFD070074, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD0700C4, 0x3F000391U, 0x10000200U);
+       psu_mask_write(0xFD0700C8, 0x01FF1F3FU, 0x0040051FU);
+       psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00020102U);
+       psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x00020000U);
+       psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00002205U);
+       psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x07300301U);
+       psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00100200U);
+       psu_mask_write(0xFD0700E4, 0x00FF03FFU, 0x00210004U);
+       psu_mask_write(0xFD0700E8, 0xFFFFFFFFU, 0x000006C0U);
+       psu_mask_write(0xFD0700EC, 0xFFFF0000U, 0x08190000U);
+       psu_mask_write(0xFD0700F0, 0x0000003FU, 0x00000010U);
+       psu_mask_write(0xFD0700F4, 0x00000FFFU, 0x0000066FU);
+       psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x0F102311U);
+       psu_mask_write(0xFD070104, 0x001F1F7FU, 0x00040419U);
+       psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x0608070CU);
+       psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x0050400CU);
+       psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x08030409U);
+       psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x06060403U);
+       psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010004U);
+       psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000606U);
+       psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x04040D07U);
+       psu_mask_write(0xFD070124, 0x40070F3FU, 0x00020309U);
+       psu_mask_write(0xFD07012C, 0x7F1F031FU, 0x1207010EU);
+       psu_mask_write(0xFD070130, 0x00030F1FU, 0x00020608U);
+       psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x81000040U);
+       psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x0201908AU);
+       psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x048B8208U);
+       psu_mask_write(0xFD070194, 0xF31F0F0FU, 0x00030304U);
+       psu_mask_write(0xFD070198, 0x0FF1F1F1U, 0x07000101U);
+       psu_mask_write(0xFD07019C, 0x000000F1U, 0x00000021U);
+       psu_mask_write(0xFD0701A0, 0xC3FF03FFU, 0x00400003U);
+       psu_mask_write(0xFD0701A4, 0x00FF00FFU, 0x00C800FFU);
+       psu_mask_write(0xFD0701B0, 0x00000007U, 0x00000000U);
+       psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000906U);
+       psu_mask_write(0xFD0701C0, 0x00000007U, 0x00000001U);
+       psu_mask_write(0xFD070200, 0x0000001FU, 0x0000001FU);
+       psu_mask_write(0xFD070204, 0x001F1F1FU, 0x001F0909U);
+       psu_mask_write(0xFD070208, 0x0F0F0F0FU, 0x01010100U);
+       psu_mask_write(0xFD07020C, 0x0F0F0F0FU, 0x01010101U);
+       psu_mask_write(0xFD070210, 0x00000F0FU, 0x00000F0FU);
+       psu_mask_write(0xFD070214, 0x0F0F0F0FU, 0x070F0707U);
+       psu_mask_write(0xFD070218, 0x8F0F0F0FU, 0x07070707U);
+       psu_mask_write(0xFD07021C, 0x00000F0FU, 0x00000F0FU);
+       psu_mask_write(0xFD070220, 0x00001F1FU, 0x00001F01U);
+       psu_mask_write(0xFD070224, 0x0F0F0F0FU, 0x07070707U);
+       psu_mask_write(0xFD070228, 0x0F0F0F0FU, 0x07070707U);
+       psu_mask_write(0xFD07022C, 0x0000000FU, 0x00000007U);
+       psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x0600060CU);
+       psu_mask_write(0xFD070244, 0x00003333U, 0x00000001U);
+       psu_mask_write(0xFD070250, 0x7FFF3F07U, 0x01002001U);
+       psu_mask_write(0xFD070264, 0xFF00FFFFU, 0x08000040U);
+       psu_mask_write(0xFD07026C, 0xFF00FFFFU, 0x08000040U);
+       psu_mask_write(0xFD070280, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD070284, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD070288, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD07028C, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD070290, 0x0000FFFFU, 0x00000000U);
+       psu_mask_write(0xFD070294, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD070300, 0x00000011U, 0x00000000U);
+       psu_mask_write(0xFD07030C, 0x80000033U, 0x00000000U);
+       psu_mask_write(0xFD070320, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFD070400, 0x00000111U, 0x00000001U);
+       psu_mask_write(0xFD070404, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070408, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070490, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD070494, 0x0033000FU, 0x0020000BU);
+       psu_mask_write(0xFD070498, 0x07FF07FFU, 0x00000000U);
+       psu_mask_write(0xFD0704B4, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD0704B8, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070540, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD070544, 0x03330F0FU, 0x02000B03U);
+       psu_mask_write(0xFD070548, 0x07FF07FFU, 0x00000000U);
+       psu_mask_write(0xFD070564, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070568, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD0705F0, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD0705F4, 0x03330F0FU, 0x02000B03U);
+       psu_mask_write(0xFD0705F8, 0x07FF07FFU, 0x00000000U);
+       psu_mask_write(0xFD070614, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070618, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD0706A0, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD0706A4, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD0706A8, 0x07FF07FFU, 0x0000004FU);
+       psu_mask_write(0xFD0706AC, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD0706B0, 0x000007FFU, 0x0000004FU);
+       psu_mask_write(0xFD0706C4, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD0706C8, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070750, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD070754, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD070758, 0x07FF07FFU, 0x0000004FU);
+       psu_mask_write(0xFD07075C, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD070760, 0x000007FFU, 0x0000004FU);
+       psu_mask_write(0xFD070774, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070778, 0x000073FFU, 0x0000200FU);
+       psu_mask_write(0xFD070800, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD070804, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD070808, 0x07FF07FFU, 0x0000004FU);
+       psu_mask_write(0xFD07080C, 0x0033000FU, 0x00100003U);
+       psu_mask_write(0xFD070810, 0x000007FFU, 0x0000004FU);
+       psu_mask_write(0xFD070F04, 0x000001FFU, 0x00000000U);
+       psu_mask_write(0xFD070F08, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD070F0C, 0x000001FFU, 0x00000010U);
+       psu_mask_write(0xFD070F10, 0x000000FFU, 0x0000000FU);
+       psu_mask_write(0xFD072190, 0x1FBFBF3FU, 0x07828002U);
+       psu_mask_write(0xFD1A0108, 0x0000000CU, 0x00000000U);
+       psu_mask_write(0xFD080010, 0xFFFFFFFFU, 0x07001E00U);
+       psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F0FC00U);
+       psu_mask_write(0xFD08001C, 0xFFFFFFFFU, 0x55AA5480U);
+       psu_mask_write(0xFD080024, 0xFFFFFFFFU, 0x010100F4U);
+       psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x41A20D10U);
+       psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0xCD141275U);
+       psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04161U);
+       psu_mask_write(0xFD0800C0, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000E3U);
+       psu_mask_write(0xFD080100, 0xFFFFFFFFU, 0x0800040CU);
+       psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x07220F08U);
+       psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x28200008U);
+       psu_mask_write(0xFD080118, 0xFFFFFFFFU, 0x000F0300U);
+       psu_mask_write(0xFD08011C, 0xFFFFFFFFU, 0x83000800U);
+       psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x01702B07U);
+       psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00310F08U);
+       psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000B0FU);
+       psu_mask_write(0xFD080140, 0xFFFFFFFFU, 0x08400020U);
+       psu_mask_write(0xFD080144, 0xFFFFFFFFU, 0x00000C80U);
+       psu_mask_write(0xFD080150, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080154, 0xFFFFFFFFU, 0x00000200U);
+       psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000630U);
+       psu_mask_write(0xFD080184, 0xFFFFFFFFU, 0x00000301U);
+       psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000010U);
+       psu_mask_write(0xFD08018C, 0xFFFFFFFFU, 0x00000200U);
+       psu_mask_write(0xFD080190, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080194, 0xFFFFFFFFU, 0x000006C0U);
+       psu_mask_write(0xFD080198, 0xFFFFFFFFU, 0x00000819U);
+       psu_mask_write(0xFD0801AC, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD0801B0, 0xFFFFFFFFU, 0x0000004DU);
+       psu_mask_write(0xFD0801B4, 0xFFFFFFFFU, 0x00000008U);
+       psu_mask_write(0xFD0801B8, 0xFFFFFFFFU, 0x0000004DU);
+       psu_mask_write(0xFD0801D8, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080200, 0xFFFFFFFFU, 0x800091C7U);
+       psu_mask_write(0xFD080204, 0xFFFFFFFFU, 0x00010236U);
+       psu_mask_write(0xFD080240, 0xFFFFFFFFU, 0x00141054U);
+       psu_mask_write(0xFD080250, 0xFFFFFFFFU, 0x00088000U);
+       psu_mask_write(0xFD080414, 0xFFFFFFFFU, 0x12341000U);
+       psu_mask_write(0xFD0804F4, 0xFFFFFFFFU, 0x00000005U);
+       psu_mask_write(0xFD080500, 0xFFFFFFFFU, 0x30000028U);
+       psu_mask_write(0xFD080508, 0xFFFFFFFFU, 0x0A000000U);
+       psu_mask_write(0xFD08050C, 0xFFFFFFFFU, 0x00000009U);
+       psu_mask_write(0xFD080510, 0xFFFFFFFFU, 0x0A000000U);
+       psu_mask_write(0xFD080520, 0xFFFFFFFFU, 0x0300B0CEU);
+       psu_mask_write(0xFD080528, 0xFFFFFFFFU, 0xF9032019U);
+       psu_mask_write(0xFD08052C, 0xFFFFFFFFU, 0x07F001E3U);
+       psu_mask_write(0xFD080544, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080548, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080558, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD08055C, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080560, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080564, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080680, 0xFFFFFFFFU, 0x008A8A58U);
+       psu_mask_write(0xFD080684, 0xFFFFFFFFU, 0x000079DDU);
+       psu_mask_write(0xFD080694, 0xFFFFFFFFU, 0x01E10210U);
+       psu_mask_write(0xFD080698, 0xFFFFFFFFU, 0x01E10000U);
+       psu_mask_write(0xFD0806A4, 0xFFFFFFFFU, 0x00087BDBU);
+       psu_mask_write(0xFD080700, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080704, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD08070C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080710, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080714, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080718, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080800, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080804, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD08080C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080810, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080814, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080818, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080900, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080904, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD08090C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080910, 0xFFFFFFFFU, 0x0E00B004U);
+       psu_mask_write(0xFD080914, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080918, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080A00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080A04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD080A0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080A10, 0xFFFFFFFFU, 0x0E00B004U);
+       psu_mask_write(0xFD080A14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080A18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080B00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080B04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD080B08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080B0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080B10, 0xFFFFFFFFU, 0x0E00B004U);
+       psu_mask_write(0xFD080B14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080B18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080C00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080C04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD080C08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080C0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080C10, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080C14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080C18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080D00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080D04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD080D08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080D0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080D10, 0xFFFFFFFFU, 0x0E00B004U);
+       psu_mask_write(0xFD080D14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080D18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080E00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080E04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD080E08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080E0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080E10, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080E14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080E18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080F00, 0xFFFFFFFFU, 0x80803660U);
+       psu_mask_write(0xFD080F04, 0xFFFFFFFFU, 0x55556000U);
+       psu_mask_write(0xFD080F08, 0xFFFFFFFFU, 0xAAAAAAAAU);
+       psu_mask_write(0xFD080F0C, 0xFFFFFFFFU, 0x0029A4A4U);
+       psu_mask_write(0xFD080F10, 0xFFFFFFFFU, 0x0C00B000U);
+       psu_mask_write(0xFD080F14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080F18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD081400, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD08141C, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD08142C, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD081430, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD081440, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD08145C, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD08146C, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD081470, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD081480, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD08149C, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD0814AC, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD0814B0, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD0814C0, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD0814DC, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD0814EC, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD0814F0, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD081500, 0xFFFFFFFFU, 0x15019FFEU);
+       psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x21100000U);
+       psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01266300U);
+       psu_mask_write(0xFD08152C, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70400000U);
+       psu_mask_write(0xFD0817DC, 0xFFFFFFFFU, 0x012643C4U);
+
+       return 1;
+}
+
+static unsigned long psu_ddr_qos_init_data(void)
+{
+       psu_mask_write(0xFD360008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD36001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD370008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD37001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD380008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD38001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD390008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD39001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3A0008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3A001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3B0008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFD3B001C, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFF9B0008, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFF9B001C, 0x0000000FU, 0x00000000U);
+
+       return 1;
+}
+
+static unsigned long psu_mio_init_data(void)
+{
+       psu_mask_write(0xFF180000, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180004, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180008, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18000C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180010, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180014, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180018, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18001C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180020, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180024, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180028, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18002C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180030, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180034, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180038, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF18003C, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF180040, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF180044, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF180048, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF18004C, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180050, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180054, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180058, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18005C, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180060, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180064, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180068, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18006C, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180070, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180074, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180078, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18007C, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180080, 0x000000FEU, 0x00000008U);
+       psu_mask_write(0xFF180084, 0x000000FEU, 0x00000008U);
+       psu_mask_write(0xFF180098, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18009C, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800A0, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800A4, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800A8, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800AC, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF1800B0, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF1800B4, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800B8, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800BC, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800C0, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800C4, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800C8, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800CC, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800D0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800D4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800D8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800DC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800EC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800FC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF180100, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180104, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180108, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18010C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180110, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180114, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180118, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18011C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180120, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180124, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180128, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18012C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180130, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180134, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180204, 0xFFFFFFFFU, 0x00040000U);
+       psu_mask_write(0xFF180208, 0xFFFFFFFFU, 0x00B02000U);
+       psu_mask_write(0xFF18020C, 0x00003FFFU, 0x00000FC0U);
+       psu_mask_write(0xFF180138, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF18013C, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180140, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF180144, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180148, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF18014C, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF180154, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180158, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF18015C, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF180160, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180164, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180168, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF180170, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180174, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180178, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF18017C, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180180, 0x03FFFFFFU, 0x03FFFFFFU);
+       psu_mask_write(0xFF180184, 0x03FFFFFFU, 0x00000000U);
+       psu_mask_write(0xFF180200, 0x0000000FU, 0x00000000U);
+
+       return 1;
+}
+
+static unsigned long psu_peripherals_pre_init_data(void)
+{
+       psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012302U);
+       psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000001U);
+
+       return 1;
+}
+
+static unsigned long psu_peripherals_init_data(void)
+{
+       psu_mask_write(0xFD1A0100, 0x00008046U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
+       psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
+       psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFF180390, 0x00000004U, 0x00000004U);
+       psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U);
+       psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U);
+       psu_mask_write(0xFF180320, 0x33840000U, 0x02840000U);
+       psu_mask_write(0xFF18031C, 0x7FFE0000U, 0x64500000U);
+       psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000600U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00008000U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00007800U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000002U, 0x00000000U);
+       psu_mask_write(0xFF000034, 0x000000FFU, 0x00000006U);
+       psu_mask_write(0xFF000018, 0x0000FFFFU, 0x0000007CU);
+       psu_mask_write(0xFF000000, 0x000001FFU, 0x00000017U);
+       psu_mask_write(0xFF000004, 0x000003FFU, 0x00000020U);
+       psu_mask_write(0xFF5E0238, 0x00040000U, 0x00000000U);
+       psu_mask_write(0xFF4B0024, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFFCA5000, 0x00001FFFU, 0x00000000U);
+       psu_mask_write(0xFD5C0060, 0x000F000FU, 0x00000000U);
+       psu_mask_write(0xFFA60040, 0x80000000U, 0x80000000U);
+       psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x05F5DD18U);
+       psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+       mask_delay(1);
+       psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000002U);
+
+       mask_delay(5);
+       psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+       return 1;
+}
+
+static unsigned long psu_serdes_init_data(void)
+{
+       psu_mask_write(0xFD410008, 0x0000001FU, 0x00000008U);
+       psu_mask_write(0xFD41000C, 0x0000001FU, 0x0000000FU);
+       psu_mask_write(0xFD402868, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD40286C, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD40A094, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD40A368, 0x000000FFU, 0x00000038U);
+       psu_mask_write(0xFD40A36C, 0x00000007U, 0x00000003U);
+       psu_mask_write(0xFD40E368, 0x000000FFU, 0x000000E0U);
+       psu_mask_write(0xFD40E36C, 0x00000007U, 0x00000003U);
+       psu_mask_write(0xFD40A370, 0x000000FFU, 0x000000F4U);
+       psu_mask_write(0xFD40A374, 0x000000FFU, 0x00000031U);
+       psu_mask_write(0xFD40A378, 0x000000FFU, 0x00000002U);
+       psu_mask_write(0xFD40A37C, 0x00000033U, 0x00000030U);
+       psu_mask_write(0xFD40E370, 0x000000FFU, 0x000000C9U);
+       psu_mask_write(0xFD40E374, 0x000000FFU, 0x000000D2U);
+       psu_mask_write(0xFD40E378, 0x000000FFU, 0x00000001U);
+       psu_mask_write(0xFD40E37C, 0x000000B3U, 0x000000B0U);
+       psu_mask_write(0xFD40906C, 0x00000003U, 0x00000003U);
+       psu_mask_write(0xFD4080F4, 0x00000003U, 0x00000003U);
+       psu_mask_write(0xFD40E360, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40D06C, 0x0000000FU, 0x0000000FU);
+       psu_mask_write(0xFD40C0F4, 0x0000000BU, 0x0000000BU);
+       psu_mask_write(0xFD4090CC, 0x00000020U, 0x00000020U);
+       psu_mask_write(0xFD401074, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD405074, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD409074, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD40D074, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD401994, 0x00000007U, 0x00000007U);
+       psu_mask_write(0xFD405994, 0x00000007U, 0x00000007U);
+       psu_mask_write(0xFD40989C, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD4098F8, 0x000000FFU, 0x0000001AU);
+       psu_mask_write(0xFD4098FC, 0x000000FFU, 0x0000001AU);
+       psu_mask_write(0xFD409990, 0x000000FFU, 0x00000010U);
+       psu_mask_write(0xFD409924, 0x000000FFU, 0x000000FEU);
+       psu_mask_write(0xFD409928, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD409900, 0x000000FFU, 0x0000001AU);
+       psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD409980, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD409914, 0x000000FFU, 0x000000F7U);
+       psu_mask_write(0xFD409918, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD409940, 0x000000FFU, 0x000000F7U);
+       psu_mask_write(0xFD409944, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD409994, 0x00000007U, 0x00000007U);
+       psu_mask_write(0xFD40D89C, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD40D8F8, 0x000000FFU, 0x0000007DU);
+       psu_mask_write(0xFD40D8FC, 0x000000FFU, 0x0000007DU);
+       psu_mask_write(0xFD40D990, 0x000000FFU, 0x00000001U);
+       psu_mask_write(0xFD40D924, 0x000000FFU, 0x0000009CU);
+       psu_mask_write(0xFD40D928, 0x000000FFU, 0x00000039U);
+       psu_mask_write(0xFD40D98C, 0x000000F0U, 0x00000020U);
+       psu_mask_write(0xFD40D900, 0x000000FFU, 0x0000007DU);
+       psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000064U);
+       psu_mask_write(0xFD40D980, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD40D914, 0x000000FFU, 0x000000F7U);
+       psu_mask_write(0xFD40D918, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD40D940, 0x000000FFU, 0x000000F7U);
+       psu_mask_write(0xFD40D944, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD40D994, 0x00000007U, 0x00000007U);
+       psu_mask_write(0xFD40107C, 0x0000000FU, 0x00000001U);
+       psu_mask_write(0xFD40507C, 0x0000000FU, 0x00000001U);
+       psu_mask_write(0xFD40907C, 0x0000000FU, 0x00000001U);
+       psu_mask_write(0xFD40D07C, 0x0000000FU, 0x00000001U);
+       psu_mask_write(0xFD4019A4, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD401038, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40102C, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD4059A4, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD405038, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40502C, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD4099A4, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD409038, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40902C, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40D9A4, 0x000000FFU, 0x000000FFU);
+       psu_mask_write(0xFD40D038, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40D02C, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD4019AC, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD4059AC, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD4099AC, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD40D9AC, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD401978, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD405978, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD409978, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD40D978, 0x00000010U, 0x00000010U);
+
+       serdes_illcalib(2, 3, 3, 0, 0, 0, 0, 0);
+       psu_mask_write(0xFD410014, 0x00000077U, 0x00000023U);
+       psu_mask_write(0xFD40C1D8, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD40DC14, 0x000000FFU, 0x000000E6U);
+       psu_mask_write(0xFD40DC40, 0x0000001FU, 0x0000000CU);
+       psu_mask_write(0xFD40D94C, 0x00000020U, 0x00000020U);
+       psu_mask_write(0xFD40D950, 0x00000007U, 0x00000006U);
+       psu_mask_write(0xFD40C048, 0x000000FFU, 0x00000001U);
+
+       return 1;
+}
+
+static unsigned long psu_resetout_init_data(void)
+{
+       psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+       psu_mask_write(0xFF9D0080, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF9D007C, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000000U);
+       psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD3D0100, 0x00000003U, 0x00000003U);
+       psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000000U);
+       psu_mask_write(0xFE20C200, 0x00023FFFU, 0x00022457U);
+       psu_mask_write(0xFE20C630, 0x003FFF00U, 0x00000000U);
+       psu_mask_write(0xFE20C11C, 0x00000600U, 0x00000600U);
+       psu_mask_write(0xFE20C12C, 0x00004000U, 0x00004000U);
+       psu_mask_write(0xFD480064, 0x00000200U, 0x00000200U);
+       mask_poll(0xFD40A3E4, 0x00000010U);
+       mask_poll(0xFD40E3E4, 0x00000010U);
+       psu_mask_write(0xFD0C00AC, 0xFFFFFFFFU, 0x28184018U);
+       psu_mask_write(0xFD0C00B0, 0xFFFFFFFFU, 0x0E081406U);
+       psu_mask_write(0xFD0C00B4, 0xFFFFFFFFU, 0x064A0813U);
+       psu_mask_write(0xFD0C00B8, 0xFFFFFFFFU, 0x3FFC96A4U);
+
+       return 1;
+}
+
+static unsigned long psu_resetin_init_data(void)
+{
+       psu_mask_write(0xFF5E023C, 0x00000540U, 0x00000540U);
+       psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000002U);
+
+       return 1;
+}
+
+static unsigned long psu_afi_config(void)
+{
+       psu_mask_write(0xFD1A0100, 0x00001F80U, 0x00000000U);
+       psu_mask_write(0xFF5E023C, 0x00080000U, 0x00000000U);
+       psu_mask_write(0xFD615000, 0x00000300U, 0x00000200U);
+       psu_mask_write(0xFD360000, 0x00000003U, 0x00000002U);
+       psu_mask_write(0xFD370000, 0x00000003U, 0x00000002U);
+       psu_mask_write(0xFD360014, 0x00000003U, 0x00000002U);
+       psu_mask_write(0xFD370014, 0x00000003U, 0x00000002U);
+
+       return 1;
+}
+
+static unsigned long psu_ddr_phybringup_data(void)
+{
+       unsigned int regval = 0;
+       unsigned int pll_retry = 10;
+       unsigned int pll_locked = 0;
+       int cur_R006_tREFPRD;
+
+       while ((pll_retry > 0) && (!pll_locked)) {
+               Xil_Out32(0xFD080004, 0x00040010);
+               Xil_Out32(0xFD080004, 0x00040011);
+
+               while ((Xil_In32(0xFD080030) & 0x1) != 1)
+                       ;
+               pll_locked = (Xil_In32(0xFD080030) & 0x80000000)
+                   >> 31;
+               pll_locked &= (Xil_In32(0xFD0807E0) & 0x10000)
+                   >> 16;
+               pll_locked &= (Xil_In32(0xFD0809E0) & 0x10000) >> 16;
+               pll_locked &= (Xil_In32(0xFD080BE0) & 0x10000)
+                   >> 16;
+               pll_locked &= (Xil_In32(0xFD080DE0) & 0x10000)
+                   >> 16;
+               pll_retry--;
+       }
+       Xil_Out32(0xFD0800C4, Xil_In32(0xFD0800C4) | (pll_retry << 16));
+       if (!pll_locked)
+               return 0;
+
+       Xil_Out32(0xFD080004U, 0x00040063U);
+
+       while ((Xil_In32(0xFD080030U) & 0x0000000FU) != 0x0000000FU)
+               ;
+       prog_reg(0xFD080004U, 0x00000001U, 0x00000000U, 0x00000001U);
+
+       while ((Xil_In32(0xFD080030U) & 0x000000FFU) != 0x0000001FU)
+               ;
+       Xil_Out32(0xFD0701B0U, 0x00000001U);
+       Xil_Out32(0xFD070320U, 0x00000001U);
+       while ((Xil_In32(0xFD070004U) & 0x0000000FU) != 0x00000001U)
+               ;
+       prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000001U);
+       Xil_Out32(0xFD080004, 0x0004FE01);
+       regval = Xil_In32(0xFD080030);
+       while (regval != 0x80000FFF)
+               regval = Xil_In32(0xFD080030);
+       regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+       if (regval != 0)
+               return 0;
+
+       Xil_Out32(0xFD080200U, 0x100091C7U);
+
+       cur_R006_tREFPRD = (Xil_In32(0xFD080018U) & 0x0003FFFFU) >> 0x00000000U;
+       prog_reg(0xFD080018, 0x3FFFF, 0x0, cur_R006_tREFPRD);
+
+       prog_reg(0xFD08001CU, 0x00000018U, 0x00000003U, 0x00000003U);
+       prog_reg(0xFD08142CU, 0x00000030U, 0x00000004U, 0x00000003U);
+       prog_reg(0xFD08146CU, 0x00000030U, 0x00000004U, 0x00000003U);
+       prog_reg(0xFD0814ACU, 0x00000030U, 0x00000004U, 0x00000003U);
+       prog_reg(0xFD0814ECU, 0x00000030U, 0x00000004U, 0x00000003U);
+       prog_reg(0xFD08152CU, 0x00000030U, 0x00000004U, 0x00000003U);
+
+       Xil_Out32(0xFD080004, 0x00060001);
+       regval = Xil_In32(0xFD080030);
+       while ((regval & 0x80004001) != 0x80004001)
+               regval = Xil_In32(0xFD080030);
+
+       regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+       if (regval != 0)
+               return 0;
+
+       prog_reg(0xFD08001CU, 0x00000018U, 0x00000003U, 0x00000000U);
+       prog_reg(0xFD08142CU, 0x00000030U, 0x00000004U, 0x00000000U);
+       prog_reg(0xFD08146CU, 0x00000030U, 0x00000004U, 0x00000000U);
+       prog_reg(0xFD0814ACU, 0x00000030U, 0x00000004U, 0x00000000U);
+       prog_reg(0xFD0814ECU, 0x00000030U, 0x00000004U, 0x00000000U);
+       prog_reg(0xFD08152CU, 0x00000030U, 0x00000004U, 0x00000000U);
+
+       Xil_Out32(0xFD080200U, 0x800091C7U);
+       prog_reg(0xFD080018, 0x3FFFF, 0x0, cur_R006_tREFPRD);
+
+       Xil_Out32(0xFD080004, 0x0000C001);
+       regval = Xil_In32(0xFD080030);
+       while ((regval & 0x80000C01) != 0x80000C01)
+               regval = Xil_In32(0xFD080030);
+
+       Xil_Out32(0xFD070180U, 0x01000040U);
+       Xil_Out32(0xFD070060U, 0x00000000U);
+       prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000000U);
+
+       return 1;
+}
+
+static int serdes_rst_seq(u32 lane3_protocol, u32 lane3_rate,
+                         u32 lane2_protocol, u32 lane2_rate,
+                         u32 lane1_protocol, u32 lane1_rate,
+                         u32 lane0_protocol, u32 lane0_rate)
+{
+       Xil_Out32(0xFD410098, 0x00000000);
+       Xil_Out32(0xFD401010, 0x00000040);
+       Xil_Out32(0xFD405010, 0x00000040);
+       Xil_Out32(0xFD409010, 0x00000040);
+       Xil_Out32(0xFD40D010, 0x00000040);
+       Xil_Out32(0xFD402084, 0x00000080);
+       Xil_Out32(0xFD406084, 0x00000080);
+       Xil_Out32(0xFD40A084, 0x00000080);
+       Xil_Out32(0xFD40E084, 0x00000080);
+       Xil_Out32(0xFD410098, 0x00000004);
+       mask_delay(50);
+       if (lane0_rate == 1)
+               Xil_Out32(0xFD410098, 0x0000000E);
+       Xil_Out32(0xFD410098, 0x00000006);
+       if (lane0_rate == 1) {
+               Xil_Out32(0xFD40000C, 0x00000004);
+               Xil_Out32(0xFD40400C, 0x00000004);
+               Xil_Out32(0xFD40800C, 0x00000004);
+               Xil_Out32(0xFD40C00C, 0x00000004);
+               Xil_Out32(0xFD410098, 0x00000007);
+               mask_delay(400);
+               Xil_Out32(0xFD40000C, 0x0000000C);
+               Xil_Out32(0xFD40400C, 0x0000000C);
+               Xil_Out32(0xFD40800C, 0x0000000C);
+               Xil_Out32(0xFD40C00C, 0x0000000C);
+               mask_delay(15);
+               Xil_Out32(0xFD410098, 0x0000000F);
+               mask_delay(100);
+       }
+       if (lane0_protocol != 0)
+               mask_poll(0xFD4023E4, 0x00000010U);
+       if (lane1_protocol != 0)
+               mask_poll(0xFD4063E4, 0x00000010U);
+       if (lane2_protocol != 0)
+               mask_poll(0xFD40A3E4, 0x00000010U);
+       if (lane3_protocol != 0)
+               mask_poll(0xFD40E3E4, 0x00000010U);
+       mask_delay(50);
+       Xil_Out32(0xFD401010, 0x000000C0);
+       Xil_Out32(0xFD405010, 0x000000C0);
+       Xil_Out32(0xFD409010, 0x000000C0);
+       Xil_Out32(0xFD40D010, 0x000000C0);
+       Xil_Out32(0xFD401010, 0x00000080);
+       Xil_Out32(0xFD405010, 0x00000080);
+       Xil_Out32(0xFD409010, 0x00000080);
+       Xil_Out32(0xFD40D010, 0x00000080);
+
+       Xil_Out32(0xFD402084, 0x000000C0);
+       Xil_Out32(0xFD406084, 0x000000C0);
+       Xil_Out32(0xFD40A084, 0x000000C0);
+       Xil_Out32(0xFD40E084, 0x000000C0);
+       mask_delay(50);
+       Xil_Out32(0xFD402084, 0x00000080);
+       Xil_Out32(0xFD406084, 0x00000080);
+       Xil_Out32(0xFD40A084, 0x00000080);
+       Xil_Out32(0xFD40E084, 0x00000080);
+       mask_delay(50);
+       Xil_Out32(0xFD401010, 0x00000000);
+       Xil_Out32(0xFD405010, 0x00000000);
+       Xil_Out32(0xFD409010, 0x00000000);
+       Xil_Out32(0xFD40D010, 0x00000000);
+       Xil_Out32(0xFD402084, 0x00000000);
+       Xil_Out32(0xFD406084, 0x00000000);
+       Xil_Out32(0xFD40A084, 0x00000000);
+       Xil_Out32(0xFD40E084, 0x00000000);
+       mask_delay(500);
+       return 1;
+}
+
+static int serdes_bist_static_settings(u32 lane_active)
+{
+       if (lane_active == 0) {
+               Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) & 0xFFFFFF1F));
+               Xil_Out32(0xFD403068, 0x1);
+               Xil_Out32(0xFD40306C, 0x1);
+               Xil_Out32(0xFD4010AC, 0x0020);
+               Xil_Out32(0xFD403008, 0x0);
+               Xil_Out32(0xFD40300C, 0xF4);
+               Xil_Out32(0xFD403010, 0x0);
+               Xil_Out32(0xFD403014, 0x0);
+               Xil_Out32(0xFD403018, 0x00);
+               Xil_Out32(0xFD40301C, 0xFB);
+               Xil_Out32(0xFD403020, 0xFF);
+               Xil_Out32(0xFD403024, 0x0);
+               Xil_Out32(0xFD403028, 0x00);
+               Xil_Out32(0xFD40302C, 0x00);
+               Xil_Out32(0xFD403030, 0x4A);
+               Xil_Out32(0xFD403034, 0x4A);
+               Xil_Out32(0xFD403038, 0x4A);
+               Xil_Out32(0xFD40303C, 0x4A);
+               Xil_Out32(0xFD403040, 0x0);
+               Xil_Out32(0xFD403044, 0x14);
+               Xil_Out32(0xFD403048, 0x02);
+               Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) & 0xFFFFFF1F));
+       }
+       if (lane_active == 1) {
+               Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) & 0xFFFFFF1F));
+               Xil_Out32(0xFD407068, 0x1);
+               Xil_Out32(0xFD40706C, 0x1);
+               Xil_Out32(0xFD4050AC, 0x0020);
+               Xil_Out32(0xFD407008, 0x0);
+               Xil_Out32(0xFD40700C, 0xF4);
+               Xil_Out32(0xFD407010, 0x0);
+               Xil_Out32(0xFD407014, 0x0);
+               Xil_Out32(0xFD407018, 0x00);
+               Xil_Out32(0xFD40701C, 0xFB);
+               Xil_Out32(0xFD407020, 0xFF);
+               Xil_Out32(0xFD407024, 0x0);
+               Xil_Out32(0xFD407028, 0x00);
+               Xil_Out32(0xFD40702C, 0x00);
+               Xil_Out32(0xFD407030, 0x4A);
+               Xil_Out32(0xFD407034, 0x4A);
+               Xil_Out32(0xFD407038, 0x4A);
+               Xil_Out32(0xFD40703C, 0x4A);
+               Xil_Out32(0xFD407040, 0x0);
+               Xil_Out32(0xFD407044, 0x14);
+               Xil_Out32(0xFD407048, 0x02);
+               Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) & 0xFFFFFF1F));
+       }
+
+       if (lane_active == 2) {
+               Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) & 0xFFFFFF1F));
+               Xil_Out32(0xFD40B068, 0x1);
+               Xil_Out32(0xFD40B06C, 0x1);
+               Xil_Out32(0xFD4090AC, 0x0020);
+               Xil_Out32(0xFD40B008, 0x0);
+               Xil_Out32(0xFD40B00C, 0xF4);
+               Xil_Out32(0xFD40B010, 0x0);
+               Xil_Out32(0xFD40B014, 0x0);
+               Xil_Out32(0xFD40B018, 0x00);
+               Xil_Out32(0xFD40B01C, 0xFB);
+               Xil_Out32(0xFD40B020, 0xFF);
+               Xil_Out32(0xFD40B024, 0x0);
+               Xil_Out32(0xFD40B028, 0x00);
+               Xil_Out32(0xFD40B02C, 0x00);
+               Xil_Out32(0xFD40B030, 0x4A);
+               Xil_Out32(0xFD40B034, 0x4A);
+               Xil_Out32(0xFD40B038, 0x4A);
+               Xil_Out32(0xFD40B03C, 0x4A);
+               Xil_Out32(0xFD40B040, 0x0);
+               Xil_Out32(0xFD40B044, 0x14);
+               Xil_Out32(0xFD40B048, 0x02);
+               Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) & 0xFFFFFF1F));
+       }
+
+       if (lane_active == 3) {
+               Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) & 0xFFFFFF1F));
+               Xil_Out32(0xFD40F068, 0x1);
+               Xil_Out32(0xFD40F06C, 0x1);
+               Xil_Out32(0xFD40D0AC, 0x0020);
+               Xil_Out32(0xFD40F008, 0x0);
+               Xil_Out32(0xFD40F00C, 0xF4);
+               Xil_Out32(0xFD40F010, 0x0);
+               Xil_Out32(0xFD40F014, 0x0);
+               Xil_Out32(0xFD40F018, 0x00);
+               Xil_Out32(0xFD40F01C, 0xFB);
+               Xil_Out32(0xFD40F020, 0xFF);
+               Xil_Out32(0xFD40F024, 0x0);
+               Xil_Out32(0xFD40F028, 0x00);
+               Xil_Out32(0xFD40F02C, 0x00);
+               Xil_Out32(0xFD40F030, 0x4A);
+               Xil_Out32(0xFD40F034, 0x4A);
+               Xil_Out32(0xFD40F038, 0x4A);
+               Xil_Out32(0xFD40F03C, 0x4A);
+               Xil_Out32(0xFD40F040, 0x0);
+               Xil_Out32(0xFD40F044, 0x14);
+               Xil_Out32(0xFD40F048, 0x02);
+               Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) & 0xFFFFFF1F));
+       }
+       return 1;
+}
+
+static int serdes_bist_run(u32 lane_active)
+{
+       if (lane_active == 0) {
+               psu_mask_write(0xFD410044, 0x00000003U, 0x00000000U);
+               psu_mask_write(0xFD410040, 0x00000003U, 0x00000000U);
+               psu_mask_write(0xFD410038, 0x00000007U, 0x00000001U);
+               Xil_Out32(0xFD4010AC, 0x0020);
+               Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) | 0x1));
+       }
+       if (lane_active == 1) {
+               psu_mask_write(0xFD410044, 0x0000000CU, 0x00000000U);
+               psu_mask_write(0xFD410040, 0x0000000CU, 0x00000000U);
+               psu_mask_write(0xFD410038, 0x00000070U, 0x00000010U);
+               Xil_Out32(0xFD4050AC, 0x0020);
+               Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) | 0x1));
+       }
+       if (lane_active == 2) {
+               psu_mask_write(0xFD410044, 0x00000030U, 0x00000000U);
+               psu_mask_write(0xFD410040, 0x00000030U, 0x00000000U);
+               psu_mask_write(0xFD41003C, 0x00000007U, 0x00000001U);
+               Xil_Out32(0xFD4090AC, 0x0020);
+               Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) | 0x1));
+       }
+       if (lane_active == 3) {
+               psu_mask_write(0xFD410040, 0x000000C0U, 0x00000000U);
+               psu_mask_write(0xFD410044, 0x000000C0U, 0x00000000U);
+               psu_mask_write(0xFD41003C, 0x00000070U, 0x00000010U);
+               Xil_Out32(0xFD40D0AC, 0x0020);
+               Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) | 0x1));
+       }
+       mask_delay(100);
+       return 1;
+}
+
+static int serdes_bist_result(u32 lane_active)
+{
+       u32 pkt_cnt_l0, pkt_cnt_h0, err_cnt_l0, err_cnt_h0;
+
+       if (lane_active == 0) {
+               pkt_cnt_l0 = Xil_In32(0xFD40304C);
+               pkt_cnt_h0 = Xil_In32(0xFD403050);
+               err_cnt_l0 = Xil_In32(0xFD403054);
+               err_cnt_h0 = Xil_In32(0xFD403058);
+       }
+       if (lane_active == 1) {
+               pkt_cnt_l0 = Xil_In32(0xFD40704C);
+               pkt_cnt_h0 = Xil_In32(0xFD407050);
+               err_cnt_l0 = Xil_In32(0xFD407054);
+               err_cnt_h0 = Xil_In32(0xFD407058);
+       }
+       if (lane_active == 2) {
+               pkt_cnt_l0 = Xil_In32(0xFD40B04C);
+               pkt_cnt_h0 = Xil_In32(0xFD40B050);
+               err_cnt_l0 = Xil_In32(0xFD40B054);
+               err_cnt_h0 = Xil_In32(0xFD40B058);
+       }
+       if (lane_active == 3) {
+               pkt_cnt_l0 = Xil_In32(0xFD40F04C);
+               pkt_cnt_h0 = Xil_In32(0xFD40F050);
+               err_cnt_l0 = Xil_In32(0xFD40F054);
+               err_cnt_h0 = Xil_In32(0xFD40F058);
+       }
+       if (lane_active == 0)
+               Xil_Out32(0xFD403004, 0x0);
+       if (lane_active == 1)
+               Xil_Out32(0xFD407004, 0x0);
+       if (lane_active == 2)
+               Xil_Out32(0xFD40B004, 0x0);
+       if (lane_active == 3)
+               Xil_Out32(0xFD40F004, 0x0);
+       if (err_cnt_l0 > 0 || err_cnt_h0 > 0 ||
+           (pkt_cnt_l0 == 0 && pkt_cnt_h0 == 0))
+               return 0;
+       return 1;
+}
+
+static int serdes_illcalib_pcie_gen1(u32 lane3_protocol, u32 lane3_rate,
+                                    u32 lane2_protocol, u32 lane2_rate,
+                                    u32 lane1_protocol, u32 lane1_rate,
+                                    u32 lane0_protocol, u32 lane0_rate,
+                                    u32 gen2_calib)
+{
+       u64 tempbistresult;
+       u32 currbistresult[4];
+       u32 prevbistresult[4];
+       u32 itercount = 0;
+       u32 ill12_val[4], ill1_val[4];
+       u32 loop = 0;
+       u32 iterresult[8];
+       u32 meancount[4];
+       u32 bistpasscount[4];
+       u32 meancountalt[4];
+       u32 meancountalt_bistpasscount[4];
+       u32 lane0_active;
+       u32 lane1_active;
+       u32 lane2_active;
+       u32 lane3_active;
+
+       lane0_active = (lane0_protocol == 1);
+       lane1_active = (lane1_protocol == 1);
+       lane2_active = (lane2_protocol == 1);
+       lane3_active = (lane3_protocol == 1);
+       for (loop = 0; loop <= 3; loop++) {
+               iterresult[loop] = 0;
+               iterresult[loop + 4] = 0;
+               meancountalt[loop] = 0;
+               meancountalt_bistpasscount[loop] = 0;
+               meancount[loop] = 0;
+               prevbistresult[loop] = 0;
+               bistpasscount[loop] = 0;
+       }
+       itercount = 0;
+       if (lane0_active)
+               serdes_bist_static_settings(0);
+       if (lane1_active)
+               serdes_bist_static_settings(1);
+       if (lane2_active)
+               serdes_bist_static_settings(2);
+       if (lane3_active)
+               serdes_bist_static_settings(3);
+       do {
+               if (gen2_calib != 1) {
+                       if (lane0_active == 1)
+                               ill1_val[0] = ((0x04 + itercount * 8) % 0x100);
+                       if (lane0_active == 1)
+                               ill12_val[0] =
+                                   ((0x04 + itercount * 8) >=
+                                    0x100) ? 0x10 : 0x00;
+                       if (lane1_active == 1)
+                               ill1_val[1] = ((0x04 + itercount * 8) % 0x100);
+                       if (lane1_active == 1)
+                               ill12_val[1] =
+                                   ((0x04 + itercount * 8) >=
+                                    0x100) ? 0x10 : 0x00;
+                       if (lane2_active == 1)
+                               ill1_val[2] = ((0x04 + itercount * 8) % 0x100);
+                       if (lane2_active == 1)
+                               ill12_val[2] =
+                                   ((0x04 + itercount * 8) >=
+                                    0x100) ? 0x10 : 0x00;
+                       if (lane3_active == 1)
+                               ill1_val[3] = ((0x04 + itercount * 8) % 0x100);
+                       if (lane3_active == 1)
+                               ill12_val[3] =
+                                   ((0x04 + itercount * 8) >=
+                                    0x100) ? 0x10 : 0x00;
+
+                       if (lane0_active == 1)
+                               Xil_Out32(0xFD401924, ill1_val[0]);
+                       if (lane0_active == 1)
+                               psu_mask_write(0xFD401990, 0x000000F0U,
+                                              ill12_val[0]);
+                       if (lane1_active == 1)
+                               Xil_Out32(0xFD405924, ill1_val[1]);
+                       if (lane1_active == 1)
+                               psu_mask_write(0xFD405990, 0x000000F0U,
+                                              ill12_val[1]);
+                       if (lane2_active == 1)
+                               Xil_Out32(0xFD409924, ill1_val[2]);
+                       if (lane2_active == 1)
+                               psu_mask_write(0xFD409990, 0x000000F0U,
+                                              ill12_val[2]);
+                       if (lane3_active == 1)
+                               Xil_Out32(0xFD40D924, ill1_val[3]);
+                       if (lane3_active == 1)
+                               psu_mask_write(0xFD40D990, 0x000000F0U,
+                                              ill12_val[3]);
+               }
+               if (gen2_calib == 1) {
+                       if (lane0_active == 1)
+                               ill1_val[0] = ((0x104 + itercount * 8) % 0x100);
+                       if (lane0_active == 1)
+                               ill12_val[0] =
+                                   ((0x104 + itercount * 8) >=
+                                    0x200) ? 0x02 : 0x01;
+                       if (lane1_active == 1)
+                               ill1_val[1] = ((0x104 + itercount * 8) % 0x100);
+                       if (lane1_active == 1)
+                               ill12_val[1] =
+                                   ((0x104 + itercount * 8) >=
+                                    0x200) ? 0x02 : 0x01;
+                       if (lane2_active == 1)
+                               ill1_val[2] = ((0x104 + itercount * 8) % 0x100);
+                       if (lane2_active == 1)
+                               ill12_val[2] =
+                                   ((0x104 + itercount * 8) >=
+                                    0x200) ? 0x02 : 0x01;
+                       if (lane3_active == 1)
+                               ill1_val[3] = ((0x104 + itercount * 8) % 0x100);
+                       if (lane3_active == 1)
+                               ill12_val[3] =
+                                   ((0x104 + itercount * 8) >=
+                                    0x200) ? 0x02 : 0x01;
+
+                       if (lane0_active == 1)
+                               Xil_Out32(0xFD401928, ill1_val[0]);
+                       if (lane0_active == 1)
+                               psu_mask_write(0xFD401990, 0x0000000FU,
+                                              ill12_val[0]);
+                       if (lane1_active == 1)
+                               Xil_Out32(0xFD405928, ill1_val[1]);
+                       if (lane1_active == 1)
+                               psu_mask_write(0xFD405990, 0x0000000FU,
+                                              ill12_val[1]);
+                       if (lane2_active == 1)
+                               Xil_Out32(0xFD409928, ill1_val[2]);
+                       if (lane2_active == 1)
+                               psu_mask_write(0xFD409990, 0x0000000FU,
+                                              ill12_val[2]);
+                       if (lane3_active == 1)
+                               Xil_Out32(0xFD40D928, ill1_val[3]);
+                       if (lane3_active == 1)
+                               psu_mask_write(0xFD40D990, 0x0000000FU,
+                                              ill12_val[3]);
+               }
+
+               if (lane0_active == 1)
+                       psu_mask_write(0xFD401018, 0x00000030U, 0x00000010U);
+               if (lane1_active == 1)
+                       psu_mask_write(0xFD405018, 0x00000030U, 0x00000010U);
+               if (lane2_active == 1)
+                       psu_mask_write(0xFD409018, 0x00000030U, 0x00000010U);
+               if (lane3_active == 1)
+                       psu_mask_write(0xFD40D018, 0x00000030U, 0x00000010U);
+               if (lane0_active == 1)
+                       currbistresult[0] = 0;
+               if (lane1_active == 1)
+                       currbistresult[1] = 0;
+               if (lane2_active == 1)
+                       currbistresult[2] = 0;
+               if (lane3_active == 1)
+                       currbistresult[3] = 0;
+               serdes_rst_seq(lane3_protocol, lane3_rate, lane2_protocol,
+                              lane2_rate, lane1_protocol, lane1_rate,
+                              lane0_protocol, lane0_rate);
+               if (lane3_active == 1)
+                       serdes_bist_run(3);
+               if (lane2_active == 1)
+                       serdes_bist_run(2);
+               if (lane1_active == 1)
+                       serdes_bist_run(1);
+               if (lane0_active == 1)
+                       serdes_bist_run(0);
+               tempbistresult = 0;
+               if (lane3_active == 1)
+                       tempbistresult = tempbistresult | serdes_bist_result(3);
+               tempbistresult = tempbistresult << 1;
+               if (lane2_active == 1)
+                       tempbistresult = tempbistresult | serdes_bist_result(2);
+               tempbistresult = tempbistresult << 1;
+               if (lane1_active == 1)
+                       tempbistresult = tempbistresult | serdes_bist_result(1);
+               tempbistresult = tempbistresult << 1;
+               if (lane0_active == 1)
+                       tempbistresult = tempbistresult | serdes_bist_result(0);
+               Xil_Out32(0xFD410098, 0x0);
+               Xil_Out32(0xFD410098, 0x2);
+
+               if (itercount < 32) {
+                       iterresult[0] =
+                           ((iterresult[0] << 1) |
+                            ((tempbistresult & 0x1) == 0x1));
+                       iterresult[1] =
+                           ((iterresult[1] << 1) |
+                            ((tempbistresult & 0x2) == 0x2));
+                       iterresult[2] =
+                           ((iterresult[2] << 1) |
+                            ((tempbistresult & 0x4) == 0x4));
+                       iterresult[3] =
+                           ((iterresult[3] << 1) |
+                            ((tempbistresult & 0x8) == 0x8));
+               } else {
+                       iterresult[4] =
+                           ((iterresult[4] << 1) |
+                            ((tempbistresult & 0x1) == 0x1));
+                       iterresult[5] =
+                           ((iterresult[5] << 1) |
+                            ((tempbistresult & 0x2) == 0x2));
+                       iterresult[6] =
+                           ((iterresult[6] << 1) |
+                            ((tempbistresult & 0x4) == 0x4));
+                       iterresult[7] =
+                           ((iterresult[7] << 1) |
+                            ((tempbistresult & 0x8) == 0x8));
+               }
+               currbistresult[0] =
+                   currbistresult[0] | ((tempbistresult & 0x1) == 1);
+               currbistresult[1] =
+                   currbistresult[1] | ((tempbistresult & 0x2) == 0x2);
+               currbistresult[2] =
+                   currbistresult[2] | ((tempbistresult & 0x4) == 0x4);
+               currbistresult[3] =
+                   currbistresult[3] | ((tempbistresult & 0x8) == 0x8);
+
+               for (loop = 0; loop <= 3; loop++) {
+                       if (currbistresult[loop] == 1 && prevbistresult[loop] == 1)
+                               bistpasscount[loop] = bistpasscount[loop] + 1;
+                       if (bistpasscount[loop] < 4 && currbistresult[loop] == 0 &&
+                           itercount > 2) {
+                               if (meancountalt_bistpasscount[loop] <
+                                   bistpasscount[loop]) {
+                                       meancountalt_bistpasscount[loop] =
+                                           bistpasscount[loop];
+                                       meancountalt[loop] =
+                                           ((itercount - 1) -
+                                            ((bistpasscount[loop] + 1) / 2));
+                               }
+                               bistpasscount[loop] = 0;
+                       }
+                       if (meancount[loop] == 0 && bistpasscount[loop] >= 4 &&
+                           (currbistresult[loop] == 0 || itercount == 63) &&
+                           prevbistresult[loop] == 1)
+                               meancount[loop] =
+                                   (itercount - 1) -
+                                   ((bistpasscount[loop] + 1) / 2);
+                       prevbistresult[loop] = currbistresult[loop];
+               }
+       } while (++itercount < 64);
+
+       for (loop = 0; loop <= 3; loop++) {
+               if (lane0_active == 0 && loop == 0)
+                       continue;
+               if (lane1_active == 0 && loop == 1)
+                       continue;
+               if (lane2_active == 0 && loop == 2)
+                       continue;
+               if (lane3_active == 0 && loop == 3)
+                       continue;
+
+               if (meancount[loop] == 0)
+                       meancount[loop] = meancountalt[loop];
+
+               if (gen2_calib != 1) {
+                       ill1_val[loop] = ((0x04 + meancount[loop] * 8) % 0x100);
+                       ill12_val[loop] =
+                           ((0x04 + meancount[loop] * 8) >=
+                            0x100) ? 0x10 : 0x00;
+                       Xil_Out32(0xFFFE0000 + loop * 4, iterresult[loop]);
+                       Xil_Out32(0xFFFE0010 + loop * 4, iterresult[loop + 4]);
+                       Xil_Out32(0xFFFE0020 + loop * 4, bistpasscount[loop]);
+                       Xil_Out32(0xFFFE0030 + loop * 4, meancount[loop]);
+               }
+               if (gen2_calib == 1) {
+                       ill1_val[loop] =
+                           ((0x104 + meancount[loop] * 8) % 0x100);
+                       ill12_val[loop] =
+                           ((0x104 + meancount[loop] * 8) >=
+                            0x200) ? 0x02 : 0x01;
+                       Xil_Out32(0xFFFE0040 + loop * 4, iterresult[loop]);
+                       Xil_Out32(0xFFFE0050 + loop * 4, iterresult[loop + 4]);
+                       Xil_Out32(0xFFFE0060 + loop * 4, bistpasscount[loop]);
+                       Xil_Out32(0xFFFE0070 + loop * 4, meancount[loop]);
+               }
+       }
+       if (gen2_calib != 1) {
+               if (lane0_active == 1)
+                       Xil_Out32(0xFD401924, ill1_val[0]);
+               if (lane0_active == 1)
+                       psu_mask_write(0xFD401990, 0x000000F0U, ill12_val[0]);
+               if (lane1_active == 1)
+                       Xil_Out32(0xFD405924, ill1_val[1]);
+               if (lane1_active == 1)
+                       psu_mask_write(0xFD405990, 0x000000F0U, ill12_val[1]);
+               if (lane2_active == 1)
+                       Xil_Out32(0xFD409924, ill1_val[2]);
+               if (lane2_active == 1)
+                       psu_mask_write(0xFD409990, 0x000000F0U, ill12_val[2]);
+               if (lane3_active == 1)
+                       Xil_Out32(0xFD40D924, ill1_val[3]);
+               if (lane3_active == 1)
+                       psu_mask_write(0xFD40D990, 0x000000F0U, ill12_val[3]);
+       }
+       if (gen2_calib == 1) {
+               if (lane0_active == 1)
+                       Xil_Out32(0xFD401928, ill1_val[0]);
+               if (lane0_active == 1)
+                       psu_mask_write(0xFD401990, 0x0000000FU, ill12_val[0]);
+               if (lane1_active == 1)
+                       Xil_Out32(0xFD405928, ill1_val[1]);
+               if (lane1_active == 1)
+                       psu_mask_write(0xFD405990, 0x0000000FU, ill12_val[1]);
+               if (lane2_active == 1)
+                       Xil_Out32(0xFD409928, ill1_val[2]);
+               if (lane2_active == 1)
+                       psu_mask_write(0xFD409990, 0x0000000FU, ill12_val[2]);
+               if (lane3_active == 1)
+                       Xil_Out32(0xFD40D928, ill1_val[3]);
+               if (lane3_active == 1)
+                       psu_mask_write(0xFD40D990, 0x0000000FU, ill12_val[3]);
+       }
+
+       if (lane0_active == 1)
+               psu_mask_write(0xFD401018, 0x00000030U, 0x00000000U);
+       if (lane1_active == 1)
+               psu_mask_write(0xFD405018, 0x00000030U, 0x00000000U);
+       if (lane2_active == 1)
+               psu_mask_write(0xFD409018, 0x00000030U, 0x00000000U);
+       if (lane3_active == 1)
+               psu_mask_write(0xFD40D018, 0x00000030U, 0x00000000U);
+
+       Xil_Out32(0xFD410098, 0);
+       if (lane0_active == 1) {
+               Xil_Out32(0xFD403004, 0);
+               Xil_Out32(0xFD403008, 0);
+               Xil_Out32(0xFD40300C, 0);
+               Xil_Out32(0xFD403010, 0);
+               Xil_Out32(0xFD403014, 0);
+               Xil_Out32(0xFD403018, 0);
+               Xil_Out32(0xFD40301C, 0);
+               Xil_Out32(0xFD403020, 0);
+               Xil_Out32(0xFD403024, 0);
+               Xil_Out32(0xFD403028, 0);
+               Xil_Out32(0xFD40302C, 0);
+               Xil_Out32(0xFD403030, 0);
+               Xil_Out32(0xFD403034, 0);
+               Xil_Out32(0xFD403038, 0);
+               Xil_Out32(0xFD40303C, 0);
+               Xil_Out32(0xFD403040, 0);
+               Xil_Out32(0xFD403044, 0);
+               Xil_Out32(0xFD403048, 0);
+               Xil_Out32(0xFD40304C, 0);
+               Xil_Out32(0xFD403050, 0);
+               Xil_Out32(0xFD403054, 0);
+               Xil_Out32(0xFD403058, 0);
+               Xil_Out32(0xFD403068, 1);
+               Xil_Out32(0xFD40306C, 0);
+               Xil_Out32(0xFD4010AC, 0);
+               psu_mask_write(0xFD410044, 0x00000003U, 0x00000001U);
+               psu_mask_write(0xFD410040, 0x00000003U, 0x00000001U);
+               psu_mask_write(0xFD410038, 0x00000007U, 0x00000000U);
+       }
+       if (lane1_active == 1) {
+               Xil_Out32(0xFD407004, 0);
+               Xil_Out32(0xFD407008, 0);
+               Xil_Out32(0xFD40700C, 0);
+               Xil_Out32(0xFD407010, 0);
+               Xil_Out32(0xFD407014, 0);
+               Xil_Out32(0xFD407018, 0);
+               Xil_Out32(0xFD40701C, 0);
+               Xil_Out32(0xFD407020, 0);
+               Xil_Out32(0xFD407024, 0);
+               Xil_Out32(0xFD407028, 0);
+               Xil_Out32(0xFD40702C, 0);
+               Xil_Out32(0xFD407030, 0);
+               Xil_Out32(0xFD407034, 0);
+               Xil_Out32(0xFD407038, 0);
+               Xil_Out32(0xFD40703C, 0);
+               Xil_Out32(0xFD407040, 0);
+               Xil_Out32(0xFD407044, 0);
+               Xil_Out32(0xFD407048, 0);
+               Xil_Out32(0xFD40704C, 0);
+               Xil_Out32(0xFD407050, 0);
+               Xil_Out32(0xFD407054, 0);
+               Xil_Out32(0xFD407058, 0);
+               Xil_Out32(0xFD407068, 1);
+               Xil_Out32(0xFD40706C, 0);
+               Xil_Out32(0xFD4050AC, 0);
+               psu_mask_write(0xFD410044, 0x0000000CU, 0x00000004U);
+               psu_mask_write(0xFD410040, 0x0000000CU, 0x00000004U);
+               psu_mask_write(0xFD410038, 0x00000070U, 0x00000000U);
+       }
+       if (lane2_active == 1) {
+               Xil_Out32(0xFD40B004, 0);
+               Xil_Out32(0xFD40B008, 0);
+               Xil_Out32(0xFD40B00C, 0);
+               Xil_Out32(0xFD40B010, 0);
+               Xil_Out32(0xFD40B014, 0);
+               Xil_Out32(0xFD40B018, 0);
+               Xil_Out32(0xFD40B01C, 0);
+               Xil_Out32(0xFD40B020, 0);
+               Xil_Out32(0xFD40B024, 0);
+               Xil_Out32(0xFD40B028, 0);
+               Xil_Out32(0xFD40B02C, 0);
+               Xil_Out32(0xFD40B030, 0);
+               Xil_Out32(0xFD40B034, 0);
+               Xil_Out32(0xFD40B038, 0);
+               Xil_Out32(0xFD40B03C, 0);
+               Xil_Out32(0xFD40B040, 0);
+               Xil_Out32(0xFD40B044, 0);
+               Xil_Out32(0xFD40B048, 0);
+               Xil_Out32(0xFD40B04C, 0);
+               Xil_Out32(0xFD40B050, 0);
+               Xil_Out32(0xFD40B054, 0);
+               Xil_Out32(0xFD40B058, 0);
+               Xil_Out32(0xFD40B068, 1);
+               Xil_Out32(0xFD40B06C, 0);
+               Xil_Out32(0xFD4090AC, 0);
+               psu_mask_write(0xFD410044, 0x00000030U, 0x00000010U);
+               psu_mask_write(0xFD410040, 0x00000030U, 0x00000010U);
+               psu_mask_write(0xFD41003C, 0x00000007U, 0x00000000U);
+       }
+       if (lane3_active == 1) {
+               Xil_Out32(0xFD40F004, 0);
+               Xil_Out32(0xFD40F008, 0);
+               Xil_Out32(0xFD40F00C, 0);
+               Xil_Out32(0xFD40F010, 0);
+               Xil_Out32(0xFD40F014, 0);
+               Xil_Out32(0xFD40F018, 0);
+               Xil_Out32(0xFD40F01C, 0);
+               Xil_Out32(0xFD40F020, 0);
+               Xil_Out32(0xFD40F024, 0);
+               Xil_Out32(0xFD40F028, 0);
+               Xil_Out32(0xFD40F02C, 0);
+               Xil_Out32(0xFD40F030, 0);
+               Xil_Out32(0xFD40F034, 0);
+               Xil_Out32(0xFD40F038, 0);
+               Xil_Out32(0xFD40F03C, 0);
+               Xil_Out32(0xFD40F040, 0);
+               Xil_Out32(0xFD40F044, 0);
+               Xil_Out32(0xFD40F048, 0);
+               Xil_Out32(0xFD40F04C, 0);
+               Xil_Out32(0xFD40F050, 0);
+               Xil_Out32(0xFD40F054, 0);
+               Xil_Out32(0xFD40F058, 0);
+               Xil_Out32(0xFD40F068, 1);
+               Xil_Out32(0xFD40F06C, 0);
+               Xil_Out32(0xFD40D0AC, 0);
+               psu_mask_write(0xFD410044, 0x000000C0U, 0x00000040U);
+               psu_mask_write(0xFD410040, 0x000000C0U, 0x00000040U);
+               psu_mask_write(0xFD41003C, 0x00000070U, 0x00000000U);
+       }
+       return 1;
+}
+
+static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate,
+                          u32 lane2_protocol, u32 lane2_rate,
+                          u32 lane1_protocol, u32 lane1_rate,
+                          u32 lane0_protocol, u32 lane0_rate)
+{
+       unsigned int rdata = 0;
+       unsigned int sata_gen2 = 1;
+       unsigned int temp_ill12 = 0;
+       unsigned int temp_PLL_REF_SEL_OFFSET;
+       unsigned int temp_TM_IQ_ILL1;
+       unsigned int temp_TM_E_ILL1;
+       unsigned int temp_tx_dig_tm_61;
+       unsigned int temp_tm_dig_6;
+       unsigned int temp_pll_fbdiv_frac_3_msb_offset;
+
+       if (lane0_protocol == 2 || lane0_protocol == 1) {
+               Xil_Out32(0xFD401910, 0xF3);
+               Xil_Out32(0xFD40193C, 0xF3);
+               Xil_Out32(0xFD401914, 0xF3);
+               Xil_Out32(0xFD401940, 0xF3);
+       }
+       if (lane1_protocol == 2 || lane1_protocol == 1) {
+               Xil_Out32(0xFD405910, 0xF3);
+               Xil_Out32(0xFD40593C, 0xF3);
+               Xil_Out32(0xFD405914, 0xF3);
+               Xil_Out32(0xFD405940, 0xF3);
+       }
+       if (lane2_protocol == 2 || lane2_protocol == 1) {
+               Xil_Out32(0xFD409910, 0xF3);
+               Xil_Out32(0xFD40993C, 0xF3);
+               Xil_Out32(0xFD409914, 0xF3);
+               Xil_Out32(0xFD409940, 0xF3);
+       }
+       if (lane3_protocol == 2 || lane3_protocol == 1) {
+               Xil_Out32(0xFD40D910, 0xF3);
+               Xil_Out32(0xFD40D93C, 0xF3);
+               Xil_Out32(0xFD40D914, 0xF3);
+               Xil_Out32(0xFD40D940, 0xF3);
+       }
+
+       if (sata_gen2 == 1) {
+               if (lane0_protocol == 2) {
+                       temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD402360);
+                       Xil_Out32(0xFD402360, 0x0);
+                       temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410000);
+                       psu_mask_write(0xFD410000, 0x0000001FU, 0x0000000DU);
+                       temp_TM_IQ_ILL1 = Xil_In32(0xFD4018F8);
+                       temp_TM_E_ILL1 = Xil_In32(0xFD401924);
+                       Xil_Out32(0xFD4018F8, 0x78);
+                       temp_tx_dig_tm_61 = Xil_In32(0xFD4000F4);
+                       temp_tm_dig_6 = Xil_In32(0xFD40106C);
+                       psu_mask_write(0xFD4000F4, 0x0000000BU, 0x00000000U);
+                       psu_mask_write(0xFD40106C, 0x0000000FU, 0x00000000U);
+                       temp_ill12 = Xil_In32(0xFD401990) & 0xF0;
+
+                       serdes_illcalib_pcie_gen1(0, 0, 0, 0, 0, 0, 1, 0, 0);
+
+                       Xil_Out32(0xFD402360, temp_pll_fbdiv_frac_3_msb_offset);
+                       Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+                       Xil_Out32(0xFD4018F8, temp_TM_IQ_ILL1);
+                       Xil_Out32(0xFD4000F4, temp_tx_dig_tm_61);
+                       Xil_Out32(0xFD40106C, temp_tm_dig_6);
+                       Xil_Out32(0xFD401928, Xil_In32(0xFD401924));
+                       temp_ill12 =
+                           temp_ill12 | (Xil_In32(0xFD401990) >> 4 & 0xF);
+                       Xil_Out32(0xFD401990, temp_ill12);
+                       Xil_Out32(0xFD401924, temp_TM_E_ILL1);
+               }
+               if (lane1_protocol == 2) {
+                       temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD406360);
+                       Xil_Out32(0xFD406360, 0x0);
+                       temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410004);
+                       psu_mask_write(0xFD410004, 0x0000001FU, 0x0000000DU);
+                       temp_TM_IQ_ILL1 = Xil_In32(0xFD4058F8);
+                       temp_TM_E_ILL1 = Xil_In32(0xFD405924);
+                       Xil_Out32(0xFD4058F8, 0x78);
+                       temp_tx_dig_tm_61 = Xil_In32(0xFD4040F4);
+                       temp_tm_dig_6 = Xil_In32(0xFD40506C);
+                       psu_mask_write(0xFD4040F4, 0x0000000BU, 0x00000000U);
+                       psu_mask_write(0xFD40506C, 0x0000000FU, 0x00000000U);
+                       temp_ill12 = Xil_In32(0xFD405990) & 0xF0;
+
+                       serdes_illcalib_pcie_gen1(0, 0, 0, 0, 1, 0, 0, 0, 0);
+
+                       Xil_Out32(0xFD406360, temp_pll_fbdiv_frac_3_msb_offset);
+                       Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+                       Xil_Out32(0xFD4058F8, temp_TM_IQ_ILL1);
+                       Xil_Out32(0xFD4040F4, temp_tx_dig_tm_61);
+                       Xil_Out32(0xFD40506C, temp_tm_dig_6);
+                       Xil_Out32(0xFD405928, Xil_In32(0xFD405924));
+                       temp_ill12 =
+                           temp_ill12 | (Xil_In32(0xFD405990) >> 4 & 0xF);
+                       Xil_Out32(0xFD405990, temp_ill12);
+                       Xil_Out32(0xFD405924, temp_TM_E_ILL1);
+               }
+               if (lane2_protocol == 2) {
+                       temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD40A360);
+                       Xil_Out32(0xFD40A360, 0x0);
+                       temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410008);
+                       psu_mask_write(0xFD410008, 0x0000001FU, 0x0000000DU);
+                       temp_TM_IQ_ILL1 = Xil_In32(0xFD4098F8);
+                       temp_TM_E_ILL1 = Xil_In32(0xFD409924);
+                       Xil_Out32(0xFD4098F8, 0x78);
+                       temp_tx_dig_tm_61 = Xil_In32(0xFD4080F4);
+                       temp_tm_dig_6 = Xil_In32(0xFD40906C);
+                       psu_mask_write(0xFD4080F4, 0x0000000BU, 0x00000000U);
+                       psu_mask_write(0xFD40906C, 0x0000000FU, 0x00000000U);
+                       temp_ill12 = Xil_In32(0xFD409990) & 0xF0;
+
+                       serdes_illcalib_pcie_gen1(0, 0, 1, 0, 0, 0, 0, 0, 0);
+
+                       Xil_Out32(0xFD40A360, temp_pll_fbdiv_frac_3_msb_offset);
+                       Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+                       Xil_Out32(0xFD4098F8, temp_TM_IQ_ILL1);
+                       Xil_Out32(0xFD4080F4, temp_tx_dig_tm_61);
+                       Xil_Out32(0xFD40906C, temp_tm_dig_6);
+                       Xil_Out32(0xFD409928, Xil_In32(0xFD409924));
+                       temp_ill12 =
+                           temp_ill12 | (Xil_In32(0xFD409990) >> 4 & 0xF);
+                       Xil_Out32(0xFD409990, temp_ill12);
+                       Xil_Out32(0xFD409924, temp_TM_E_ILL1);
+               }
+               if (lane3_protocol == 2) {
+                       temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD40E360);
+                       Xil_Out32(0xFD40E360, 0x0);
+                       temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD41000C);
+                       psu_mask_write(0xFD41000C, 0x0000001FU, 0x0000000DU);
+                       temp_TM_IQ_ILL1 = Xil_In32(0xFD40D8F8);
+                       temp_TM_E_ILL1 = Xil_In32(0xFD40D924);
+                       Xil_Out32(0xFD40D8F8, 0x78);
+                       temp_tx_dig_tm_61 = Xil_In32(0xFD40C0F4);
+                       temp_tm_dig_6 = Xil_In32(0xFD40D06C);
+                       psu_mask_write(0xFD40C0F4, 0x0000000BU, 0x00000000U);
+                       psu_mask_write(0xFD40D06C, 0x0000000FU, 0x00000000U);
+                       temp_ill12 = Xil_In32(0xFD40D990) & 0xF0;
+
+                       serdes_illcalib_pcie_gen1(1, 0, 0, 0, 0, 0, 0, 0, 0);
+
+                       Xil_Out32(0xFD40E360, temp_pll_fbdiv_frac_3_msb_offset);
+                       Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+                       Xil_Out32(0xFD40D8F8, temp_TM_IQ_ILL1);
+                       Xil_Out32(0xFD40C0F4, temp_tx_dig_tm_61);
+                       Xil_Out32(0xFD40D06C, temp_tm_dig_6);
+                       Xil_Out32(0xFD40D928, Xil_In32(0xFD40D924));
+                       temp_ill12 =
+                           temp_ill12 | (Xil_In32(0xFD40D990) >> 4 & 0xF);
+                       Xil_Out32(0xFD40D990, temp_ill12);
+                       Xil_Out32(0xFD40D924, temp_TM_E_ILL1);
+               }
+               rdata = Xil_In32(0xFD410098);
+               rdata = (rdata & 0xDF);
+               Xil_Out32(0xFD410098, rdata);
+       }
+
+       if (lane0_protocol == 2 && lane0_rate == 3) {
+               psu_mask_write(0xFD40198C, 0x000000F0U, 0x00000020U);
+               psu_mask_write(0xFD40192C, 0x000000FFU, 0x00000094U);
+       }
+       if (lane1_protocol == 2 && lane1_rate == 3) {
+               psu_mask_write(0xFD40598C, 0x000000F0U, 0x00000020U);
+               psu_mask_write(0xFD40592C, 0x000000FFU, 0x00000094U);
+       }
+       if (lane2_protocol == 2 && lane2_rate == 3) {
+               psu_mask_write(0xFD40998C, 0x000000F0U, 0x00000020U);
+               psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000094U);
+       }
+       if (lane3_protocol == 2 && lane3_rate == 3) {
+               psu_mask_write(0xFD40D98C, 0x000000F0U, 0x00000020U);
+               psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000094U);
+       }
+
+       if (lane0_protocol == 1) {
+               if (lane0_rate == 0) {
+                       serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+                                                 lane2_protocol, lane2_rate,
+                                                 lane1_protocol, lane1_rate,
+                                                 lane0_protocol, 0, 0);
+               } else {
+                       serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+                                                 lane2_protocol, lane2_rate,
+                                                 lane1_protocol, lane1_rate,
+                                                 lane0_protocol, 0, 0);
+                       serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+                                                 lane2_protocol, lane2_rate,
+                                                 lane1_protocol, lane1_rate,
+                                                 lane0_protocol, lane0_rate,
+                                                 1);
+               }
+       }
+
+       if (lane0_protocol == 3)
+               Xil_Out32(0xFD401914, 0xF3);
+       if (lane0_protocol == 3)
+               Xil_Out32(0xFD401940, 0xF3);
+       if (lane0_protocol == 3)
+               Xil_Out32(0xFD401990, 0x20);
+       if (lane0_protocol == 3)
+               Xil_Out32(0xFD401924, 0x37);
+
+       if (lane1_protocol == 3)
+               Xil_Out32(0xFD405914, 0xF3);
+       if (lane1_protocol == 3)
+               Xil_Out32(0xFD405940, 0xF3);
+       if (lane1_protocol == 3)
+               Xil_Out32(0xFD405990, 0x20);
+       if (lane1_protocol == 3)
+               Xil_Out32(0xFD405924, 0x37);
+
+       if (lane2_protocol == 3)
+               Xil_Out32(0xFD409914, 0xF3);
+       if (lane2_protocol == 3)
+               Xil_Out32(0xFD409940, 0xF3);
+       if (lane2_protocol == 3)
+               Xil_Out32(0xFD409990, 0x20);
+       if (lane2_protocol == 3)
+               Xil_Out32(0xFD409924, 0x37);
+
+       if (lane3_protocol == 3)
+               Xil_Out32(0xFD40D914, 0xF3);
+       if (lane3_protocol == 3)
+               Xil_Out32(0xFD40D940, 0xF3);
+       if (lane3_protocol == 3)
+               Xil_Out32(0xFD40D990, 0x20);
+       if (lane3_protocol == 3)
+               Xil_Out32(0xFD40D924, 0x37);
+
+       return 1;
+}
+
+static int serdes_enb_coarse_saturation(void)
+{
+       Xil_Out32(0xFD402094, 0x00000010);
+       Xil_Out32(0xFD406094, 0x00000010);
+       Xil_Out32(0xFD40A094, 0x00000010);
+       Xil_Out32(0xFD40E094, 0x00000010);
+       return 1;
+}
+
+static int serdes_fixcal_code(void)
+{
+       int maskstatus = 1;
+       unsigned int rdata = 0;
+       unsigned int match_pmos_code[23];
+       unsigned int match_nmos_code[23];
+       unsigned int match_ical_code[7];
+       unsigned int match_rcal_code[7];
+       unsigned int p_code = 0;
+       unsigned int n_code = 0;
+       unsigned int i_code = 0;
+       unsigned int r_code = 0;
+       unsigned int repeat_count = 0;
+       unsigned int L3_TM_CALIB_DIG20 = 0;
+       unsigned int L3_TM_CALIB_DIG19 = 0;
+       unsigned int L3_TM_CALIB_DIG18 = 0;
+       unsigned int L3_TM_CALIB_DIG16 = 0;
+       unsigned int L3_TM_CALIB_DIG15 = 0;
+       unsigned int L3_TM_CALIB_DIG14 = 0;
+       int i = 0;
+       int count = 0;
+
+       rdata = Xil_In32(0xFD40289C);
+       rdata = rdata & ~0x03;
+       rdata = rdata | 0x1;
+       Xil_Out32(0xFD40289C, rdata);
+
+       do {
+               if (count == 1100000)
+                       break;
+               rdata = Xil_In32(0xFD402B1C);
+               count++;
+       } while ((rdata & 0x0000000E) != 0x0000000E);
+
+       for (i = 0; i < 23; i++) {
+               match_pmos_code[i] = 0;
+               match_nmos_code[i] = 0;
+       }
+       for (i = 0; i < 7; i++) {
+               match_ical_code[i] = 0;
+               match_rcal_code[i] = 0;
+       }
+
+       do {
+               Xil_Out32(0xFD410010, 0x00000000);
+               Xil_Out32(0xFD410014, 0x00000000);
+
+               Xil_Out32(0xFD410010, 0x00000001);
+               Xil_Out32(0xFD410014, 0x00000000);
+
+               maskstatus = mask_poll(0xFD40EF14, 0x2);
+               if (maskstatus == 0) {
+                       xil_printf("#SERDES initialization timed out\n\r");
+                       return maskstatus;
+               }
+
+               p_code = mask_read(0xFD40EF18, 0xFFFFFFFF);
+               n_code = mask_read(0xFD40EF1C, 0xFFFFFFFF);
+               ;
+               i_code = mask_read(0xFD40EF24, 0xFFFFFFFF);
+               r_code = mask_read(0xFD40EF28, 0xFFFFFFFF);
+               ;
+
+               if (p_code >= 0x26 && p_code <= 0x3C)
+                       match_pmos_code[p_code - 0x26] += 1;
+
+               if (n_code >= 0x26 && n_code <= 0x3C)
+                       match_nmos_code[n_code - 0x26] += 1;
+
+               if (i_code >= 0xC && i_code <= 0x12)
+                       match_ical_code[i_code - 0xc] += 1;
+
+               if (r_code >= 0x6 && r_code <= 0xC)
+                       match_rcal_code[r_code - 0x6] += 1;
+
+       } while (repeat_count++ < 10);
+
+       for (i = 0; i < 23; i++) {
+               if (match_pmos_code[i] >= match_pmos_code[0]) {
+                       match_pmos_code[0] = match_pmos_code[i];
+                       p_code = 0x26 + i;
+               }
+               if (match_nmos_code[i] >= match_nmos_code[0]) {
+                       match_nmos_code[0] = match_nmos_code[i];
+                       n_code = 0x26 + i;
+               }
+       }
+
+       for (i = 0; i < 7; i++) {
+               if (match_ical_code[i] >= match_ical_code[0]) {
+                       match_ical_code[0] = match_ical_code[i];
+                       i_code = 0xC + i;
+               }
+               if (match_rcal_code[i] >= match_rcal_code[0]) {
+                       match_rcal_code[0] = match_rcal_code[i];
+                       r_code = 0x6 + i;
+               }
+       }
+
+       L3_TM_CALIB_DIG20 = mask_read(0xFD40EC50, 0xFFFFFFF0);
+       L3_TM_CALIB_DIG20 = L3_TM_CALIB_DIG20 | 0x8 | ((p_code >> 2) & 0x7);
+
+       L3_TM_CALIB_DIG19 = mask_read(0xFD40EC4C, 0xFFFFFF18);
+       L3_TM_CALIB_DIG19 = L3_TM_CALIB_DIG19 | ((p_code & 0x3) << 6)
+           | 0x20 | 0x4 | ((n_code >> 3) & 0x3);
+
+       L3_TM_CALIB_DIG18 = mask_read(0xFD40EC48, 0xFFFFFF0F);
+       L3_TM_CALIB_DIG18 = L3_TM_CALIB_DIG18 | ((n_code & 0x7) << 5) | 0x10;
+
+       L3_TM_CALIB_DIG16 = mask_read(0xFD40EC40, 0xFFFFFFF8);
+       L3_TM_CALIB_DIG16 = L3_TM_CALIB_DIG16 | ((r_code >> 1) & 0x7);
+
+       L3_TM_CALIB_DIG15 = mask_read(0xFD40EC3C, 0xFFFFFF30);
+       L3_TM_CALIB_DIG15 = L3_TM_CALIB_DIG15 | ((r_code & 0x1) << 7)
+           | 0x40 | 0x8 | ((i_code >> 1) & 0x7);
+
+       L3_TM_CALIB_DIG14 = mask_read(0xFD40EC38, 0xFFFFFF3F);
+       L3_TM_CALIB_DIG14 = L3_TM_CALIB_DIG14 | ((i_code & 0x1) << 7) | 0x40;
+
+       Xil_Out32(0xFD40EC50, L3_TM_CALIB_DIG20);
+       Xil_Out32(0xFD40EC4C, L3_TM_CALIB_DIG19);
+       Xil_Out32(0xFD40EC48, L3_TM_CALIB_DIG18);
+       Xil_Out32(0xFD40EC40, L3_TM_CALIB_DIG16);
+       Xil_Out32(0xFD40EC3C, L3_TM_CALIB_DIG15);
+       Xil_Out32(0xFD40EC38, L3_TM_CALIB_DIG14);
+       return maskstatus;
+}
+
+static int init_serdes(void)
+{
+       int status = 1;
+
+       status &= psu_resetin_init_data();
+
+       status &= serdes_fixcal_code();
+       status &= serdes_enb_coarse_saturation();
+
+       status &= psu_serdes_init_data();
+       status &= psu_resetout_init_data();
+
+       return status;
+}
+
+static void init_peripheral(void)
+{
+       psu_mask_write(0xFD5F0018, 0x8000001FU, 0x8000001FU);
+}
+
+int psu_init(void)
+{
+       int status = 1;
+
+       status &= psu_mio_init_data();
+       status &= psu_peripherals_pre_init_data();
+       status &= psu_pll_init_data();
+       status &= psu_clock_init_data();
+
+       status &= psu_ddr_init_data();
+       status &= psu_ddr_phybringup_data();
+
+       status &= psu_peripherals_init_data();
+       status &= init_serdes();
+       init_peripheral();
+
+       status &= psu_afi_config();
+       psu_ddr_qos_init_data();
+
+       if (status == 0)
+               return 1;
+       return 0;
+}
index 4466717..23c12f4 100644 (file)
@@ -436,7 +436,7 @@ int dram_init(void)
 }
 #endif
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
index 863b7f9..9bf5e86 100644 (file)
@@ -2031,12 +2031,19 @@ config HASH_VERIFY
        help
          Add -v option to verify data against a hash.
 
+config CMD_SCP03
+       bool "scp03 - SCP03 enable and rotate/provision operations"
+       depends on SCP03
+       help
+         This command provides access to a Trusted Application
+         running in a TEE to request Secure Channel Protocol 03
+         (SCP03) enablement and/or rotation of its SCP03 keys.
+
 config CMD_TPM_V1
        bool
 
 config CMD_TPM_V2
        bool
-       select CMD_LOG
 
 config CMD_TPM
        bool "Enable the 'tpm' command"
@@ -2245,6 +2252,15 @@ config CMD_BEDBUG
          for some PowerPC processors. For details please see the
          documentation in doc/README.bedbug.
 
+config CMD_CBSYSINFO
+       bool "cbsysinfo"
+       depends on X86
+       default y if SYS_COREBOOT
+       help
+         This provides information about the coreboot sysinfo table stored in
+         memory by coreboot before jumping to U-Boot. It can be useful for
+         debugging the beaaviour of coreboot or U-Boot.
+
 config CMD_DIAG
        bool "diag - Board diagnostics"
        help
index 567e2b7..e606ac4 100644 (file)
@@ -194,6 +194,9 @@ obj-$(CONFIG_CMD_BLOB) += blob.o
 # Android Verified Boot 2.0
 obj-$(CONFIG_CMD_AVB) += avb.o
 
+# Foundries.IO SCP03
+obj-$(CONFIG_CMD_SCP03) += scp03.o
+
 obj-$(CONFIG_ARM) += arm/
 obj-$(CONFIG_RISCV) += riscv/
 obj-$(CONFIG_SANDBOX) += sandbox/
index 157261b..e5b9a17 100644 (file)
@@ -187,10 +187,12 @@ static int do_acpi_dump(struct cmd_tbl *cmdtp, int flag, int argc,
        return 0;
 }
 
+#ifdef CONFIG_SYS_LONGHELP
 static char acpi_help_text[] =
        "list - list ACPI tables\n"
        "acpi items [-d]  - List/dump each piece of ACPI data from devices\n"
        "acpi dump <name> - Dump ACPI table";
+#endif
 
 U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text,
        U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list),
index 97b5734..21e7ff6 100644 (file)
@@ -29,9 +29,11 @@ static int do_bloblist_list(struct cmd_tbl *cmdtp, int flag, int argc,
        return 0;
 }
 
+#ifdef CONFIG_SYS_LONGHELP
 static char bloblist_help_text[] =
        "info   - show information about the bloblist\n"
        "bloblist list   - list blobs in the bloblist";
+#endif
 
 U_BOOT_CMD_WITH_SUBCMDS(bloblist, "Bloblists", bloblist_help_text,
        U_BOOT_SUBCMD_MKENT(info, 1, 1, do_bloblist_info),
index 271b385..cba81ff 100644 (file)
@@ -358,6 +358,9 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
 
        free(load_options);
 
+       if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD))
+               efi_initrd_deregister();
+
        return ret;
 }
 
index 55c7abe..6e36575 100644 (file)
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <command.h>
 #include <efi_dt_fixup.h>
+#include <efi_load_initrd.h>
 #include <efi_loader.h>
 #include <efi_rng.h>
 #include <exports.h>
@@ -19,6 +20,7 @@
 #include <part.h>
 #include <search.h>
 #include <linux/ctype.h>
+#include <linux/err.h>
 
 #define BS systab.boottime
 #define RT systab.runtime
@@ -129,6 +131,82 @@ static int do_efi_capsule_show(struct cmd_tbl *cmdtp, int flag,
        return CMD_RET_SUCCESS;
 }
 
+#ifdef CONFIG_EFI_ESRT
+
+#define EFI_ESRT_FW_TYPE_NUM 4
+char *efi_fw_type_str[EFI_ESRT_FW_TYPE_NUM] = {"unknown", "system FW", "device FW",
+        "UEFI driver"};
+
+#define EFI_ESRT_UPDATE_STATUS_NUM 9
+char *efi_update_status_str[EFI_ESRT_UPDATE_STATUS_NUM] = {"success", "unsuccessful",
+       "insufficient resources", "incorrect version", "invalid format",
+       "auth error", "power event (AC)", "power event (batt)",
+       "unsatisfied dependencies"};
+
+#define EFI_FW_TYPE_STR_GET(idx) (\
+EFI_ESRT_FW_TYPE_NUM > (idx) ? efi_fw_type_str[(idx)] : "error"\
+)
+
+#define EFI_FW_STATUS_STR_GET(idx) (\
+EFI_ESRT_UPDATE_STATUS_NUM  > (idx) ? efi_update_status_str[(idx)] : "error"\
+)
+
+/**
+ * do_efi_capsule_esrt() - manage UEFI capsules
+ *
+ * @cmdtp:     Command table
+ * @flag:      Command flag
+ * @argc:      Number of arguments
+ * @argv:      Argument array
+ * Return:     CMD_RET_SUCCESS on success,
+ *             CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule esrt" sub-command.
+ * The prints the current ESRT table.
+ *
+ *     efidebug capsule esrt
+ */
+static int do_efi_capsule_esrt(struct cmd_tbl *cmdtp, int flag,
+                              int argc, char * const argv[])
+{
+       struct efi_system_resource_table *esrt = NULL;
+
+       if (argc != 1)
+               return CMD_RET_USAGE;
+
+       for (int idx = 0; idx < systab.nr_tables; idx++)
+               if (!guidcmp(&efi_esrt_guid, &systab.tables[idx].guid))
+                       esrt = (struct efi_system_resource_table *)systab.tables[idx].table;
+
+       if (!esrt) {
+               log_info("ESRT: table not present\n");
+               return CMD_RET_SUCCESS;
+       }
+
+       printf("========================================\n");
+       printf("ESRT: fw_resource_count=%d\n", esrt->fw_resource_count);
+       printf("ESRT: fw_resource_count_max=%d\n", esrt->fw_resource_count_max);
+       printf("ESRT: fw_resource_version=%lld\n", esrt->fw_resource_version);
+
+       for (int idx = 0; idx < esrt->fw_resource_count; idx++) {
+               printf("[entry %d]==============================\n", idx);
+               printf("ESRT: fw_class=%pUL\n", &esrt->entries[idx].fw_class);
+               printf("ESRT: fw_type=%s\n", EFI_FW_TYPE_STR_GET(esrt->entries[idx].fw_type));
+               printf("ESRT: fw_version=%d\n", esrt->entries[idx].fw_version);
+               printf("ESRT: lowest_supported_fw_version=%d\n",
+                      esrt->entries[idx].lowest_supported_fw_version);
+               printf("ESRT: capsule_flags=%d\n",
+                      esrt->entries[idx].capsule_flags);
+               printf("ESRT: last_attempt_version=%d\n",
+                      esrt->entries[idx].last_attempt_version);
+               printf("ESRT: last_attempt_status=%s\n",
+                      EFI_FW_STATUS_STR_GET(esrt->entries[idx].last_attempt_status));
+       }
+       printf("========================================\n");
+
+       return CMD_RET_SUCCESS;
+}
+#endif /*  CONFIG_EFI_ESRT */
 /**
  * do_efi_capsule_res() - show a capsule update result
  *
@@ -221,6 +299,10 @@ static struct cmd_tbl cmd_efidebug_capsule_sub[] = {
                         "", ""),
        U_BOOT_CMD_MKENT(show, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_show,
                         "", ""),
+#ifdef CONFIG_EFI_ESRT
+       U_BOOT_CMD_MKENT(esrt, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_esrt,
+                        "", ""),
+#endif
        U_BOOT_CMD_MKENT(disk-update, 0, 0, do_efi_capsule_on_disk_update,
                         "", ""),
        U_BOOT_CMD_MKENT(result, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_res,
@@ -517,6 +599,10 @@ static const struct {
                EFI_ACPI_TABLE_GUID,
        },
        {
+               "EFI System Resource Table",
+               EFI_SYSTEM_RESOURCE_TABLE_GUID,
+       },
+       {
                "device tree",
                EFI_FDT_GUID,
        },
@@ -799,6 +885,54 @@ static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
 }
 
 /**
+ * create_initrd_dp() - Create a special device for our Boot### option
+ *
+ * @dev:       Device
+ * @part:      Disk partition
+ * @file:      Filename
+ * Return:     Pointer to the device path or ERR_PTR
+ *
+ */
+static
+struct efi_device_path *create_initrd_dp(const char *dev, const char *part,
+                                        const char *file)
+
+{
+       struct efi_device_path *tmp_dp = NULL, *tmp_fp = NULL;
+       struct efi_device_path *initrd_dp = NULL;
+       efi_status_t ret;
+       const struct efi_initrd_dp id_dp = {
+               .vendor = {
+                       {
+                       DEVICE_PATH_TYPE_MEDIA_DEVICE,
+                       DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
+                       sizeof(id_dp.vendor),
+                       },
+                       EFI_INITRD_MEDIA_GUID,
+               },
+               .end = {
+                       DEVICE_PATH_TYPE_END,
+                       DEVICE_PATH_SUB_TYPE_END,
+                       sizeof(id_dp.end),
+               }
+       };
+
+       ret = efi_dp_from_name(dev, part, file, &tmp_dp, &tmp_fp);
+       if (ret != EFI_SUCCESS) {
+               printf("Cannot create device path for \"%s %s\"\n", part, file);
+               goto out;
+       }
+
+       initrd_dp = efi_dp_append((const struct efi_device_path *)&id_dp,
+                                 tmp_fp);
+
+out:
+       efi_free_pool(tmp_dp);
+       efi_free_pool(tmp_fp);
+       return initrd_dp;
+}
+
+/**
  * do_efi_boot_add() - set UEFI load option
  *
  * @cmdtp:     Command table
@@ -810,7 +944,9 @@ static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
  *
  * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
  *
- *     efidebug boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
+ * efidebug boot add -b <id> <label> <interface> <devnum>[:<part>] <file>
+ *                   -i <file> <interface2> <devnum2>[:<part>] <initrd>
+ *                   -s '<options>'
  */
 static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
                           int argc, char *const argv[])
@@ -823,55 +959,105 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
        size_t label_len, label_len16;
        u16 *label;
        struct efi_device_path *device_path = NULL, *file_path = NULL;
+       struct efi_device_path *final_fp = NULL;
+       struct efi_device_path *initrd_dp = NULL;
        struct efi_load_option lo;
        void *data = NULL;
        efi_uintn_t size;
+       efi_uintn_t fp_size = 0;
        efi_status_t ret;
        int r = CMD_RET_SUCCESS;
 
-       if (argc < 6 || argc > 7)
-               return CMD_RET_USAGE;
-
-       id = (int)simple_strtoul(argv[1], &endp, 16);
-       if (*endp != '\0' || id > 0xffff)
-               return CMD_RET_USAGE;
-
-       sprintf(var_name, "Boot%04X", id);
-       p = var_name16;
-       utf8_utf16_strncpy(&p, var_name, 9);
-
        guid = efi_global_variable_guid;
 
        /* attributes */
        lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
+       lo.optional_data = NULL;
+       lo.label = NULL;
 
-       /* label */
-       label_len = strlen(argv[2]);
-       label_len16 = utf8_utf16_strnlen(argv[2], label_len);
-       label = malloc((label_len16 + 1) * sizeof(u16));
-       if (!label)
-               return CMD_RET_FAILURE;
-       lo.label = label; /* label will be changed below */
-       utf8_utf16_strncpy(&label, argv[2], label_len);
+       argc--;
+       argv++; /* 'add' */
+       for (; argc > 0; argc--, argv++) {
+               if (!strcmp(argv[0], "-b")) {
+                       if (argc <  5 || lo.label) {
+                               r = CMD_RET_USAGE;
+                               goto out;
+                       }
+                       id = (int)simple_strtoul(argv[1], &endp, 16);
+                       if (*endp != '\0' || id > 0xffff)
+                               return CMD_RET_USAGE;
+
+                       sprintf(var_name, "Boot%04X", id);
+                       p = var_name16;
+                       utf8_utf16_strncpy(&p, var_name, 9);
+
+                       /* label */
+                       label_len = strlen(argv[2]);
+                       label_len16 = utf8_utf16_strnlen(argv[2], label_len);
+                       label = malloc((label_len16 + 1) * sizeof(u16));
+                       if (!label)
+                               return CMD_RET_FAILURE;
+                       lo.label = label; /* label will be changed below */
+                       utf8_utf16_strncpy(&label, argv[2], label_len);
+
+                       /* file path */
+                       ret = efi_dp_from_name(argv[3], argv[4], argv[5],
+                                              &device_path, &file_path);
+                       if (ret != EFI_SUCCESS) {
+                               printf("Cannot create device path for \"%s %s\"\n",
+                                      argv[3], argv[4]);
+                               r = CMD_RET_FAILURE;
+                               goto out;
+                       }
+                       fp_size += efi_dp_size(file_path) +
+                               sizeof(struct efi_device_path);
+                       argc -= 5;
+                       argv += 5;
+               } else if (!strcmp(argv[0], "-i")) {
+                       if (argc < 3 || initrd_dp) {
+                               r = CMD_RET_USAGE;
+                               goto out;
+                       }
 
-       /* file path */
-       ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
-                              &file_path);
-       if (ret != EFI_SUCCESS) {
-               printf("Cannot create device path for \"%s %s\"\n",
-                      argv[3], argv[4]);
+                       initrd_dp = create_initrd_dp(argv[1], argv[2], argv[3]);
+                       if (!initrd_dp) {
+                               printf("Cannot add an initrd\n");
+                               r = CMD_RET_FAILURE;
+                               goto out;
+                       }
+                       argc -= 3;
+                       argv += 3;
+                       fp_size += efi_dp_size(initrd_dp) +
+                               sizeof(struct efi_device_path);
+               } else if (!strcmp(argv[0], "-s")) {
+                       if (argc < 1 || lo.optional_data) {
+                               r = CMD_RET_USAGE;
+                               goto out;
+                       }
+                       lo.optional_data = (const u8 *)argv[1];
+                       argc -= 1;
+                       argv += 1;
+               } else {
+                       r = CMD_RET_USAGE;
+                       goto out;
+               }
+       }
+
+       if (!file_path) {
+               printf("Missing binary\n");
+               r = CMD_RET_USAGE;
+               goto out;
+       }
+
+       final_fp = efi_dp_concat(file_path, initrd_dp);
+       if (!final_fp) {
+               printf("Cannot create final device path\n");
                r = CMD_RET_FAILURE;
                goto out;
        }
-       lo.file_path = file_path;
-       lo.file_path_length = efi_dp_size(file_path)
-                               + sizeof(struct efi_device_path); /* for END */
 
-       /* optional data */
-       if (argc == 6)
-               lo.optional_data = NULL;
-       else
-               lo.optional_data = (const u8 *)argv[6];
+       lo.file_path = final_fp;
+       lo.file_path_length = fp_size;
 
        size = efi_serialize_load_option(&lo, (u8 **)&data);
        if (!size) {
@@ -888,8 +1074,11 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
                printf("Cannot set %ls\n", var_name16);
                r = CMD_RET_FAILURE;
        }
+
 out:
        free(data);
+       efi_free_pool(final_fp);
+       efi_free_pool(initrd_dp);
        efi_free_pool(device_path);
        efi_free_pool(file_path);
        free(lo.label);
@@ -955,11 +1144,14 @@ static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag,
  */
 static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
 {
+       struct efi_device_path *initrd_path = NULL;
        struct efi_load_option lo;
        char *label, *p;
        size_t label_len16, label_len;
        u16 *dp_str;
        efi_status_t ret;
+       efi_uintn_t initrd_dp_size;
+       const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
 
        ret = efi_deserialize_load_option(&lo, data, size);
        if (ret != EFI_SUCCESS) {
@@ -990,6 +1182,14 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
        printf("  file_path: %ls\n", dp_str);
        efi_free_pool(dp_str);
 
+       initrd_path = efi_dp_from_lo(&lo, &initrd_dp_size, lf2_initrd_guid);
+       if (initrd_path) {
+               dp_str = efi_dp_str(initrd_path);
+               printf("  initrd_path: %ls\n", dp_str);
+               efi_free_pool(dp_str);
+               efi_free_pool(initrd_path);
+       }
+
        printf("  data:\n");
        print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
                       lo.optional_data, *size, true);
@@ -1559,7 +1759,10 @@ static int do_efidebug(struct cmd_tbl *cmdtp, int flag,
 static char efidebug_help_text[] =
        "  - UEFI Shell-like interface to configure UEFI environment\n"
        "\n"
-       "efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
+       "efidebug boot add "
+       "-b <bootid> <label> <interface> <devnum>[:<part>] <file path> "
+       "-i <interface> <devnum>[:<part>] <initrd file path> "
+       "-s '<optional data>'\n"
        "  - set UEFI BootXXXX variable\n"
        "    <load options> will be passed to UEFI application\n"
        "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
@@ -1580,6 +1783,10 @@ static char efidebug_help_text[] =
        "  - show capsule information\n"
        "efidebug capsule result [<capsule result var>]\n"
        "  - show a capsule update result\n"
+#ifdef CONFIG_EFI_ESRT
+       "efidebug capsule esrt\n"
+       "  - print the ESRT\n"
+#endif
        "\n"
 #endif
        "efidebug devices\n"
@@ -1603,7 +1810,7 @@ static char efidebug_help_text[] =
 #endif
 
 U_BOOT_CMD(
-       efidebug, 10, 0, do_efidebug,
+       efidebug, CONFIG_SYS_MAXARGS, 0, do_efidebug,
        "Configure UEFI environment",
        efidebug_help_text
 );
index 1d21f79..6aa3d91 100644 (file)
@@ -41,17 +41,35 @@ static int do_host_save(struct cmd_tbl *cmdtp, int flag, int argc,
 static int do_host_bind(struct cmd_tbl *cmdtp, int flag, int argc,
                        char *const argv[])
 {
-       if (argc < 2 || argc > 3)
-               return CMD_RET_USAGE;
+       bool removable = false;
+       const char *dev_str;
+       char *file;
        char *ep;
-       char *dev_str = argv[1];
-       char *file = argc >= 3 ? argv[2] : NULL;
-       int dev = simple_strtoul(dev_str, &ep, 16);
+       int dev;
+
+       /* Skip 'bind' */
+       argc--;
+       argv++;
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       if (!strcmp(argv[0], "-r")) {
+               removable = true;
+               argc--;
+               argv++;
+       }
+
+       if (argc > 2)
+               return CMD_RET_USAGE;
+       dev_str = argv[0];
+       dev = simple_strtoul(dev_str, &ep, 16);
        if (*ep) {
                printf("** Bad device specification %s **\n", dev_str);
                return CMD_RET_USAGE;
        }
-       return !!host_dev_bind(dev, file);
+       file = argc > 1 ? argv[1] : NULL;
+
+       return !!host_dev_bind(dev, file, removable);
 }
 
 static int do_host_info(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -146,7 +164,7 @@ static struct cmd_tbl cmd_host_sub[] = {
        U_BOOT_CMD_MKENT(ls, 3, 0, do_host_ls, "", ""),
        U_BOOT_CMD_MKENT(save, 6, 0, do_host_save, "", ""),
        U_BOOT_CMD_MKENT(size, 3, 0, do_host_size, "", ""),
-       U_BOOT_CMD_MKENT(bind, 3, 0, do_host_bind, "", ""),
+       U_BOOT_CMD_MKENT(bind, 4, 0, do_host_bind, "", ""),
        U_BOOT_CMD_MKENT(info, 3, 0, do_host_info, "", ""),
        U_BOOT_CMD_MKENT(dev, 0, 1, do_host_dev, "", ""),
 };
@@ -178,7 +196,8 @@ U_BOOT_CMD(
        "host save hostfs - <addr> <filename> <bytes> [<offset>] - "
                "save a file to host\n"
        "host size hostfs - <filename> - determine size of file on host\n"
-       "host bind <dev> [<filename>] - bind \"host\" device to file\n"
+       "host bind [-r] <dev> [<filename>] - bind \"host\" device to file\n"
+       "     -r = mark as removable\n"
        "host info [<dev>]            - show device binding & info\n"
        "host dev [<dev>] - Set or retrieve the current host device\n"
        "host commands use the \"hostfs\" device. The \"host\" device is used\n"
diff --git a/cmd/scp03.c b/cmd/scp03.c
new file mode 100644 (file)
index 0000000..655e0bb
--- /dev/null
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <scp03.h>
+
+int do_scp03_enable(struct cmd_tbl *cmdtp, int flag, int argc,
+                   char *const argv[])
+{
+       if (argc != 1)
+               return CMD_RET_USAGE;
+
+       if (tee_enable_scp03()) {
+               printf("TEE failed to enable SCP03\n");
+               return CMD_RET_FAILURE;
+       }
+
+       printf("SCP03 is enabled\n");
+
+       return CMD_RET_SUCCESS;
+}
+
+int do_scp03_provision(struct cmd_tbl *cmdtp, int flag, int argc,
+                      char *const argv[])
+{
+       if (argc != 1)
+               return CMD_RET_USAGE;
+
+       if (tee_provision_scp03()) {
+               printf("TEE failed to provision SCP03 keys\n");
+               return CMD_RET_FAILURE;
+       }
+
+       printf("SCP03 is provisioned\n");
+
+       return CMD_RET_SUCCESS;
+}
+
+static char text[] =
+       "provides a command to enable SCP03 and provision the SCP03 keys\n"
+       " enable    - enable SCP03 on the TEE\n"
+       " provision - provision SCP03 on the TEE\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(scp03, "Secure Channel Protocol 03 control", text,
+       U_BOOT_SUBCMD_MKENT(enable, 1, 1, do_scp03_enable),
+       U_BOOT_SUBCMD_MKENT(provision, 1, 1, do_scp03_provision));
+
index 0e2168a..3a7e35d 100644 (file)
@@ -11,6 +11,7 @@
 #include <tpm-common.h>
 #include <tpm-v1.h>
 #include "tpm-user-utils.h"
+#include <tpm_api.h>
 
 static int do_tpm_startup(struct cmd_tbl *cmdtp, int flag, int argc,
                          char *const argv[])
@@ -55,7 +56,7 @@ static int do_tpm_nv_define_space(struct cmd_tbl *cmdtp, int flag, int argc,
        perm = simple_strtoul(argv[2], NULL, 0);
        size = simple_strtoul(argv[3], NULL, 0);
 
-       return report_return_code(tpm_nv_define_space(dev, index, perm, size));
+       return report_return_code(tpm1_nv_define_space(dev, index, perm, size));
 }
 
 static int do_tpm_nv_read_value(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -130,7 +131,7 @@ static int do_tpm_extend(struct cmd_tbl *cmdtp, int flag, int argc,
                return CMD_RET_FAILURE;
        }
 
-       rc = tpm_extend(dev, index, in_digest, out_digest);
+       rc = tpm_pcr_extend(dev, index, in_digest, out_digest);
        if (!rc) {
                puts("PCR value after execution of the command:\n");
                print_byte_string(out_digest, sizeof(out_digest));
@@ -304,7 +305,7 @@ static int do_tpm_nv_define(struct cmd_tbl *cmdtp, int flag, int argc,
        index = simple_strtoul(argv[2], NULL, 0);
        perm = simple_strtoul(argv[3], NULL, 0);
 
-       return report_return_code(tpm_nv_define_space(dev, index, perm, size));
+       return report_return_code(tpm1_nv_define_space(dev, index, perm, size));
 }
 
 static int do_tpm_nv_read(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -389,7 +390,7 @@ static int do_tpm_oiap(struct cmd_tbl *cmdtp, int flag, int argc,
        if (rc)
                return rc;
 
-       err = tpm_oiap(dev, &auth_handle);
+       err = tpm1_oiap(dev, &auth_handle);
 
        return report_return_code(err);
 }
@@ -461,8 +462,8 @@ static int do_tpm_load_key2_oiap(struct cmd_tbl *cmdtp, int flag, int argc,
                return CMD_RET_FAILURE;
        parse_byte_string(argv[4], usage_auth, NULL);
 
-       err = tpm_load_key2_oiap(dev, parent_handle, key, key_len, usage_auth,
-                                &key_handle);
+       err = tpm1_load_key2_oiap(dev, parent_handle, key, key_len, usage_auth,
+                                 &key_handle);
        if (!err)
                printf("Key handle is 0x%x\n", key_handle);
 
@@ -491,8 +492,8 @@ static int do_tpm_get_pub_key_oiap(struct cmd_tbl *cmdtp, int flag, int argc,
                return CMD_RET_FAILURE;
        parse_byte_string(argv[2], usage_auth, NULL);
 
-       err = tpm_get_pub_key_oiap(dev, key_handle, usage_auth, pub_key_buffer,
-                                  &pub_key_len);
+       err = tpm1_get_pub_key_oiap(dev, key_handle, usage_auth, pub_key_buffer,
+                                   &pub_key_len);
        if (!err) {
                printf("dump of received pub key structure:\n");
                print_byte_string(pub_key_buffer, pub_key_len);
@@ -500,7 +501,7 @@ static int do_tpm_get_pub_key_oiap(struct cmd_tbl *cmdtp, int flag, int argc,
        return report_return_code(err);
 }
 
-TPM_COMMAND_NO_ARG(tpm_end_oiap)
+TPM_COMMAND_NO_ARG(tpm1_end_oiap)
 
 #endif /* CONFIG_TPM_AUTH_SESSIONS */
 
@@ -562,7 +563,7 @@ static int do_tpm_flush(struct cmd_tbl *cmdtp, int flag, int argc,
                res_count = get_unaligned_be16(buf);
                ptr = buf + 2;
                for (i = 0; i < res_count; ++i, ptr += 4)
-                       tpm_flush_specific(dev, get_unaligned_be32(ptr), type);
+                       tpm1_flush_specific(dev, get_unaligned_be32(ptr), type);
        } else {
                u32 handle = simple_strtoul(argv[2], NULL, 0);
 
@@ -570,7 +571,7 @@ static int do_tpm_flush(struct cmd_tbl *cmdtp, int flag, int argc,
                        printf("Illegal resource handle %s\n", argv[2]);
                        return -1;
                }
-               tpm_flush_specific(dev, cpu_to_be32(handle), type);
+               tpm1_flush_specific(dev, cpu_to_be32(handle), type);
        }
 
        return 0;
@@ -691,7 +692,7 @@ static struct cmd_tbl tpm1_commands[] = {
        U_BOOT_CMD_MKENT(oiap, 0, 1,
                         do_tpm_oiap, "", ""),
        U_BOOT_CMD_MKENT(end_oiap, 0, 1,
-                        do_tpm_end_oiap, "", ""),
+                        do_tpm1_end_oiap, "", ""),
        U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1,
                         do_tpm_load_key2_oiap, "", ""),
 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
index ebfb25c..a3ccb12 100644 (file)
@@ -9,6 +9,7 @@
 #include <log.h>
 #include <tpm-v1.h>
 #include "tpm-user-utils.h"
+#include <tpm_api.h>
 
 /* Prints error and returns on failure */
 #define TPM_CHECK(tpm_command) do { \
@@ -49,7 +50,7 @@ static uint32_t tpm_get_flags(struct udevice *dev, uint8_t *disable,
        struct tpm_permanent_flags pflags;
        uint32_t result;
 
-       result = tpm_get_permanent_flags(dev, &pflags);
+       result = tpm1_get_permanent_flags(dev, &pflags);
        if (result)
                return result;
        if (disable)
@@ -90,7 +91,7 @@ static int test_early_extend(struct udevice *dev)
        tpm_init(dev);
        TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
        TPM_CHECK(tpm_continue_self_test(dev));
-       TPM_CHECK(tpm_extend(dev, 1, value_in, value_out));
+       TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, value_out));
        printf("done\n");
        return 0;
 }
@@ -146,7 +147,7 @@ static int test_enable(struct udevice *dev)
 
 #define reboot() do { \
        printf("\trebooting...\n"); \
-       reset_cpu(0); \
+       reset_cpu(); \
 } while (0)
 
 static int test_fast_enable(struct udevice *dev)
@@ -238,18 +239,18 @@ static void initialise_spaces(struct udevice *dev)
        uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
 
        printf("\tInitialising spaces\n");
-       tpm_nv_set_locked(dev);  /* useful only the first time */
-       tpm_nv_define_space(dev, INDEX0, perm, 4);
+       tpm1_nv_set_locked(dev);  /* useful only the first time */
+       tpm1_nv_define_space(dev, INDEX0, perm, 4);
        tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero, 4);
-       tpm_nv_define_space(dev, INDEX1, perm, 4);
+       tpm1_nv_define_space(dev, INDEX1, perm, 4);
        tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero, 4);
-       tpm_nv_define_space(dev, INDEX2, perm, 4);
+       tpm1_nv_define_space(dev, INDEX2, perm, 4);
        tpm_nv_write_value(dev, INDEX2, (uint8_t *)&zero, 4);
-       tpm_nv_define_space(dev, INDEX3, perm, 4);
+       tpm1_nv_define_space(dev, INDEX3, perm, 4);
        tpm_nv_write_value(dev, INDEX3, (uint8_t *)&zero, 4);
        perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
                TPM_NV_PER_PPWRITE;
-       tpm_nv_define_space(dev, INDEX_INITIALISED, perm, 1);
+       tpm1_nv_define_space(dev, INDEX_INITIALISED, perm, 1);
 }
 
 static int test_readonly(struct udevice *dev)
@@ -325,30 +326,33 @@ static int test_redefine_unowned(struct udevice *dev)
 
        /* Redefines spaces a couple of times. */
        perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
-       TPM_CHECK(tpm_nv_define_space(dev, INDEX0, perm, 2 * sizeof(uint32_t)));
-       TPM_CHECK(tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)));
+       TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm,
+                                      2 * sizeof(uint32_t)));
+       TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)));
        perm = TPM_NV_PER_PPWRITE;
-       TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, 2 * sizeof(uint32_t)));
-       TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
+       TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm,
+                                      2 * sizeof(uint32_t)));
+       TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
 
        /* Sets the global lock */
        tpm_set_global_lock(dev);
 
        /* Verifies that index0 cannot be redefined */
-       result = tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
+       result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
        assert(result == TPM_AREA_LOCKED);
 
        /* Checks that index1 can */
-       TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, 2 * sizeof(uint32_t)));
-       TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
+       TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm,
+                                      2 * sizeof(uint32_t)));
+       TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
 
        /* Turns off PP */
        tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
 
        /* Verifies that neither index0 nor index1 can be redefined */
-       result = tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
+       result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
        assert(result == TPM_BAD_PRESENCE);
-       result = tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t));
+       result = tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t));
        assert(result == TPM_BAD_PRESENCE);
 
        printf("done\n");
@@ -434,7 +438,7 @@ static int test_timing(struct udevice *dev)
                   100);
        TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
                   100);
-       TTPM_CHECK(tpm_extend(dev, 0, in, out), 200);
+       TTPM_CHECK(tpm_pcr_extend(dev, 0, in, out), 200);
        TTPM_CHECK(tpm_set_global_lock(dev), 50);
        TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
        printf("done\n");
index 3686b87..685b458 100644 (file)
@@ -9,7 +9,7 @@
 #include <version.h>
 #include <linux/compiler.h>
 #ifdef CONFIG_SYS_COREBOOT
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 #endif
 
 const char __weak version_string[] = U_BOOT_VERSION_STRING;
index 144b1cf..5f82204 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0+
 
+obj-$(CONFIG_CMD_CBSYSINFO) += cbsysinfo.o
 obj-y += mtrr.o
 obj-$(CONFIG_CMD_EXCEPTION) += exception.o
 obj-$(CONFIG_USE_HOB) += hob.o
diff --git a/cmd/x86/cbsysinfo.c b/cmd/x86/cbsysinfo.c
new file mode 100644 (file)
index 0000000..a0db0ad
--- /dev/null
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <command.h>
+#include <console.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void cbprompt(const char *name)
+{
+       for (; *name == '>'; name++)
+               puts("   ");
+       printf("%-12s: ", name);
+}
+
+static void print_dec(const char *name, int value)
+{
+       cbprompt(name);
+       printf(value > 9 ? "0d%d\n" : "%d\n", value);
+}
+
+static void print_hex(const char *name, int value)
+{
+       cbprompt(name);
+       printf("%x\n", value);
+}
+
+static void print_addr(const char *name, ulong value)
+{
+       cbprompt(name);
+       printf("%08lx\n", value);
+}
+
+static void print_addr64(const char *name, u64 value)
+{
+       cbprompt(name);
+       printf("%16llx\n", value);
+}
+
+static void print_ptr(const char *name, const void *value)
+{
+       cbprompt(name);
+       printf("%p\n", value);
+}
+
+static void print_str(const char *name, const char *value)
+{
+       if (value) {
+               cbprompt(name);
+               printf("%s\n", value);
+       }
+}
+
+static void print_idx(const char *name, uint idx, const u8 *strings)
+{
+       const char *ptr;
+
+       cbprompt(name);
+       ptr = (char *)strings + idx;
+       printf("%d: %s\n", idx, ptr ? ptr : "(unknown)");
+}
+
+static const char *const cb_mem_name[] = {
+       NULL,
+       "ram",
+       "reserved",
+       "acpi",
+       "nvs",
+       "unusable",
+       "vendor",
+};
+
+static const char *get_mem_name(int tag)
+{
+       if (tag >= CB_MEM_RAM && tag <= CB_MEM_VENDOR_RSVD)
+               return cb_mem_name[tag];
+
+       if (tag == CB_MEM_TABLE)
+               return "table";
+
+       return "(unknown)";
+}
+
+static const struct timestamp_id_to_name {
+       uint id;
+       const char *name;
+} timestamp_ids[] = {
+       /* Marker to report base_time */
+       { 0,                    "1st timestamp" },
+       { TS_START_ROMSTAGE,    "start of romstage" },
+       { TS_BEFORE_INITRAM,    "before ram initialization" },
+       { TS_AFTER_INITRAM,     "after ram initialization" },
+       { TS_END_ROMSTAGE,      "end of romstage" },
+       { TS_START_VBOOT,       "start of verified boot" },
+       { TS_END_VBOOT,         "end of verified boot" },
+       { TS_START_COPYRAM,     "starting to load ramstage" },
+       { TS_END_COPYRAM,       "finished loading ramstage" },
+       { TS_START_RAMSTAGE,    "start of ramstage" },
+       { TS_START_BOOTBLOCK,   "start of bootblock" },
+       { TS_END_BOOTBLOCK,     "end of bootblock" },
+       { TS_START_COPYROM,     "starting to load romstage" },
+       { TS_END_COPYROM,       "finished loading romstage" },
+       { TS_START_ULZMA,       "starting LZMA decompress (ignore for x86)" },
+       { TS_END_ULZMA,         "finished LZMA decompress (ignore for x86)" },
+       { TS_START_ULZ4F,       "starting LZ4 decompress (ignore for x86)" },
+       { TS_END_ULZ4F,         "finished LZ4 decompress (ignore for x86)" },
+       { TS_DEVICE_ENUMERATE,  "device enumeration" },
+       { TS_DEVICE_CONFIGURE,  "device configuration" },
+       { TS_DEVICE_ENABLE,     "device enable" },
+       { TS_DEVICE_INITIALIZE, "device initialization" },
+       { TS_DEVICE_DONE,       "device setup done" },
+       { TS_CBMEM_POST,        "cbmem post" },
+       { TS_WRITE_TABLES,      "write tables" },
+       { TS_FINALIZE_CHIPS,    "finalize chips" },
+       { TS_LOAD_PAYLOAD,      "load payload" },
+       { TS_ACPI_WAKE_JUMP,    "ACPI wake jump" },
+       { TS_SELFBOOT_JUMP,     "selfboot jump" },
+
+       { TS_START_COPYVER,     "starting to load verstage" },
+       { TS_END_COPYVER,       "finished loading verstage" },
+       { TS_START_TPMINIT,     "starting to initialize TPM" },
+       { TS_END_TPMINIT,       "finished TPM initialization" },
+       { TS_START_VERIFY_SLOT, "starting to verify keyblock/preamble (RSA)" },
+       { TS_END_VERIFY_SLOT,   "finished verifying keyblock/preamble (RSA)" },
+       { TS_START_HASH_BODY,   "starting to verify body (load+SHA2+RSA) " },
+       { TS_DONE_LOADING,      "finished loading body (ignore for x86)" },
+       { TS_DONE_HASHING,      "finished calculating body hash (SHA2)" },
+       { TS_END_HASH_BODY,     "finished verifying body signature (RSA)" },
+
+       { TS_START_COPYVPD,     "starting to load Chrome OS VPD" },
+       { TS_END_COPYVPD_RO,    "finished loading Chrome OS VPD (RO)" },
+       { TS_END_COPYVPD_RW,    "finished loading Chrome OS VPD (RW)" },
+
+       { TS_U_BOOT_INITTED,    "U-Boot start" },
+       { TS_RO_PARAMS_INIT,    "RO parameter init" },
+       { TS_RO_VB_INIT,        "RO vboot init" },
+       { TS_RO_VB_SELECT_FIRMWARE,             "RO vboot select firmware" },
+       { TS_RO_VB_SELECT_AND_LOAD_KERNEL,      "RO vboot select&load kernel" },
+       { TS_RW_VB_SELECT_AND_LOAD_KERNEL,      "RW vboot select&load kernel" },
+       { TS_VB_SELECT_AND_LOAD_KERNEL,         "vboot select&load kernel" },
+       { TS_VB_EC_VBOOT_DONE,  "finished EC verification" },
+       { TS_VB_STORAGE_INIT_DONE, "finished storage device initialization" },
+       { TS_VB_READ_KERNEL_DONE, "finished reading kernel from disk" },
+       { TS_VB_VBOOT_DONE,     "finished vboot kernel verification" },
+       { TS_KERNEL_DECOMPRESSION, "starting kernel decompression/relocation" },
+       { TS_START_KERNEL,      "jumping to kernel" },
+       { TS_U_BOOT_START_KERNEL,       "just before jump to kernel" },
+
+       /* Intel ME-related timestamps */
+       { TS_ME_INFORM_DRAM_WAIT, "waiting for ME acknowledgment of raminit"},
+       { TS_ME_INFORM_DRAM_DONE, "finished waiting for ME response"},
+
+       /* FSP-related timestamps */
+       { TS_FSP_MEMORY_INIT_START, "calling FspMemoryInit" },
+       { TS_FSP_MEMORY_INIT_END, "returning from FspMemoryInit" },
+       { TS_FSP_TEMP_RAM_EXIT_START, "calling FspTempRamExit" },
+       { TS_FSP_TEMP_RAM_EXIT_END, "returning from FspTempRamExit" },
+       { TS_FSP_SILICON_INIT_START, "calling FspSiliconInit" },
+       { TS_FSP_SILICON_INIT_END, "returning from FspSiliconInit" },
+       { TS_FSP_BEFORE_ENUMERATE, "calling FspNotify(AfterPciEnumeration)" },
+       { TS_FSP_AFTER_ENUMERATE,
+                "returning from FspNotify(AfterPciEnumeration)" },
+       { TS_FSP_BEFORE_FINALIZE, "calling FspNotify(ReadyToBoot)" },
+       { TS_FSP_AFTER_FINALIZE, "returning from FspNotify(ReadyToBoot)" },
+       { TS_FSP_BEFORE_END_OF_FIRMWARE, "calling FspNotify(EndOfFirmware)" },
+       { TS_FSP_AFTER_END_OF_FIRMWARE,
+               "returning from FspNotify(EndOfFirmware)" },
+};
+
+static const char *timestamp_name(uint32_t id)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(timestamp_ids); i++) {
+               if (timestamp_ids[i].id == id)
+                       return timestamp_ids[i].name;
+       }
+
+       return "<unknown>";
+}
+
+static void show_table(struct sysinfo_t *info, bool verbose)
+{
+       struct cb_serial *ser = info->serial;
+       int i;
+
+       printf("Coreboot table at %lx, decoded to %p",
+              gd->arch.coreboot_table, info);
+       if (info->header)
+               printf(", forwarded to %p\n", info->header);
+       printf("\n");
+
+       print_dec("CPU KHz", info->cpu_khz);
+
+       print_addr("Serial I/O port", info->ser_ioport);
+       print_addr(">base", info->ser_base);
+       print_ptr(">pointer", ser);
+       if (ser) {
+               print_hex(">type", ser->type);
+               print_addr(">base", ser->baseaddr);
+               print_dec(">baud", ser->baud);
+               print_hex(">baud", ser->regwidth);
+               print_dec(">input_hz", ser->input_hertz);
+               print_addr(">PCI addr", ser->uart_pci_addr);
+       }
+
+       print_dec("Mem ranges", info->n_memranges);
+       printf("%12s: %-11s        ||   base        ||   size\n", "id", "type");
+       for (i = 0; i < info->n_memranges; i++) {
+               const struct memrange *mr = &info->memrange[i];
+
+               printf("%12d: %02x:%-8s %016llx %016llx\n", i, mr->type,
+                      get_mem_name(mr->type), mr->base, mr->size);
+       }
+       print_ptr("option_table", info->option_table);
+
+       print_hex("CMOS start", info->cmos_range_start);
+       if (info->cmos_range_start) {
+               print_hex(">CMOS end", info->cmos_range_end);
+               print_hex(">CMOS csum loc", info->cmos_checksum_location);
+       }
+
+       print_hex("VBNV start", info->vbnv_start);
+       print_hex("VBNV size", info->vbnv_size);
+
+       print_str("CB version", info->cb_version);
+       print_str(">Extra", info->extra_version);
+       print_str(">Build", info->build);
+       print_str(">Time", info->compile_time);
+       print_str(">By", info->compile_by);
+       print_str(">Host", info->compile_host);
+       print_str(">Domain", info->compile_domain);
+       print_str(">Compiler", info->compiler);
+       print_str(">Linker", info->linker);
+       print_str(">Assembler", info->assembler);
+
+       print_ptr("Framebuffer", info->framebuffer);
+       if (info->framebuffer) {
+               struct cb_framebuffer *fb = info->framebuffer;
+
+               print_addr64(">Phys addr", fb->physical_address);
+               print_dec(">X res", fb->x_resolution);
+               print_dec(">X res", fb->y_resolution);
+               print_hex(">Bytes / line", fb->bytes_per_line);
+               print_dec(">Bpp", fb->bits_per_pixel);
+               printf("   %-12s  red %d/%d, green %d/%d, blue %d/%d, reserved %d/%d\n",
+                      "pos/size", fb->red_mask_pos, fb->red_mask_size,
+                      fb->green_mask_pos, fb->green_mask_size,
+                      fb->blue_mask_pos, fb->blue_mask_size,
+                      fb->reserved_mask_pos, fb->reserved_mask_size);
+       }
+
+       print_dec("GPIOs", info->num_gpios);
+       printf("%12s: %4s %12s %3s %s\n", "id", "port", "polarity", "val",
+              "name");
+       for (i = 0; i < info->num_gpios; i++) {
+               const struct cb_gpio *gpio = &info->gpios[i];
+               char portstr[4];
+
+               if (gpio->port == 0xffffffff)
+                       strcpy(portstr, "-");
+               else
+                       sprintf(portstr, "%x", gpio->port);
+               printf("%12d: %4s %12s %3d %s\n", i, portstr,
+                      gpio->polarity == CB_GPIO_ACTIVE_LOW ? "active-low" :
+                      "active-high", gpio->value, gpio->name);
+       }
+       print_dec("MACs", info->num_macs);
+       for (i = 0; i < info->num_macs; i++) {
+               const struct mac_address *mac = &info->macs[i];
+               int j;
+
+               printf("%12d: ", i);
+               for (j = 0; j < sizeof(mac->mac_addr); j++)
+                       printf("%s%02x", j ? ":" : "", mac->mac_addr[j]);
+               printf("\n");
+       }
+       print_str(">Serial #", info->serialno);
+       print_ptr("Multiboot tab", info->mbtable);
+       print_ptr("CB header", info->header);
+       print_ptr("CB mainboard", info->mainboard);
+       if (info->mainboard) {
+               struct cb_mainboard *mb = info->mainboard;
+
+               print_idx(">vendor", mb->vendor_idx, mb->strings);
+               print_idx(">part_number", mb->part_number_idx, mb->strings);
+       }
+       print_ptr("vboot handoff", info->vboot_handoff);
+       print_hex(">size", info->vboot_handoff_size);
+       print_ptr(">vdat addr", info->vdat_addr);
+       print_hex(">size", info->vdat_size);
+
+       print_addr64("SMBIOS", info->smbios_start);
+       print_hex(">size", info->smbios_size);
+       print_hex("ROM MTRR", info->x86_rom_var_mtrr_index);
+
+       print_ptr("Tstamp table", info->tstamp_table);
+       if (verbose && info->tstamp_table) {
+               struct timestamp_table *ts = info->tstamp_table;
+
+               printf("%-12s", "Base_time");
+               print_grouped_ull(ts->base_time, 12);
+               printf("\n");
+               print_dec("Tick MHz", ts->tick_freq_mhz);
+               for (i = 0; i < ts->num_entries; i++) {
+                       const struct timestamp_entry *tse;
+
+                       tse = &ts->entries[i];
+                       printf("   ");
+                       print_grouped_ull(tse->entry_stamp, 12);
+                       printf("  %s\n", timestamp_name(tse->entry_id));
+               }
+       }
+
+       print_ptr("CBmem cons", info->cbmem_cons);
+       if (info->cbmem_cons) {
+               struct cbmem_console *cons = info->cbmem_cons;
+               int i;
+
+               print_hex("Size", cons->size);
+               print_hex("Cursor", cons->cursor);
+               if (verbose) {
+                       for (i = 0; i < cons->cursor; i++) {
+                               int ch = cons->body[i];
+
+                               putc(ch);
+
+                               if (ch == '\n') {
+                                       /* check for ctrl-c to abort... */
+                                       if (ctrlc()) {
+                                               puts("Abort\n");
+                                               return;
+                                       }
+                                       printf("   ");
+                               }
+                       }
+                       printf("\n");
+               }
+       }
+
+       print_ptr("MRC cache", info->mrc_cache);
+       print_ptr("ACPI GNVS", info->acpi_gnvs);
+       print_hex("Board ID", info->board_id);
+       print_hex("RAM code", info->ram_code);
+       print_ptr("WiFi calib", info->wifi_calibration);
+       print_addr64("Ramoops buff", info->ramoops_buffer);
+       print_hex(">size", info->ramoops_buffer_size);
+       print_hex("SF size", info->spi_flash.size);
+       print_hex("SF sector", info->spi_flash.sector_size);
+       print_hex("SF erase cmd", info->spi_flash.erase_cmd);
+
+       print_addr64("FMAP offset", info->fmap_offset);
+       print_addr64("CBFS offset", info->cbfs_offset);
+       print_addr64("CBFS size", info->cbfs_size);
+       print_addr64("Boot media size", info->boot_media_size);
+       print_addr64("MTC start", info->mtc_start);
+       print_hex("MTC size", info->mtc_size);
+
+       print_ptr("Chrome OS VPD", info->chromeos_vpd);
+}
+
+static int do_cbsysinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+                       char *const argv[])
+{
+       bool verbose = false;
+
+       if (argc > 1) {
+               if (!strcmp("-v", argv[1]))
+                       verbose = true;
+               else
+                       return CMD_RET_USAGE;
+       }
+
+       if (!gd->arch.coreboot_table) {
+               printf("No coreboot sysinfo table found\n");
+               return CMD_RET_FAILURE;
+       }
+       show_table(&lib_sysinfo, verbose);
+
+       return 0;
+}
+
+U_BOOT_CMD(
+       cbsysinfo,      2,      1,      do_cbsysinfo,
+       "Show coreboot sysinfo table",
+       "[-v]         Dumps out the contents of the sysinfo table. This only\n"
+       "works if U-Boot is booted from coreboot"
+);
index 2bb3798..482f123 100644 (file)
@@ -588,6 +588,14 @@ config AVB_BUF_SIZE
 
 endif # AVB_VERIFY
 
+config SCP03
+       bool "Build SCP03 - Secure Channel Protocol O3 - controls"
+       depends on OPTEE || SANDBOX
+       depends on TEE
+       help
+         This option allows U-Boot to enable and or provision SCP03 on an OPTEE
+         controlled Secured Element.
+
 config SPL_HASH
        bool # "Support hashing API (SHA1, SHA256, etc.)"
        help
index daeea67..215b8b2 100644 (file)
@@ -137,3 +137,4 @@ obj-$(CONFIG_CMD_LOADB) += xyzModem.o
 obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o
 
 obj-$(CONFIG_AVB_VERIFY) += avb_verify.o
+obj-$(CONFIG_SCP03) += scp03.o
index b54aa30..1cfe34f 100644 (file)
@@ -1,31 +1,52 @@
 // SPDX-License-Identifier: GPL-2.0+
 
 #include <common.h>
+#include <dm.h>
 #include <init.h>
+#include <sysinfo.h>
 #include <asm/global_data.h>
 #include <linux/libfdt.h>
 #include <linux/compiler.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 int __weak checkboard(void)
 {
        return 0;
 }
 
 /*
- * If the root node of the DTB has a "model" property, show it.
+ * Check sysinfo for board information. Failing that if the root node of the DTB
+ * has a "model" property, show it.
+ *
  * Then call checkboard().
  */
 int __weak show_board_info(void)
 {
-#ifdef CONFIG_OF_CONTROL
-       DECLARE_GLOBAL_DATA_PTR;
-       const char *model;
+       if (IS_ENABLED(CONFIG_OF_CONTROL)) {
+               struct udevice *dev;
+               const char *model;
+               char str[80];
+               int ret = -ENOSYS;
+
+               if (IS_ENABLED(CONFIG_SYSINFO)) {
+                       /* This might provide more detail */
+                       ret = uclass_first_device_err(UCLASS_SYSINFO, &dev);
+                       if (!ret)
+                               ret = sysinfo_get_str(dev,
+                                                     SYSINFO_ID_BOARD_MODEL,
+                                                     sizeof(str), str);
+               }
 
-       model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+               /* Fail back to the main 'model' if available */
+               if (ret)
+                       model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+               else
+                       model = str;
 
-       if (model)
-               printf("Model: %s\n", model);
-#endif
+               if (model)
+                       printf("Model: %s\n", model);
+       }
 
        return checkboard();
 }
index defaed8..ea71522 100644 (file)
@@ -583,10 +583,11 @@ int bootm_process_cmdline(char *buf, int maxlen, int flags)
                if (ret)
                        return log_msg_ret("silent", ret);
        }
-       if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && (flags & BOOTM_CL_SUBST)) {
+       if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && IS_ENABLED(CONFIG_CMDLINE) &&
+           (flags & BOOTM_CL_SUBST)) {
                ret = process_subst(buf, maxlen);
                if (ret)
-                       return log_msg_ret("silent", ret);
+                       return log_msg_ret("subst", ret);
        }
 
        return 0;
index 2c0110c..4621105 100644 (file)
@@ -9,6 +9,8 @@
  * permits accurate timestamping of each.
  */
 
+#define LOG_CATEGORY   LOGC_BOOT
+
 #include <common.h>
 #include <bootstage.h>
 #include <hang.h>
@@ -127,12 +129,16 @@ ulong bootstage_add_record(enum bootstage_id id, const char *name,
 
        /* Only record the first event for each */
        rec = find_id(data, id);
-       if (!rec && data->rec_count < RECORD_COUNT) {
-               rec = &data->record[data->rec_count++];
-               rec->time_us = mark;
-               rec->name = name;
-               rec->flags = flags;
-               rec->id = id;
+       if (!rec) {
+               if (data->rec_count < RECORD_COUNT) {
+                       rec = &data->record[data->rec_count++];
+                       rec->time_us = mark;
+                       rec->name = name;
+                       rec->flags = flags;
+                       rec->id = id;
+               } else {
+                       log_warning("Bootstage space exhasuted\n");
+               }
        }
 
        /* Tell the board about this progress */
index 94501b1..b972042 100644 (file)
@@ -1512,6 +1512,10 @@ int fit_image_check_arch(const void *fit, int noffset, uint8_t arch)
        uint8_t image_arch;
        int aarch32_support = 0;
 
+       /* Let's assume that sandbox can load any architecture */
+       if (IS_ENABLED(CONFIG_SANDBOX))
+               return true;
+
        if (IS_ENABLED(CONFIG_ARM64_SUPPORT_AARCH32))
                aarch32_support = 1;
 
index 6b0034c..ea407c6 100644 (file)
@@ -153,7 +153,7 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec)
 {
        struct log_filter *filt;
 
-       if (rec->force_debug)
+       if (rec->flags & LOGRECF_FORCE_DEBUG)
                return true;
 
        /* If there are no filters, filter on the default log level */
@@ -218,8 +218,11 @@ static int log_dispatch(struct log_rec *rec, const char *fmt, va_list args)
                if ((ldev->flags & LOGDF_ENABLE) &&
                    log_passes_filters(ldev, rec)) {
                        if (!rec->msg) {
-                               vsnprintf(buf, sizeof(buf), fmt, args);
+                               int len;
+
+                               len = vsnprintf(buf, sizeof(buf), fmt, args);
                                rec->msg = buf;
+                               gd->log_cont = len && buf[len - 1] != '\n';
                        }
                        ldev->drv->emit(ldev, rec);
                }
@@ -245,7 +248,11 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
 
        rec.cat = cat;
        rec.level = level & LOGL_LEVEL_MASK;
-       rec.force_debug = level & LOGL_FORCE_DEBUG;
+       rec.flags = 0;
+       if (level & LOGL_FORCE_DEBUG)
+               rec.flags |= LOGRECF_FORCE_DEBUG;
+       if (gd->log_cont)
+               rec.flags |= LOGRECF_CONT;
        rec.file = file;
        rec.line = line;
        rec.func = func;
@@ -255,7 +262,8 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
                gd->log_drop_count++;
 
                /* display dropped traces with console puts and DEBUG_UART */
-               if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL || rec.force_debug) {
+               if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL ||
+                   rec.flags & LOGRECF_FORCE_DEBUG) {
                        char buf[CONFIG_SYS_CBSIZE];
 
                        va_start(args, fmt);
index 6abb13c..3f61774 100644 (file)
@@ -15,6 +15,7 @@ DECLARE_GLOBAL_DATA_PTR;
 static int log_console_emit(struct log_device *ldev, struct log_rec *rec)
 {
        int fmt = gd->log_fmt;
+       bool add_space = false;
 
        /*
         * The output format is designed to give someone a fighting chance of
@@ -26,18 +27,21 @@ static int log_console_emit(struct log_device *ldev, struct log_rec *rec)
         *    - function is an identifier and ends with ()
         *    - message has a space before it unless it is on its own
         */
-       if (fmt & BIT(LOGF_LEVEL))
-               printf("%s.", log_get_level_name(rec->level));
-       if (fmt & BIT(LOGF_CAT))
-               printf("%s,", log_get_cat_name(rec->cat));
-       if (fmt & BIT(LOGF_FILE))
-               printf("%s:", rec->file);
-       if (fmt & BIT(LOGF_LINE))
-               printf("%d-", rec->line);
-       if (fmt & BIT(LOGF_FUNC))
-               printf("%s()", rec->func);
+       if (!(rec->flags & LOGRECF_CONT) && fmt != BIT(LOGF_MSG)) {
+               add_space = true;
+               if (fmt & BIT(LOGF_LEVEL))
+                       printf("%s.", log_get_level_name(rec->level));
+               if (fmt & BIT(LOGF_CAT))
+                       printf("%s,", log_get_cat_name(rec->cat));
+               if (fmt & BIT(LOGF_FILE))
+                       printf("%s:", rec->file);
+               if (fmt & BIT(LOGF_LINE))
+                       printf("%d-", rec->line);
+               if (fmt & BIT(LOGF_FUNC))
+                       printf("%s()", rec->func);
+       }
        if (fmt & BIT(LOGF_MSG))
-               printf("%s%s", fmt != BIT(LOGF_MSG) ? " " : "", rec->msg);
+               printf("%s%s", add_space ? " " : "", rec->msg);
 
        return 0;
 }
diff --git a/common/scp03.c b/common/scp03.c
new file mode 100644 (file)
index 0000000..09ef7b5
--- /dev/null
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+
+#include <common.h>
+#include <scp03.h>
+#include <tee.h>
+#include <tee/optee_ta_scp03.h>
+
+static int scp03_enable(bool provision)
+{
+       const struct tee_optee_ta_uuid uuid = PTA_SCP03_UUID;
+       struct tee_open_session_arg session;
+       struct tee_invoke_arg invoke;
+       struct tee_param param;
+       struct udevice *tee = NULL;
+
+       tee = tee_find_device(tee, NULL, NULL, NULL);
+       if (!tee)
+               return -ENODEV;
+
+       memset(&session, 0, sizeof(session));
+       tee_optee_ta_uuid_to_octets(session.uuid, &uuid);
+       if (tee_open_session(tee, &session, 0, NULL))
+               return -ENXIO;
+
+       memset(&param, 0, sizeof(param));
+       param.attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+       param.u.value.a = provision;
+
+       memset(&invoke, 0, sizeof(invoke));
+       invoke.func = PTA_CMD_ENABLE_SCP03;
+       invoke.session = session.session;
+
+       if (tee_invoke_func(tee, &invoke, 1, &param))
+               return -EIO;
+
+       tee_close_session(tee, session.session);
+
+       return 0;
+}
+
+int tee_enable_scp03(void)
+{
+       return scp03_enable(false);
+}
+
+int tee_provision_scp03(void)
+{
+       return scp03_enable(true);
+}
index 774541c..0711cbf 100644 (file)
@@ -276,6 +276,19 @@ config SPL_SEPARATE_BSS
          location is used. Normally we put the device tree at the end of BSS
          but with this option enabled, it goes at _image_binary_end.
 
+config SPL_READ_ONLY
+       bool
+       depends on SPL_OF_PLATDATA
+       # Bind cannot be supported because the udevice structs are in read-only
+       # memory so we cannot update the linked lists.
+       select SPL_OF_PLATDATA_NO_BIND
+       select SPL_OF_PLATDATA_RT
+       help
+         Some platforms (e.g. x86 Apollo Lake) load SPL into a read-only
+         section of memory. This means that of-platdata must make a copy (in
+         writeable memory) of anything it wants to modify, such as
+         device-private data.
+
 config SPL_BANNER_PRINT
        bool "Enable output of the SPL banner 'U-Boot SPL ...'"
        default y
@@ -487,7 +500,7 @@ config SPL_CACHE_SUPPORT
          future requests for that data can be served faster. Enable this option
          to build the drivers in drivers/cache as part of an SPL build.
 
-config SPL_CPU_SUPPORT
+config SPL_CPU
        bool "Support CPU drivers"
        help
          Enable this to support CPU drivers in SPL. These drivers can set
@@ -1440,6 +1453,17 @@ config TPL_STACK
          The address of the initial stack-pointer for the TPL stage.
          Usually this will be the (aligned) top-of-stack.
 
+config TPL_READ_ONLY
+       bool
+       depends on TPL_OF_PLATDATA
+       select TPL_OF_PLATDATA_NO_BIND
+       select TPL_OF_PLATDATA_RT
+       help
+         Some platforms (e.g. x86 Apollo Lake) load SPL into a read-only
+         section of memory. This means that of-platdata must make a copy (in
+         writeable memory) of anything it wants to modify, such as
+         device-private data.
+
 config TPL_BOOTROM_SUPPORT
         bool "Support returning to the BOOTROM (from TPL)"
        help
index e3d8408..556a91a 100644 (file)
@@ -16,6 +16,7 @@
 #include <init.h>
 #include <irq_func.h>
 #include <log.h>
+#include <mapmem.h>
 #include <serial.h>
 #include <spl.h>
 #include <asm/global_data.h>
@@ -168,7 +169,7 @@ __weak void spl_board_prepare_for_boot(void)
 
 __weak struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
 {
-       return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset);
+       return map_sysmem(CONFIG_SYS_TEXT_BASE + offset, 0);
 }
 
 void spl_set_header_raw_uboot(struct spl_image_info *spl_image)
@@ -386,6 +387,22 @@ static inline int write_spl_handoff(void) { return 0; }
 
 #endif /* HANDOFF */
 
+/**
+ * get_bootstage_id() - Get the bootstage ID to emit
+ *
+ * @start: true if this is for starting SPL, false for ending it
+ * @return bootstage ID to use
+ */
+static enum bootstage_id get_bootstage_id(bool start)
+{
+       enum u_boot_phase phase = spl_phase();
+
+       if (IS_ENABLED(CONFIG_TPL_BUILD) && phase == PHASE_TPL)
+               return start ? BOOTSTAGE_ID_START_TPL : BOOTSTAGE_ID_END_TPL;
+       else
+               return start ? BOOTSTAGE_ID_START_SPL : BOOTSTAGE_ID_END_SPL;
+}
+
 static int spl_common_init(bool setup_malloc)
 {
        int ret;
@@ -416,8 +433,8 @@ static int spl_common_init(bool setup_malloc)
                              __func__, ret);
        }
 #endif /* CONFIG_BOOTSTAGE_STASH */
-       bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_START_TPL :
-                           BOOTSTAGE_ID_START_SPL, SPL_TPL_NAME);
+       bootstage_mark_name(get_bootstage_id(true),
+                           spl_phase_name(spl_phase()));
 #if CONFIG_IS_ENABLED(LOG)
        ret = log_init();
        if (ret) {
@@ -694,7 +711,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 #endif
        switch (spl_image.os) {
        case IH_OS_U_BOOT:
-               debug("Jumping to U-Boot\n");
+               debug("Jumping to %s...\n", spl_phase_name(spl_next_phase()));
                break;
 #if CONFIG_IS_ENABLED(ATF)
        case IH_OS_ARM_TRUSTED_FIRMWARE:
@@ -732,8 +749,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
        debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr,
              gd->malloc_ptr / 1024);
 #endif
-       bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_END_TPL :
-                           BOOTSTAGE_ID_END_SPL, "end " SPL_TPL_NAME);
+       bootstage_mark_name(get_bootstage_id(false), "end phase");
 #ifdef CONFIG_BOOTSTAGE_STASH
        ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
                              CONFIG_BOOTSTAGE_STASH_SIZE);
@@ -741,7 +757,6 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
                debug("Failed to stash bootstage: err=%d\n", ret);
 #endif
 
-       debug("loaded - jumping to %s...\n", spl_phase_name(spl_next_phase()));
        spl_board_prepare_for_boot();
        jump_to_image_no_args(&spl_image);
 }
index 75c8ff0..49508fc 100644 (file)
@@ -11,6 +11,7 @@
 #include <image.h>
 #include <log.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <spl.h>
 #include <sysinfo.h>
 #include <asm/cache.h>
@@ -235,11 +236,11 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
        size_t length;
        int len;
        ulong size;
-       ulong load_addr, load_ptr;
+       ulong load_addr;
+       void *load_ptr;
        void *src;
        ulong overhead;
        int nr_sectors;
-       int align_len = ARCH_DMA_MINALIGN - 1;
        uint8_t image_comp = -1, type = -1;
        const void *data;
        const void *fit = ctx->fit;
@@ -269,11 +270,13 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
        }
 
        if (external_data) {
+               void *src_ptr;
+
                /* External data */
                if (fit_image_get_data_size(fit, node, &len))
                        return -ENOENT;
 
-               load_ptr = (load_addr + align_len) & ~align_len;
+               src_ptr = map_sysmem(ALIGN(load_addr, ARCH_DMA_MINALIGN), len);
                length = len;
 
                overhead = get_aligned_image_overhead(info, offset);
@@ -281,12 +284,12 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
 
                if (info->read(info,
                               sector + get_aligned_image_offset(info, offset),
-                              nr_sectors, (void *)load_ptr) != nr_sectors)
+                              nr_sectors, src_ptr) != nr_sectors)
                        return -EIO;
 
-               debug("External data: dst=%lx, offset=%x, size=%lx\n",
-                     load_ptr, offset, (unsigned long)length);
-               src = (void *)load_ptr + overhead;
+               debug("External data: dst=%p, offset=%x, size=%lx\n",
+                     src_ptr, offset, (unsigned long)length);
+               src = src_ptr + overhead;
        } else {
                /* Embedded data */
                if (fit_image_get_data(fit, node, &data, &length)) {
@@ -295,7 +298,7 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
                }
                debug("Embedded data: dst=%lx, size=%lx\n", load_addr,
                      (unsigned long)length);
-               src = (void *)data;
+               src = (void *)data;     /* cast away const */
        }
 
        if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
@@ -309,16 +312,16 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
        if (CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS))
                board_fit_image_post_process(&src, &length);
 
+       load_ptr = map_sysmem(load_addr, length);
        if (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) {
                size = length;
-               if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN,
-                          src, &size)) {
+               if (gunzip(load_ptr, CONFIG_SYS_BOOTM_LEN, src, &size)) {
                        puts("Uncompressing error\n");
                        return -EIO;
                }
                length = size;
        } else {
-               memcpy((void *)load_addr, src, length);
+               memcpy(load_ptr, src, length);
        }
 
        if (image_info) {
@@ -383,7 +386,7 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image,
        }
 
        /* Make the load-address of the FDT available for the SPL framework */
-       spl_image->fdt_addr = (void *)image_info.load_addr;
+       spl_image->fdt_addr = map_sysmem(image_info.load_addr, 0);
        if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY))
                return 0;
 
index f990448..76cccfa 100644 (file)
@@ -19,6 +19,7 @@ CONFIG_SYS_LDSCRIPT="arch/arm/mach-zynq/u-boot.lds"
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_BOOTDELAY=3
 CONFIG_USE_PREBOOT=y
 # CONFIG_DISPLAY_CPUINFO is not set
@@ -50,6 +51,7 @@ CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_FAT=y
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_NET_RANDOM_ETHADDR=y
index 0811ffd..4823913 100644 (file)
@@ -43,7 +43,7 @@ CONFIG_BLOBLIST_ADDR=0x100000
 CONFIG_HANDOFF=y
 CONFIG_TPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_SEPARATE_BSS=y
-CONFIG_SPL_CPU_SUPPORT=y
+CONFIG_SPL_CPU=y
 CONFIG_SPL_DM_SPI_FLASH=y
 CONFIG_SPL_PCI=y
 # CONFIG_SPL_SPI_FLASH_TINY is not set
@@ -73,6 +73,7 @@ CONFIG_MAC_PARTITION=y
 CONFIG_ISO_PARTITION=y
 CONFIG_EFI_PARTITION=y
 # CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent interrupts linux-name acpi,name acpi,path u-boot,acpi-dsdt-order u-boot,acpi-ssdt-order"
 CONFIG_ENV_OVERWRITE=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
index 8f56ee3..872e33d 100644 (file)
@@ -31,7 +31,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_MISC_INIT_R=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_CPU_SUPPORT=y
+CONFIG_SPL_CPU=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_DM_SPI_FLASH=y
diff --git a/configs/hihope_rzg2_defconfig b/configs/hihope_rzg2_defconfig
new file mode 100644 (file)
index 0000000..69eaab0
--- /dev/null
@@ -0,0 +1,82 @@
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_ARCH_RMOBILE=y
+CONFIG_SYS_TEXT_BASE=0x50000000
+CONFIG_ENV_SIZE=0x20000
+CONFIG_ENV_OFFSET=0xFFFE0000
+CONFIG_DM_GPIO=y
+CONFIG_RCAR_GEN3=y
+CONFIG_TARGET_HIHOPE_RZG2=y
+# CONFIG_SPL is not set
+CONFIG_DEFAULT_DEVICE_TREE="r8a774a1-hihope-rzg2m-u-boot"
+CONFIG_FIT=y
+CONFIG_SUPPORT_RAW_INITRD=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.20"
+CONFIG_DEFAULT_FDT_FILE="r8a774a1-hihope-rzg2m.dtb"
+# CONFIG_BOARD_EARLY_INIT_F is not set
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIST="r8a774a1-hihope-rzg2m-u-boot r8a774b1-hihope-rzg2n-u-boot r8a774e1-hihope-rzg2h-u-boot"
+CONFIG_MULTI_DTB_FIT_LZO=y
+CONFIG_MULTI_DTB_FIT_USER_DEFINED_AREA=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SYS_MMC_ENV_DEV=1
+CONFIG_SYS_MMC_ENV_PART=2
+CONFIG_VERSION_VARIABLE=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+CONFIG_CLK_RENESAS=y
+CONFIG_GPIO_HOG=y
+CONFIG_RCAR_GPIO=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_RCAR_I2C=y
+CONFIG_SYS_I2C_RCAR_IIC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
+CONFIG_RENESAS_SDHI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_USE_4K_SECTORS=y
+CONFIG_BITBANGMII=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_ETH=y
+CONFIG_RENESAS_RAVB=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_SCIF_CONSOLE=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_RENESAS_RPC_SPI=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_OF_LIBFDT_OVERLAY=y
index fa427d8..c12ce5c 100644 (file)
@@ -4,7 +4,10 @@ CONFIG_ARCH_MEDIATEK=y
 CONFIG_SYS_TEXT_BASE=0x41e00000
 CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=25000000
 CONFIG_DEFAULT_DEVICE_TREE="mt7622-rfb"
+CONFIG_DEBUG_UART=y
 CONFIG_FIT=y
 CONFIG_DEFAULT_FDT_FILE="mt7622-rfb"
 CONFIG_LOGLEVEL=7
@@ -51,8 +54,6 @@ CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_MTK_SNOR=y
 CONFIG_SYSRESET_WATCHDOG=y
-CONFIG_TIMER=y
-CONFIG_MTK_TIMER=y
 CONFIG_WDT_MTK=y
 CONFIG_LZO=y
 CONFIG_HEXDUMP=y
index 2e94f97..cd9f7aa 100644 (file)
@@ -10,7 +10,11 @@ CONFIG_SPL_TEXT_BASE=0x201000
 CONFIG_TARGET_MT7629=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_STACK_R_ADDR=0x40800000
+CONFIG_SPL_PAYLOAD="u-boot-lzma.img"
+CONFIG_BUILD_TARGET="u-boot-mtk.bin"
 CONFIG_DEFAULT_DEVICE_TREE="mt7629-rfb"
+CONFIG_SPL_IMAGE="spl/u-boot-spl-mtk.bin"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_BOOTDELAY=3
@@ -18,6 +22,7 @@ CONFIG_DEFAULT_FDT_FILE="mt7629-rfb"
 CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_STACK_R=y
 CONFIG_SPL_NOR_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
 CONFIG_HUSH_PARSER=y
@@ -87,4 +92,5 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_WDT_MTK=y
 CONFIG_LZMA=y
+CONFIG_SPL_LZMA=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/mt8183_pumpkin_defconfig b/configs/mt8183_pumpkin_defconfig
new file mode 100644 (file)
index 0000000..b0bdcb3
--- /dev/null
@@ -0,0 +1,81 @@
+CONFIG_ARM=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_SYS_TEXT_BASE=0x4c000000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0x0
+CONFIG_DM_GPIO=y
+CONFIG_TARGET_MT8183=y
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=26000000
+# CONFIG_PSCI_RESET is not set
+CONFIG_DEFAULT_DEVICE_TREE="mt8183-pumpkin"
+CONFIG_DEBUG_UART=y
+# CONFIG_ANDROID_BOOT_IMAGE is not set
+CONFIG_FIT=y
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
+CONFIG_DEFAULT_FDT_FILE="mt8183-pumpkin"
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_HUSH_PARSER=y
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+# CONFIG_CMD_BOOTD is not set
+# CONFIG_CMD_BOOTI is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_GO is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+# CONFIG_CMD_EDITENV is not set
+# CONFIG_CMD_CRC32 is not set
+# CONFIG_CMD_MEMORY is not set
+CONFIG_CMD_CLK=y
+CONFIG_CMD_GPT=y
+# CONFIG_RANDOM_UUID is not set
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+# CONFIG_CMD_ITEST is not set
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_BLOCK_CACHE is not set
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_MMC_ENV_PART=2
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DEVRES=y
+CONFIG_CLK=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x4d000000
+CONFIG_FASTBOOT_BUF_SIZE=0x8000000
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT=y
+# CONFIG_INPUT is not set
+CONFIG_DM_MMC=y
+# CONFIG_MMC_QUIRKS is not set
+CONFIG_MMC_MTK=y
+CONFIG_DM_ETH=y
+CONFIG_PHY=y
+CONFIG_PHY_MTK_TPHY=y
+CONFIG_BAUDRATE=921600
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_MTK_SERIAL=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_USB_MTU3=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x0e8d
+CONFIG_USB_GADGET_PRODUCT_NUM=0x201c
+CONFIG_USB_ETHER=y
+CONFIG_WDT=y
+CONFIG_WDT_MTK=y
+# CONFIG_REGEX is not set
+CONFIG_OF_LIBFDT_OVERLAY=y
+# CONFIG_EFI_LOADER is not set
index 99a489c..4815d8a 100644 (file)
@@ -31,7 +31,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_PCI_INIT_R=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_CPU_SUPPORT=y
+CONFIG_SPL_CPU=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_DM_SPI_FLASH=y
 CONFIG_SPL_NET_SUPPORT=y
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig
new file mode 100644 (file)
index 0000000..1ac7e02
--- /dev/null
@@ -0,0 +1,231 @@
+CONFIG_SYS_TEXT_BASE=0x200000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SYS_MEMTEST_START=0x00100000
+CONFIG_SYS_MEMTEST_END=0x00101000
+CONFIG_ENV_SIZE=0x2000
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000
+CONFIG_SPL=y
+CONFIG_BOOTSTAGE_STASH_ADDR=0x0
+CONFIG_DEFAULT_DEVICE_TREE="sandbox"
+CONFIG_SANDBOX_SPL=y
+CONFIG_DEBUG_UART=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_BOOTSTAGE_FDT=y
+CONFIG_BOOTSTAGE_STASH=y
+CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
+CONFIG_CONSOLE_RECORD=y
+CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_HANDOFF=y
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_ENV_SUPPORT=y
+CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_RTC_SUPPORT=y
+CONFIG_CMD_CPU=y
+CONFIG_CMD_LICENSE=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_BOOTEFI_HELLO=y
+# CONFIG_CMD_ELF is not set
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_ERASEENV=y
+CONFIG_CMD_ENV_CALLBACK=y
+CONFIG_CMD_ENV_FLAGS=y
+CONFIG_CMD_NVEDIT_INFO=y
+CONFIG_CMD_NVEDIT_LOAD=y
+CONFIG_CMD_NVEDIT_SELECT=y
+CONFIG_LOOPW=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MX_CYCLIC=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_DEMO=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_IDE=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_OSD=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_REMOTEPROC=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_BOOTP_DNS2=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_TFTPSRV=y
+CONFIG_CMD_RARP=y
+CONFIG_CMD_CDP=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_BMP=y
+CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SOUND=y
+CONFIG_CMD_QFW=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_TPM_TEST=y
+CONFIG_CMD_CBFS=y
+CONFIG_CMD_CRAMFS=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_MAC_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_HOSTFILE=y
+CONFIG_SPL_OF_PLATDATA=y
+CONFIG_ENV_IS_NOWHERE=y
+CONFIG_ENV_IS_IN_EXT4=y
+CONFIG_ENV_EXT4_INTERFACE="host"
+CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
+CONFIG_BOOTP_SEND_HOSTNAME=y
+CONFIG_NETCONSOLE=y
+CONFIG_IP_DEFRAG=y
+CONFIG_SPL_DM=y
+CONFIG_DM_DMA=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_DEVRES=y
+CONFIG_DEBUG_DEVRES=y
+# CONFIG_SPL_SIMPLE_BUS is not set
+CONFIG_ADC=y
+CONFIG_ADC_SANDBOX=y
+CONFIG_AXI=y
+CONFIG_AXI_SANDBOX=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_CPU=y
+CONFIG_DM_DEMO=y
+CONFIG_DM_DEMO_SIMPLE=y
+CONFIG_DM_DEMO_SHAPE=y
+CONFIG_SPL_FIRMWARE=y
+CONFIG_GPIO_HOG=y
+CONFIG_PM8916_GPIO=y
+CONFIG_SANDBOX_GPIO=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_I2C_CROS_EC_LDO=y
+CONFIG_DM_I2C_GPIO=y
+CONFIG_SYS_I2C_SANDBOX=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_I8042_KEYB=y
+CONFIG_LED=y
+CONFIG_LED_BLINK=y
+CONFIG_LED_GPIO=y
+CONFIG_DM_MAILBOX=y
+CONFIG_SANDBOX_MBOX=y
+CONFIG_MISC=y
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_I2C=y
+CONFIG_CROS_EC_LPC=y
+CONFIG_CROS_EC_SANDBOX=y
+CONFIG_CROS_EC_SPI=y
+CONFIG_IRQ=y
+CONFIG_P2SB=y
+CONFIG_PWRSEQ=y
+CONFIG_SPL_PWRSEQ=y
+CONFIG_MMC_SANDBOX=y
+CONFIG_SPI_FLASH_SANDBOX=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_ETH=y
+CONFIG_NVME=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_SANDBOX=y
+CONFIG_PHY=y
+CONFIG_PHY_SANDBOX=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_SANDBOX=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_ACT8846=y
+CONFIG_DM_PMIC_PFUZE100=y
+CONFIG_DM_PMIC_MAX77686=y
+CONFIG_DM_PMIC_MC34708=y
+CONFIG_PMIC_PM8916=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_PMIC_S2MPS11=y
+CONFIG_DM_PMIC_SANDBOX=y
+CONFIG_PMIC_S5M8767=y
+CONFIG_PMIC_TPS65090=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_DM_REGULATOR_PFUZE100=y
+CONFIG_DM_REGULATOR_MAX77686=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_DM_REGULATOR_SANDBOX=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_SANDBOX=y
+CONFIG_RAM=y
+CONFIG_REMOTEPROC_SANDBOX=y
+CONFIG_DM_RESET=y
+CONFIG_SANDBOX_RESET=y
+CONFIG_DM_RTC=y
+CONFIG_SPL_DM_RTC=y
+CONFIG_SANDBOX_SERIAL=y
+CONFIG_SOUND=y
+CONFIG_SOUND_SANDBOX=y
+CONFIG_SOC_DEVICE=y
+CONFIG_SANDBOX_SPI=y
+CONFIG_SPMI=y
+CONFIG_SPMI_SANDBOX=y
+CONFIG_SYSINFO=y
+CONFIG_SYSINFO_SANDBOX=y
+CONFIG_SYSRESET=y
+CONFIG_SPL_SYSRESET=y
+CONFIG_TIMER=y
+CONFIG_TIMER_EARLY=y
+CONFIG_SANDBOX_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EMUL=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_DM_VIDEO=y
+CONFIG_CONSOLE_ROTATION=y
+CONFIG_CONSOLE_TRUETYPE=y
+CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
+CONFIG_VIDEO_SANDBOX_SDL=y
+CONFIG_OSD=y
+CONFIG_SANDBOX_OSD=y
+CONFIG_SPLASH_SCREEN_ALIGN=y
+CONFIG_VIDEO_BMP_RLE8=y
+CONFIG_FS_CBFS=y
+CONFIG_FS_CRAMFS=y
+# CONFIG_SPL_USE_TINY_PRINTF is not set
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_RSA_VERIFY_WITH_PKEY=y
+CONFIG_TPM=y
+CONFIG_LZ4=y
+CONFIG_ERRNO_STR=y
+CONFIG_UNIT_TEST=y
+CONFIG_SPL_UNIT_TEST=y
+CONFIG_UT_TIME=y
+CONFIG_UT_DM=y
index c011870..ac71cab 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_SYS_TEXT_BASE=0
+CONFIG_SYS_TEXT_BASE=0x200000
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_NR_DRAM_BANKS=1
@@ -7,6 +7,7 @@ CONFIG_SYS_MEMTEST_END=0x00101000
 CONFIG_ENV_SIZE=0x2000
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
 CONFIG_BOOTSTAGE_STASH_ADDR=0x0
 CONFIG_DEFAULT_DEVICE_TREE="sandbox"
@@ -87,6 +88,7 @@ CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_HOSTFILE=y
 CONFIG_SPL_OF_PLATDATA=y
+CONFIG_SPL_OF_PLATDATA_INST=y
 CONFIG_ENV_IS_NOWHERE=y
 CONFIG_ENV_IS_IN_EXT4=y
 CONFIG_ENV_EXT4_INTERFACE="host"
@@ -102,6 +104,7 @@ CONFIG_SYSCON=y
 CONFIG_SPL_SYSCON=y
 CONFIG_DEVRES=y
 CONFIG_DEBUG_DEVRES=y
+# CONFIG_SPL_SIMPLE_BUS is not set
 CONFIG_ADC=y
 CONFIG_ADC_SANDBOX=y
 CONFIG_AXI=y
diff --git a/configs/silinux_ek874_defconfig b/configs/silinux_ek874_defconfig
new file mode 100644 (file)
index 0000000..dcd7560
--- /dev/null
@@ -0,0 +1,83 @@
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_ARCH_RMOBILE=y
+CONFIG_SYS_TEXT_BASE=0x50000000
+CONFIG_SPL_TEXT_BASE=0xe6318000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x3F0000
+CONFIG_ENV_SECT_SIZE=0x10000
+CONFIG_RCAR_GEN3=y
+CONFIG_TARGET_SILINUX_EK874=y
+# CONFIG_BOARD_EARLY_INIT_F is not set
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_RENESAS=y
+CONFIG_DEFAULT_DEVICE_TREE="r8a774c0-ek874-u-boot"
+CONFIG_SMBIOS_PRODUCT_NAME=""
+CONFIG_FIT=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.20"
+CONFIG_SUPPORT_RAW_INITRD=y
+CONFIG_DEFAULT_FDT_FILE="r8a774c0-ek874.dtb"
+CONFIG_VERSION_VARIABLE=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_BLK=y
+CONFIG_CLK=y
+CONFIG_CLK_RENESAS=y
+CONFIG_DM_GPIO=y
+CONFIG_RCAR_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_RCAR_I2C=y
+CONFIG_SYS_I2C_RCAR_IIC=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_USE_4K_SECTORS=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_RENESAS_RPC_SPI=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_RENESAS_SDHI=y
+CONFIG_BITBANGMII=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_ETH=y
+CONFIG_RENESAS_RAVB=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_SCIF_CONSOLE=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SMBIOS_MANUFACTURER=""
index 69adb0b..2d639a1 100644 (file)
@@ -32,6 +32,7 @@ CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
+CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIMER=y
 CONFIG_CMD_EXT4_WRITE=y
index 552f1b4..2fe5318 100644 (file)
@@ -47,6 +47,8 @@ CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_CMD_MTDPARTS_SPREAD=y
index 35eb5f1..4594f80 100644 (file)
@@ -3,8 +3,10 @@ CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_mini_emmc"
 CONFIG_SYS_ICACHE_OFF=y
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x10000
+CONFIG_SYS_MALLOC_F_LEN=0x1000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x80
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x600
 CONFIG_SPL=y
 # CONFIG_CMD_ZYNQMP is not set
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-mini-emmc0"
index eaec137..d7c64b9 100644 (file)
@@ -3,8 +3,10 @@ CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_mini_emmc"
 CONFIG_SYS_ICACHE_OFF=y
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x10000
+CONFIG_SYS_MALLOC_F_LEN=0x1000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x80
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x600
 CONFIG_SPL=y
 # CONFIG_CMD_ZYNQMP is not set
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-mini-emmc1"
index 0bf4b7d..fbff215 100644 (file)
@@ -56,6 +56,7 @@ CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_BMP=y
 CONFIG_CMD_CACHE=y
+CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIMER=y
 CONFIG_CMD_TPM=y
index a686d47..683e4b5 100644 (file)
@@ -56,7 +56,6 @@ quiet_cmd_sphinx = SPHINX  $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
        PYTHONDONTWRITEBYTECODE=1 \
        BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \
        $(SPHINXBUILD) \
-       -W \
        -b $2 \
        -c $(abspath $(srctree)/$(src)) \
        -d $(abspath $(BUILDDIR)/.doctrees/$3) \
index 60ee1e0..e052b6b 100644 (file)
@@ -17,6 +17,12 @@ of the sandbox U-Boot. The purpose of running U-Boot under Linux is to test
 all the generic code, not specific to any one architecture. The idea is to
 create unit tests which we can run to test this upper level code.
 
+Sandbox allows development of many types of new features in a traditional way,
+rather than needing to test each iteration on real hardware. Many U-Boot
+features were developed on sandbox, including the core driver model, most
+uclasses, verified boot, bloblist, logging and dozens of others. Sandbox has
+enabled many large-scale code refactors as well.
+
 CONFIG_SANDBOX is defined when building a native board.
 
 The board name is 'sandbox' but the vendor name is unset, so there is a
@@ -76,7 +82,7 @@ console::
 You can issue commands as your would normally. If the command you want is
 not supported you can add it to include/configs/sandbox.h.
 
-To exit, type 'reset' or press Ctrl-C.
+To exit, type 'poweroff' or press Ctrl-C.
 
 
 Console / LCD support
@@ -383,6 +389,8 @@ the contents of the root directory on the second partion of the image
    =>host bind 0 ./disk.raw
    =>ls host 0:2
 
+The device can be marked removeable with 'host bind -r'.
+
 A disk image can be created using the following commands::
 
    $> truncate -s 1200M ./disk.raw
@@ -486,42 +494,10 @@ Testing
 -------
 
 U-Boot sandbox can be used to run various tests, mostly in the test/
-directory. These include:
-
-command_ut:
-  Unit tests for command parsing and handling
-compression:
-  Unit tests for U-Boot's compression algorithms, useful for
-  security checking. It supports gzip, bzip2, lzma and lzo.
-driver model:
-  Run this pytest::
-
-   ./test/py/test.py --bd sandbox --build -k ut_dm -v
-
-image:
-  Unit tests for images:
-  test/image/test-imagetools.sh - multi-file images
-  test/image/test-fit.py        - FIT images
-tracing:
-  test/trace/test-trace.sh tests the tracing system (see README.trace)
-verified boot:
-  See test/vboot/vboot_test.sh for this
-
-If you change or enhance any of the above subsystems, you shold write or
-expand a test and include it with your patch series submission. Test
-coverage in U-Boot is limited, as we need to work to improve it.
-
-Note that many of these tests are implemented as commands which you can
-run natively on your board if desired (and enabled).
-
-To run all tests use "make check".
-
-To run a single test in an existing sandbox build, you can use -T to use the
-test device tree, and -c to select the test:
-
-  /tmp/b/sandbox/u-boot -T -c "ut dm pci_busdev"
+directory.
 
-This runs dm_test_pci_busdev() which is in test/dm/pci.c
+See :doc:`../develop/tests_sandbox` for more information and
+:doc:`../develop/testing` for information about testing generally.
 
 
 Memory Map
@@ -537,5 +513,7 @@ Addr      Config                     Usage
    e000   CONFIG_BLOBLIST_ADDR       Blob list
   10000   CONFIG_MALLOC_F_ADDR       Early memory allocation
   f0000   CONFIG_PRE_CON_BUF_ADDR    Pre-console buffer
- 100000   CONFIG_TRACE_EARLY_ADDR    Early trace buffer (if enabled)
+ 100000   CONFIG_TRACE_EARLY_ADDR    Early trace buffer (if enabled). Also used
+                                     as the SPL load buffer in spl_test_load().
+ 200000   CONFIG_SYS_TEXT_BASE       Load buffer for U-Boot (sandbox_spl only)
 =======   ========================   ===============================
index cc307aa..2ebfed8 100644 (file)
@@ -709,8 +709,8 @@ to load a 'u-boot-payload.efi', see below test logs on QEMU.
   No controllers found
   Hit any key to stop autoboot:  0
 
-See :doc:`../uefi/u-boot_on_efi` and :doc:`../uefi/uefi` for details of
-EFI support in U-Boot.
+See :doc:`../develop/uefi/u-boot_on_efi` and :doc:`../develop/uefi/uefi` for
+details of EFI support in U-Boot.
 
 Chain-loading
 -------------
index 9fec75f..33ce4bc 100644 (file)
@@ -60,7 +60,7 @@ to be pointing to the EFI System Partition which contains the capsule
 file. The BootNext, BootXXXX and OsIndications variables can be set
 using the following commands::
 
-    => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name>
+    => efidebug boot add -b 0 Boot0000 virtio 0:1 <capsule_file_name>
     => efidebug boot next 0
     => setenv -e -nv -bs -rt -v OsIndications =0x04
     => saveenv
@@ -198,7 +198,7 @@ command line::
     3. Set the following environment and UEFI boot variables
 
         => setenv -e -nv -bs -rt -v OsIndications =0x04
-        => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name>
+        => efidebug boot add -b 0 Boot0000 virtio 0:1 <capsule_file_name>
         => efidebug boot next 0
         => saveenv
 
index c39f1e3..4b58567 100644 (file)
@@ -16,6 +16,169 @@ Note that booting U-Boot on APL is already supported by coreboot and
 Slim Bootloader. This documentation refers to a 'bare metal' port.
 
 
+Building
+--------
+
+First, you need the following binary blobs:
+
+   * descriptor.bin - Intel flash descriptor
+   * fitimage.bin - Base flash image structure
+   * fsp_m.bin - FSP-M, for setting up SDRAM
+   * fsp_s.bin - FSP-S, for setting up Silicon
+   * vbt.bin - for setting up display
+
+These binaries do not seem to be available publicly. If you have a ROM image,
+such as santa.bin then you can do this::
+
+  cbfstool santa.bin extract -n fspm.bin -f fsp-m.bin
+  cbfstool santa.bin extract -n fsps.bin -f fsp-s.bin
+  cbfstool santa.bin extract -n vbt-santa.bin -f vbt.bin
+  mkdir tmp
+  cd tmp
+  dump_fmap -x ../santa.bin
+  mv SI_DESC ../descriptor.bin
+  mv IFWI ../fitimage.bin
+
+Put all of these files in `board/google/chromebook_coral` so they can be found
+by the build.
+
+To build::
+
+  make O=/tmp/b/chromebook_coral chromebook_coral_defconfig
+  make O=/tmp/b/chromebook_coral -s -j30 all
+
+That should produce `/tmp/b/chrombook_coral/u-boot.rom` which you can use with
+a Dediprog em100::
+
+  em100 -s -c w25q128fw -d /tmp/b/chromebook_coral/u-boot.rom -r
+
+or you can use flashrom to write it to the board. If you do that, make sure you
+have a way to restore the old ROM without booting the board. Otherwise you may
+brick it. Having said that, you may find these instructions useful if you want
+to unbrick your device:
+
+  https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging.md
+
+You can buy Suzy-Q from Sparkfun:
+
+  https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/main/docs/ccd.md#suzyq-suzyqable
+
+Note that it will hang at the SPL prompt for 21 seconds. When booting into
+Chrome OS it will always select developer mode, so will wipe anything you have
+on the device if you let it proceed. You have two seconds in U-Boot to stop the
+auto-boot prompt and several seconds at the 'developer wipe' screen to stop it
+wiping the disk.
+
+Here is the console output::
+
+  U-Boot TPL 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
+  Trying to boot from Mapped SPI
+
+  U-Boot SPL 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
+  Trying to boot from Mapped SPI
+
+
+  U-Boot 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
+
+  CPU:   Intel(R) Celeron(R) CPU N3450 @ 1.10GHz
+  DRAM:  3.9 GiB
+  MMC:   sdmmc@1b,0: 1, emmc@1c,0: 2
+  Video: 1024x768x32 @ b0000000
+  Model: Google Coral
+  Net:   No ethernet found.
+  SF: Detected w25q128fw with page size 256 Bytes, erase size 4 KiB, total 16 MiB
+  Hit any key to stop autoboot:  0
+  cmdline=console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=${uuid}/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=${uuid} add_efi_memmap boot=local noresume noswap i915.modeset=1 Kernel command line: "console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off  "
+  Setup located at 00090000:
+
+  ACPI RSDP addr      : 7991f000
+  E820: 14 entries
+                Addr              Size  Type
+      d0000000     1000000  <NULL>
+             0       a0000  RAM
+         a0000       60000  Reserved
+      7b000000      800000  Reserved
+      7b800000     4800000  Reserved
+      7ac00000      400000  Reserved
+        100000     ff00000  RAM
+      10000000     2151000  Reserved
+      12151000    68aaf000  RAM
+     100000000    80000000  RAM
+      e0000000    10000000  Reserved
+      7991bfd0     12e4030  Reserved
+      d0000000    10000000  Reserved
+      fed10000        8000  Reserved
+  Setup sectors       : 1e
+  Root flags          : 1
+  Sys size            : 63420
+  RAM size            : 0
+  Video mode          : ffff
+  Root dev            : 0
+  Boot flag           : 0
+  Jump                : 66eb
+  Header              : 53726448
+                        Kernel V2
+  Version             : 20d
+  Real mode switch    : 0
+  Start sys           : 1000
+  Kernel version      : 38cc
+     @00003acc:
+  Type of loader      : 80
+                        U-Boot, version 0
+  Load flags          : 81
+                      : loaded-high can-use-heap
+  Setup move size     : 8000
+  Code32 start        : 100000
+  Ramdisk image       : 0
+  Ramdisk size        : 0
+  Bootsect kludge     : 0
+  Heap end ptr        : 8e00
+  Ext loader ver      : 0
+  Ext loader type     : 0
+  Command line ptr    : 99000
+     console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off
+  Initrd addr max     : 7fffffff
+  Kernel alignment    : 200000
+  Relocatable kernel  : 1
+  Min alignment       : 15
+                      : 200000
+  Xload flags         : 3
+                      : 64-bit-entry can-load-above-4gb
+  Cmdline size        : 7ff
+  Hardware subarch    : 0
+  HW subarch data     : 0
+  Payload offset      : 26e
+  Payload length      : 612045
+  Setup data          : 0
+  Pref address        : 1000000
+  Init size           : 1383000
+  Handover offset     : 0
+
+  Starting kernel ...
+
+  Timer summary in microseconds (17 records):
+         Mark    Elapsed  Stage
+            0          0  reset
+      155,279    155,279  TPL
+      237,088     81,809  end phase
+      237,533        445  SPL
+      816,456    578,923  end phase
+      817,357        901  board_init_f
+    1,061,751    244,394  board_init_r
+    1,402,435    340,684  id=64
+    1,430,071     27,636  main_loop
+    5,532,057  4,101,986  start_kernel
+
+  Accumulated time:
+                     685  dm_r
+                   2,817  fast_spi
+                  33,095  dm_spl
+                  52,468  dm_f
+                 208,242  fsp-m
+                 242,221  fsp-s
+                 332,710  mmap_spi
+
+
 Boot flow - TPL
 ---------------
 
@@ -181,7 +344,7 @@ Partial memory map
     ff000000       Bottom of ROM
     fefc0000       Top of CAR region
     fef96000       Stack for FSP-M
-    fef40000 59000 FSP-M
+    fef40000 59000 FSP-M (also VPL loads here)
     fef11000       SPL loaded here
     fef10000       CONFIG_BLOBLIST_ADDR
     fef10000       Stack top in TPL, SPL and U-Boot before relocation
@@ -195,35 +358,72 @@ Partial memory map
      1110000       CONFIG_SYS_TEXT_BASE
 
 
+Speeding up SPL for development
+-------------------------------
+
+The 21-second wait for memory training is annoying during development, since
+every new image incurs this cost when booting. There is no cache to fall back on
+since that area of the image is empty on start-up.
+
+You can add suitable cache contents to the image to fix this, for development
+purposes only, like this::
+
+   # Read the image back after booting through SPL
+   em100 -s -c w25q128fw -u image.bin
+
+   # Extract the two cache regions
+   binman extract -i image.bin extra *cache
+
+   # Move them into the source directory
+   mv *cache board/google/chromebook_coral
+
+Then add something like this to the devicetree::
+
+  #if IS_ENABLED(CONFIG_HAVE_MRC) || IS_ENABLED(CONFIG_FSP_VERSION2)
+     /* Provide initial contents of the MRC data for faster development */
+     rw-mrc-cache {
+        type = "blob";
+        /* Mirror the offset in spi-flash@0 */
+        offset = <0xff8e0000>;
+        size = <0x10000>;
+        filename = "board/google/chromebook_coral/rw-mrc-cache";
+     };
+     rw-var-mrc-cache {
+        type = "blob";
+        size = <0x1000>;
+        filename = "board/google/chromebook_coral/rw-var-mrc-cache";
+     };
+  #endif
+
+This tells binman to put the cache contents in the same place as the
+`rw-mrc-cache` and `rw-var-mrc-cache` regions defined by the SPI-flash driver.
+
+
 Supported peripherals
 ---------------------
 
-- UART
-- SPI flash
-- Video
-- MMC (dev 0) and micro-SD (dev 1)
-- Chrome OS EC
-- Keyboard
-- USB
+The following have U-Boot drivers:
+
+   - UART
+   - SPI flash
+   - Video
+   - MMC (dev 0) and micro-SD (dev 1)
+   - Chrome OS EC
+   - Cr50 (security chip)
+   - Keyboard
+   - USB
 
 
 To do
 -----
 
 - Finish peripherals
-   - left-side USB
-   - USB-C
-   - Cr50 (security chip: a basic driver is running but not included here)
    - Sound (Intel I2S support exists, but need da7219 driver)
-   - Various minor features supported by LPC, etc.
-- Booting Chrome OS, e.g. with verified boot
-- Integrate with Chrome OS vboot
-- Improvements to booting from coreboot (i.e. as a coreboot target)
 - Use FSP-T binary instead of our own CAR implementation
 - Use the official FSP package instead of the coreboot one
-- Enable all CPU cores
 - Suspend / resume
-- ACPI
+- Fix MMC which seems to try to read even though the card is empty
+- Fix USB3 crash "WARN halted endpoint, queueing URB anyway."
 
 
 Credits
similarity index 79%
rename from doc/README.chromium-chainload
rename to doc/chromium/chainload.rst
index 45eaece..7b6bb10 100644 (file)
@@ -1,3 +1,6 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+
 Running U-Boot from coreboot on Chromebooks
 ===========================================
 
@@ -15,7 +18,7 @@ replace the ROM unless you have a servo board and cable to restore it with.
 
 
 For all of these the standard U-Boot build instructions apply. For example on
-ARM:
+ARM::
 
    sudo apt install gcc-arm-linux-gnueabi
    mkdir b
@@ -37,14 +40,17 @@ https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-t
 Nyan-big
 --------
 
-Compiled based on information here:
-https://lists.denx.de/pipermail/u-boot/2015-March/209530.html
-https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big
-https://lists.denx.de/pipermail/u-boot/2017-May/289491.html
-https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card
+Compiled based on information here::
+
+   https://lists.denx.de/pipermail/u-boot/2015-March/209530.html
+   https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big
+   https://lists.denx.de/pipermail/u-boot/2017-May/289491.html
+   https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card
 
 1. Build U-Boot
 
+Steps::
+
    mkdir b
    make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
 
@@ -61,16 +67,21 @@ kernel, and crashes if it is not present.
 
 3. Build and sign an image
 
-   ./b/nyan-big/tools/mkimage -f doc/chromium/nyan-big.its u-boot-chromium.fit
+Steps::
+
+   ./b/nyan-big/tools/mkimage -f doc/chromium/files/nyan-big.its u-boot-chromium.fit
    echo test >dummy.txt
-   vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
-       --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
-       --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
-       --bootloader dummy.txt --pack u-boot.kpart
+   vbutil_kernel --arch arm \
+     --keyblock doc/chromium/files/devkeys/kernel.keyblock \
+     --signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk \
+     --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
+     --bootloader dummy.txt --pack u-boot.kpart
 
 
 4. Prepare an SD card
 
+Steps::
+
    DISK=/dev/sdc   # Replace with your actual SD card device
    sudo cgpt create $DISK
    sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK
@@ -80,6 +91,8 @@ kernel, and crashes if it is not present.
 
 5. Write U-Boot to the SD card
 
+Steps::
+
    sudo dd if=u-boot.kpart of=/dev/sdc1; sync
 
 
@@ -90,7 +103,7 @@ do this, login as root (via Ctrl-Alt-forward_arrow) and type
 'enable_dev_usb_boot'. You only need to do this once.
 
 Reboot the device with the SD card inserted. Press Clrl-U at the developer
-mode screen. It should show something like the following on the display:
+mode screen. It should show something like the following on the display::
 
    U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600)
 
@@ -104,9 +117,9 @@ mode screen. It should show something like the following on the display:
 
 7. Known problems
 
-On the serial console the word MMC is chopped at the start of the line:
+On the serial console the word MMC is chopped at the start of the line::
 
-C:   sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0
+   C:   sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0
 
 This is likely due to some problem with change-over of the serial driver
 during relocation (or perhaps updating the clock setup in board_init()).
@@ -116,7 +129,7 @@ during relocation (or perhaps updating the clock setup in board_init()).
 
 To check that you copied the u-boot.its file correctly, use these commands.
 You should see that the data at 0x100 in u-boot-chromium.fit is the first few
-bytes of U-Boot:
+bytes of U-Boot::
 
    hd u-boot-chromium.fit |head -20
    ...
@@ -141,34 +154,39 @@ The instruction are similar to those for Nyan with changes as noted below:
 
 Open include/configs/rk3288_common.h
 
-Change:
+Change::
 
-#define CONFIG_SYS_TEXT_BASE           0x00100000
+   #define CONFIG_SYS_TEXT_BASE                0x00100000
 
-to:
+to::
 
-#define CONFIG_SYS_TEXT_BASE           0x02000100
+   #define CONFIG_SYS_TEXT_BASE                0x02000100
 
 
 
 2. Build U-Boot
 
+Steps::
+
    mkdir b
    make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \
-       chromebook_jerry_defconfig all
+      chromebook_jerry_defconfig all
 
 
 3. See above
 
 4. Build and sign an image
 
+Steps::
+
    ./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \
-       u-boot-chromium.fit
+      u-boot-chromium.fit
    echo test >dummy.txt
-   vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
-       --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
-       --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
-       --bootloader dummy.txt --pack u-boot.kpart
+   vbutil_kernel --arch arm \
+      --keyblock doc/chromium/files/devkeys/kernel.keyblock \
+      --signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk \
+      --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
+      --bootloader dummy.txt --pack u-boot.kpart
 
 
 5. See above
@@ -182,7 +200,7 @@ do this, login as root (via Ctrl-Alt-forward_arrow) and type
 'enable_dev_usb_boot'. You only need to do this once.
 
 Reboot the device with the SD card inserted. Press Clrl-U at the developer
-mode screen. It should show something like the following on the display:
+mode screen. It should show something like the following on the display::
 
    U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600)
 
@@ -203,18 +221,18 @@ None as yet.
 
 
 Other notes
-===========
+-----------
 
 flashrom
---------
+~~~~~~~~
 
-   Used to make a backup of your firmware, or to replace it.
+Used to make a backup of your firmware, or to replace it.
 
-   See: https://www.chromium.org/chromium-os/packages/cros-flashrom
+See: https://www.chromium.org/chromium-os/packages/cros-flashrom
 
 
 coreboot
---------
+~~~~~~~~
 
 Coreboot itself is not designed to actually boot an OS. Instead, a program
 called Depthcharge is used. This originally came out of U-Boot and was then
diff --git a/doc/chromium/index.rst b/doc/chromium/index.rst
new file mode 100644 (file)
index 0000000..0722c25
--- /dev/null
@@ -0,0 +1,14 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+
+Chromium OS-specific doc
+========================
+
+This provides some information about Chromium OS and U-Boot.
+
+.. toctree::
+   :maxdepth: 2
+
+   overview
+   run_vboot
+   chainload
diff --git a/doc/chromium/overview.rst b/doc/chromium/overview.rst
new file mode 100644 (file)
index 0000000..5498ed9
--- /dev/null
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+
+Chromium OS Support in U-Boot
+=============================
+
+Introduction
+------------
+
+This describes how to use U-Boot with Chromium OS. Several options are
+available:
+
+   - Running U-Boot from the 'altfw' feature, which is available on selected
+     Chromebooks from 2019 onwards (initially Grunt). Press '1' from the
+     developer-mode screen to get into U-Boot. See here for details:
+     https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_mode.md
+
+   - Running U-Boot from the disk partition. This involves signing U-Boot and
+     placing it on the disk, for booting as a 'kernel'. See
+     :doc:`chainload` for information on this. This is the only
+     option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat
+     more involved.
+
+   - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be
+     used instead of either or both of depthcharge (a bootloader which forked
+     from U-Boot in 2013) and coreboot. See :doc:`run_vboot` for more
+     information on this.
+
+   - Running U-Boot from coreboot. This allows U-Boot to run on more devices
+     since many of them only support coreboot as the bootloader and have
+     no bare-metal support in U-Boot. For this, use the 'coreboot' target.
+
+   - Running U-Boot and booting into a Chrome OS image, but without verified
+     boot. This can be useful for testing.
+
+
+Talks and documents
+-------------------
+
+Here is some material relevant to Chromium OS verified boot with U-Boot:
+
+   - "U-Boot with Chrome OS and firmware packaging"
+
+     - Author: Simon Glass
+     - Presented at Open Source Firmware Conference 2018, Erlangen
+     - Describes the work in progress as at the end of 2018
+     - Slides at `OSFC <https://2018.osfc.io/uploads/talk/paper/26/U-Boot_with_Chrome_OS_and_firmware_packaging.pdf>`_
+     - Video on `Youtube <https://www.youtube.com/watch?v=1jknxUvmwpo>`_
+
+   - "Verified Boot in Chrome OS and how to make it work for you"
+
+     - Author: Simon Glass
+     - Presented at ELCE 2013, Edinburgh
+     - Describes the original 2013 implementation as shipped on snow (first
+       `ARM Chromebook was a Samsung Chromebook <https://www.cnet.com/products/samsung-series-3-chromebook-xe303c12-11-6-exynos-5250-2-gb-ram-16-gb-ssd-bilingual-english-french/>`_
+       with Samsung Exynos5250 `review <https://www.cnet.com/reviews/samsung-chromebook-series-3-review/>`_),
+       spring (`HP Chromebook 11 <https://www.cnet.com/products/hp-chromebook-11-g2-11-6-exynos-5250-4-gb-ram-16-gb-emmc/>`_)
+       and pit/pi (`Samsung Chromebook 2 <https://www.cnet.com/products/samsung-chromebook-2-xe503c12-11-6-exynos-5-octa-4-gb-ram-16-gb-ssd/>`_
+       with Exynos 5 Octa 5420 in 2014).
+     - Slides at `Google research <https://research.google/pubs/pub42038/>`_
+     - Video at `Youtube <https://www.youtube.com/watch?v=kdpZC9jFzZA>`_
+
+   - "Chrome University 2018: Chrome OS Firmware and Verified Boot 201"
+
+     - Author: Duncan Laurie
+     - Describes Chrome OS firmware as of 2018 and includes a wide range of
+       topics. This has no U-Boot information, but does cover coreboot and also
+       talks about the Chrome OS EC and Security chip. This is probably the
+       best introduction talk.
+     - Video at `YouTube <https://www.youtube.com/watch?v=WY2sWpuda2g>`_
+
+   - `Chromium OS U-Boot <https://www.chromium.org/developers/u-boot>`_
+
+   - `Firmware porting Guide <https://www.chromium.org/chromium-os/firmware-porting-guide>`_
similarity index 68%
rename from doc/README.chromium
rename to doc/chromium/run_vboot.rst
index 75f2f24..41b4f63 100644 (file)
@@ -1,42 +1,14 @@
-Chromium OS Support in U-Boot
-=============================
-
-Introduction
-------------
-
-This describes how to use U-Boot with Chromium OS. Several options are
-available:
-
-   - Running U-Boot from the 'altfw' feature, which is available on selected
-        Chromebooks from 2019 onwards (initially Grunt). Press '1' from the
-        developer-mode screen to get into U-Boot. See here for details:
-        https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device?pli=1
-
-   - Running U-Boot from the disk partition. This involves signing U-Boot and
-        placing it on the disk, for booting as a 'kernel'. See
-        README.chromium-chainload for information on this. This is the only
-        option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat
-        more involved.
-
-   - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be
-        used instead of either or both of depthcharge (a bootloader which forked
-        from U-Boot in 2013) and coreboot. See below for more information on
-        this.
-
-   - Running U-Boot from coreboot. This allows U-Boot to run on more devices
-        since many of them only support coreboot as the bootloader and have
-        no bare-metal support in U-Boot. For this, use the 'coreboot' target.
-
-   - Running U-Boot and booting into a Chrome OS image, but without verified
-        boot. This can be useful for testing.
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+.. sectionauthor:: Simon Glass <sjg@chromium.org>
 
 
-U-Boot with Chromium OS verified boot
--------------------------------------
+Running U-Boot with Chromium OS verified boot
+=============================================
 
-To obtain:
+To obtain::
 
-   git clone https://github.com/sglass68/u-boot.git
+   git clone https://github.com/sjg20/u-boot.git
    cd u-boot
    git checkout cros-master
 
@@ -46,28 +18,35 @@ To obtain:
    git checkout 45964294
    #  futility: updater: Correct output version for Snow
 
-To build for sandbox:
+To build for sandbox::
 
    UB=/tmp/b/chromeos_sandbox    # U-Boot build directory
    cd u-boot
    make O=$UB chromeos_sandbox_defconfig
    make O=$UB -j20 -s VBOOT_SOURCE=/path/to/vboot_reference \
-       MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1
+     MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1
 
 Replace sandbox with another supported target.
 
 This produces $UB/image.bin which contains the firmware binaries in a SPI
 flash image.
 
-To run on sandbox:
+To run on sandbox::
 
+   CROS=~/cosarm
+   IMG=$CROS/src/build/images/coral/latest/chromiumos_image.bin
    $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out \
-       -L6 -c "host bind 0 $CROS/src/build/images/cheza/latest/chromiumos_image.bin; vboot go auto" \
-       -l -w -s state.dtb -r
+     -L6 -c "host bind 0 $IMG; vboot go auto" \
+     -l -w -s state.dtb -r -n -m $UB/ram
+
+   $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out -L6 -l \
+     -c "host bind 0 $IMG; vboot go auto" -w -s $UB/state.dtb -r -n -m $UB/mem
+
 
 To run on other boards:
-   Install image.bin in the SPI flash of your device
-   Boot your system
+
+   - Install image.bin in the SPI flash of your device
+   - Boot your system
 
 
 Sandbox
@@ -83,7 +62,7 @@ a device tree and binding a Chromium OS disk image for use to find kernels
 phases into state.dtb and will automatically ensure that memory is shared
 between all phases. TPL will jump to SPL and then on to U-Boot proper.
 
-It is possible to run with debugging on, e.g.
+It is possible to run with debugging on, e.g.::
 
    gdb --args $UB/tpl/u-boot-tpl -d ....
 
@@ -95,7 +74,7 @@ Samus
 -----
 
 Basic support is available for samus, using the chromeos_samus target. If you
-have an em100, use:
+have an em100, use::
 
    sudo em100 -s -c W25Q128FW -d $UB/image.bin -t -r
 
@@ -119,11 +98,20 @@ New uclasses
 
 Several uclasses are provided in cros/:
 
-       UCLASS_CROS_AUX_FW              Chrome OS auxiliary firmware
-       UCLASS_CROS_FWSTORE             Chrome OS firmware storage
-       UCLASS_CROS_NVDATA              Chrome OS non-volatile data device
-       UCLASS_CROS_VBOOT_EC            Chrome OS vboot EC operations
-       UCLASS_CROS_VBOOT_FLAG          Chrome OS verified boot flag
+UCLASS_CROS_AUX_FW
+   Chrome OS auxiliary firmware
+
+UCLASS_CROS_FWSTORE
+   Chrome OS firmware storage
+
+UCLASS_CROS_NVDATA
+   Chrome OS non-volatile data device
+
+UCLASS_CROS_VBOOT_EC
+   Chrome OS vboot EC operations
+
+UCLASS_CROS_VBOOT_FLAG
+   Chrome OS verified boot flag
 
 The existing UCLASS_CROS_EC is also used.
 
@@ -181,7 +169,7 @@ detect problems that affect the flow or particular vboot features.
 U-Boot without Chromium OS verified boot
 ----------------------------------------
 
-The following script can be used to boot a Chrome OS image on coral:
+The following script can be used to boot a Chrome OS image on coral::
 
    # Read the image header and obtain the address of the kernel
    # The offset 4f0 is defined by verified boot and may change for other
@@ -213,6 +201,4 @@ TO DO
 Get the full ACPI tables working with Coral
 
 
-Simon Glass
-sjg@chromium.org
 7 October 2018
similarity index 68%
rename from doc/driver-model/index.rst
rename to doc/develop/driver-model/index.rst
index c9faf0a..fd4575d 100644 (file)
@@ -3,6 +3,10 @@
 Driver Model
 ============
 
+The following holds information on the U-Boot device driver framework:
+driver-model, including the design details of itself and several driver
+subsystems
+
 .. toctree::
    :maxdepth: 2
 
diff --git a/doc/develop/driver-model/of-plat.rst b/doc/develop/driver-model/of-plat.rst
new file mode 100644 (file)
index 0000000..74f1932
--- /dev/null
@@ -0,0 +1,913 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Compiled-in Device Tree / Platform Data
+=======================================
+
+
+Introduction
+------------
+
+Device tree is the standard configuration method in U-Boot. It is used to
+define what devices are in the system and provide configuration information
+to these devices.
+
+The overhead of adding devicetree access to U-Boot is fairly modest,
+approximately 3KB on Thumb 2 (plus the size of the DT itself). This means
+that in most cases it is best to use devicetree for configuration.
+
+However there are some very constrained environments where U-Boot needs to
+work. These include SPL with severe memory limitations. For example, some
+SoCs require a 16KB SPL image which must include a full MMC stack. In this
+case the overhead of devicetree access may be too great.
+
+It is possible to create platform data manually by defining C structures
+for it, and reference that data in a `U_BOOT_DRVINFO()` declaration. This
+bypasses the use of devicetree completely, effectively creating a parallel
+configuration mechanism. But it is an available option for SPL.
+
+As an alternative, the 'of-platdata' feature is provided. This converts the
+devicetree contents into C code which can be compiled into the SPL binary.
+This saves the 3KB of code overhead and perhaps a few hundred more bytes due
+to more efficient storage of the data.
+
+
+How it works
+------------
+
+The feature is enabled by CONFIG OF_PLATDATA. This is only available in
+SPL/TPL and should be tested with:
+
+.. code-block:: c
+
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
+
+A tool called 'dtoc' converts a devicetree file either into a set of
+struct declarations, one for each compatible node, and a set of
+`U_BOOT_DRVINFO()` declarations along with the actual platform data for each
+device. As an example, consider this MMC node:
+
+.. code-block:: none
+
+    sdmmc: dwmmc@ff0c0000 {
+            compatible = "rockchip,rk3288-dw-mshc";
+            clock-freq-min-max = <400000 150000000>;
+            clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+                     <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+            clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+            fifo-depth = <0x100>;
+            interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+            reg = <0xff0c0000 0x4000>;
+            bus-width = <4>;
+            cap-mmc-highspeed;
+            cap-sd-highspeed;
+            card-detect-delay = <200>;
+            disable-wp;
+            num-slots = <1>;
+            pinctrl-names = "default";
+            pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
+                vmmc-supply = <&vcc_sd>;
+                status = "okay";
+                u-boot,dm-pre-reloc;
+        };
+
+
+Some of these properties are dropped by U-Boot under control of the
+CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce
+the following C struct declaration:
+
+.. code-block:: c
+
+    struct dtd_rockchip_rk3288_dw_mshc {
+            fdt32_t         bus_width;
+            bool            cap_mmc_highspeed;
+            bool            cap_sd_highspeed;
+            fdt32_t         card_detect_delay;
+            fdt32_t         clock_freq_min_max[2];
+            struct phandle_1_arg clocks[4];
+            bool            disable_wp;
+            fdt32_t         fifo_depth;
+            fdt32_t         interrupts[3];
+            fdt32_t         num_slots;
+            fdt32_t         reg[2];
+            fdt32_t         vmmc_supply;
+    };
+
+and the following device declarations:
+
+.. code-block:: c
+
+    /* Node /clock-controller@ff760000 index 0 */
+    ...
+
+    /* Node /dwmmc@ff0c0000 index 2 */
+    static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = {
+            .fifo_depth             = 0x100,
+            .cap_sd_highspeed       = true,
+            .interrupts             = {0x0, 0x20, 0x4},
+            .clock_freq_min_max     = {0x61a80, 0x8f0d180},
+            .vmmc_supply            = 0xb,
+            .num_slots              = 0x1,
+            .clocks                 = {{0, 456},
+                                       {0, 68},
+                                       {0, 114},
+                                       {0, 118}},
+            .cap_mmc_highspeed      = true,
+            .disable_wp             = true,
+            .bus_width              = 0x4,
+            .u_boot_dm_pre_reloc    = true,
+            .reg                    = {0xff0c0000, 0x4000},
+            .card_detect_delay      = 0xc8,
+    };
+
+    U_BOOT_DRVINFO(dwmmc_at_ff0c0000) = {
+            .name           = "rockchip_rk3288_dw_mshc",
+            .plat       = &dtv_dwmmc_at_ff0c0000,
+            .plat_size  = sizeof(dtv_dwmmc_at_ff0c0000),
+            .parent_idx     = -1,
+    };
+
+The device is then instantiated at run-time and the platform data can be
+accessed using:
+
+.. code-block:: c
+
+    struct udevice *dev;
+    struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_plat(dev);
+
+This avoids the code overhead of converting the devicetree data to
+platform data in the driver. The `of_to_plat()` method should
+therefore do nothing in such a driver.
+
+Note that for the platform data to be matched with a driver, the 'name'
+property of the `U_BOOT_DRVINFO()` declaration has to match a driver declared
+via `U_BOOT_DRIVER()`. This effectively means that a `U_BOOT_DRIVER()` with a
+'name' corresponding to the devicetree 'compatible' string (after converting
+it to a valid name for C) is needed, so a dedicated driver is required for
+each 'compatible' string.
+
+In order to make this a bit more flexible, the `DM_DRIVER_ALIAS()` macro can be
+used to declare an alias for a driver name, typically a 'compatible' string.
+This macro produces no code, but is used by dtoc tool. It must be located in the
+same file as its associated driver, ideally just after it.
+
+The parent_idx is the index of the parent `driver_info` structure within its
+linker list (instantiated by the `U_BOOT_DRVINFO()` macro). This is used to
+support `dev_get_parent()`.
+
+During the build process dtoc parses both `U_BOOT_DRIVER()` and
+`DM_DRIVER_ALIAS()` to build a list of valid driver names and driver aliases.
+If the 'compatible' string used for a device does not not match a valid driver
+name, it will be checked against the list of driver aliases in order to get the
+right driver name to use. If in this step there is no match found a warning is
+issued to avoid run-time failures.
+
+Where a node has multiple compatible strings, dtoc generates a `#define` to
+make them equivalent, e.g.:
+
+.. code-block:: c
+
+    #define dtd_rockchip_rk3299_dw_mshc dtd_rockchip_rk3288_dw_mshc
+
+
+Converting of-platdata to a useful form
+---------------------------------------
+
+Of course it would be possible to use the of-platdata directly in your driver
+whenever configuration information is required. However this means that the
+driver will not be able to support devicetree, since the of-platdata
+structure is not available when devicetree is used. It would make no sense
+to use this structure if devicetree were available, since the structure has
+all the limitations metioned in caveats below.
+
+Therefore it is recommended that the of-platdata structure should be used
+only in the `probe()` method of your driver. It cannot be used in the
+`of_to_plat()` method since this is not called when platform data is
+already present.
+
+
+How to structure your driver
+----------------------------
+
+Drivers should always support devicetree as an option. The of-platdata
+feature is intended as a add-on to existing drivers.
+
+Your driver should convert the plat struct in its `probe()` method. The
+existing devicetree decoding logic should be kept in the
+`of_to_plat()` method and wrapped with `#if`.
+
+For example:
+
+.. code-block:: c
+
+    #include <dt-structs.h>
+
+    struct mmc_plat {
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
+            /* Put this first since driver model will copy the data here */
+            struct dtd_mmc dtplat;
+    #endif
+            /*
+             * Other fields can go here, to be filled in by decoding from
+             * the devicetree (or the C structures when of-platdata is used).
+             */
+            int fifo_depth;
+    };
+
+    static int mmc_of_to_plat(struct udevice *dev)
+    {
+    #if !CONFIG_IS_ENABLED(OF_PLATDATA)
+            /* Decode the devicetree data */
+            struct mmc_plat *plat = dev_get_plat(dev);
+            const void *blob = gd->fdt_blob;
+            int node = dev_of_offset(dev);
+
+            plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0);
+    #endif
+
+            return 0;
+    }
+
+    static int mmc_probe(struct udevice *dev)
+    {
+            struct mmc_plat *plat = dev_get_plat(dev);
+
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
+            /* Decode the of-platdata from the C structures */
+            struct dtd_mmc *dtplat = &plat->dtplat;
+
+            plat->fifo_depth = dtplat->fifo_depth;
+    #endif
+            /* Set up the device from the plat data */
+            writel(plat->fifo_depth, ...)
+    }
+
+    static const struct udevice_id mmc_ids[] = {
+            { .compatible = "vendor,mmc" },
+            { }
+    };
+
+    U_BOOT_DRIVER(mmc_drv) = {
+            .name           = "mmc_drv",
+            .id             = UCLASS_MMC,
+            .of_match       = mmc_ids,
+            .of_to_plat = mmc_of_to_plat,
+            .probe          = mmc_probe,
+            .priv_auto = sizeof(struct mmc_priv),
+            .plat_auto = sizeof(struct mmc_plat),
+    };
+
+    DM_DRIVER_ALIAS(mmc_drv, vendor_mmc) /* matches compatible string */
+
+Note that `struct mmc_plat` is defined in the C file, not in a header. This
+is to avoid needing to include dt-structs.h in a header file. The idea is to
+keep the use of each of-platdata struct to the smallest possible code area.
+There is just one driver C file for each struct, that can convert from the
+of-platdata struct to the standard one used by the driver.
+
+In the case where SPL_OF_PLATDATA is enabled, `plat_auto` is
+still used to allocate space for the platform data. This is different from
+the normal behaviour and is triggered by the use of of-platdata (strictly
+speaking it is a non-zero `plat_size` which triggers this).
+
+The of-platdata struct contents is copied from the C structure data to the
+start of the newly allocated area. In the case where devicetree is used,
+the platform data is allocated, and starts zeroed. In this case the
+`of_to_plat()` method should still set up the platform data (and the
+of-platdata struct will not be present).
+
+SPL must use either of-platdata or devicetree. Drivers cannot use both at
+the same time, but they must support devicetree. Supporting of-platdata is
+optional.
+
+The devicetree becomes inaccessible when CONFIG_SPL_OF_PLATDATA is enabled,
+since the devicetree access code is not compiled in. A corollary is that
+a board can only move to using of-platdata if all the drivers it uses support
+it. There would be little point in having some drivers require the device
+tree data, since then libfdt would still be needed for those drivers and
+there would be no code-size benefit.
+
+
+Build-time instantiation
+------------------------
+
+Even with of-platdata there is a fair amount of code required in driver model.
+It is possible to have U-Boot handle the instantiation of devices at build-time,
+so avoiding the need for the `device_bind()` code and some parts of
+`device_probe()`.
+
+The feature is enabled by CONFIG_OF_PLATDATA_INST.
+
+Here is an example device, as generated by dtoc::
+
+   /*
+    * Node /serial index 6
+    * driver sandbox_serial parent root_driver
+   */
+
+   #include <asm/serial.h>
+   struct sandbox_serial_plat __attribute__ ((section (".priv_data")))
+      _sandbox_serial_plat_serial = {
+      .dtplat = {
+         .sandbox_text_colour   = "cyan",
+      },
+   };
+   #include <asm/serial.h>
+   u8 _sandbox_serial_priv_serial[sizeof(struct sandbox_serial_priv)]
+      __attribute__ ((section (".priv_data")));
+   #include <serial.h>
+   u8 _sandbox_serial_uc_priv_serial[sizeof(struct serial_dev_priv)]
+      __attribute__ ((section (".priv_data")));
+
+   DM_DEVICE_INST(serial) = {
+      .driver     = DM_DRIVER_REF(sandbox_serial),
+      .name       = "sandbox_serial",
+      .plat_      = &_sandbox_serial_plat_serial,
+      .priv_      = _sandbox_serial_priv_serial,
+      .uclass     = DM_UCLASS_REF(serial),
+      .uclass_priv_ = _sandbox_serial_uc_priv_serial,
+      .uclass_node   = {
+         .prev = &DM_UCLASS_REF(serial)->dev_head,
+         .next = &DM_UCLASS_REF(serial)->dev_head,
+      },
+      .child_head   = {
+         .prev = &DM_DEVICE_REF(serial)->child_head,
+         .next = &DM_DEVICE_REF(serial)->child_head,
+      },
+      .sibling_node   = {
+         .prev = &DM_DEVICE_REF(i2c_at_0)->sibling_node,
+         .next = &DM_DEVICE_REF(spl_test)->sibling_node,
+      },
+      .seq_ = 0,
+   };
+
+Here is part of the driver, for reference::
+
+   static const struct udevice_id sandbox_serial_ids[] = {
+      { .compatible = "sandbox,serial" },
+      { }
+   };
+
+   U_BOOT_DRIVER(sandbox_serial) = {
+      .name   = "sandbox_serial",
+      .id   = UCLASS_SERIAL,
+      .of_match    = sandbox_serial_ids,
+      .of_to_plat  = sandbox_serial_of_to_plat,
+      .plat_auto   = sizeof(struct sandbox_serial_plat),
+      .priv_auto   = sizeof(struct sandbox_serial_priv),
+      .probe = sandbox_serial_probe,
+      .remove = sandbox_serial_remove,
+      .ops   = &sandbox_serial_ops,
+      .flags = DM_FLAG_PRE_RELOC,
+   };
+
+
+The `DM_DEVICE_INST()` macro declares a struct udevice so you can see that the
+members are from that struct. The private data is declared immediately above,
+as `_sandbox_serial_priv_serial`, so there is no need for run-time memory
+allocation. The #include lines are generated as well, since dtoc searches the
+U-Boot source code for the definition of `struct sandbox_serial_priv` and adds
+the relevant header so that the code will compile without errors.
+
+The `plat_` member is set to the dtv data which is declared immediately above
+the device. This is similar to how it would look without of-platdata-inst, but
+node that the `dtplat` member inside is part of the wider
+`_sandbox_serial_plat_serial` struct. This is because the driver declares its
+own platform data, and the part generated by dtoc can only be a portion of it.
+The `dtplat` part is always first in the struct. If the device has no
+`.plat_auto` field, then a simple dtv struct can be used as with this example::
+
+   static struct dtd_sandbox_clk dtv_clk_sbox = {
+      .assigned_clock_rates   = 0x141,
+      .assigned_clocks   = {0x7, 0x3},
+   };
+
+   #include <asm/clk.h>
+   u8 _sandbox_clk_priv_clk_sbox[sizeof(struct sandbox_clk_priv)]
+      __attribute__ ((section (".priv_data")));
+
+   DM_DEVICE_INST(clk_sbox) = {
+      .driver    = DM_DRIVER_REF(sandbox_clk),
+      .name      = "sandbox_clk",
+      .plat_     = &dtv_clk_sbox,
+
+Here is part of the driver, for reference::
+
+   static const struct udevice_id sandbox_clk_ids[] = {
+      { .compatible = "sandbox,clk" },
+      { }
+   };
+
+   U_BOOT_DRIVER(sandbox_clk) = {
+      .name       = "sandbox_clk",
+      .id         = UCLASS_CLK,
+      .of_match   = sandbox_clk_ids,
+      .ops        = &sandbox_clk_ops,
+      .probe      = sandbox_clk_probe,
+      .priv_auto  = sizeof(struct sandbox_clk_priv),
+   };
+
+
+You can see that `dtv_clk_sbox` just has the devicetree contents and there is
+no need for the `dtplat` separation, since the driver has no platform data of
+its own, besides that provided by the devicetree (i.e. no `.plat_auto` field).
+
+The doubly linked lists are handled by explicitly declaring the value of each
+node, as you can see with the `.prev` and `.next` values in the example above.
+Since dtoc knows the order of devices it can link them into the appropriate
+lists correctly.
+
+One of the features of driver model is the ability for a uclass to have a
+small amount of private data for each device in that uclass. This is used to
+provide a generic data structure that the uclass can use for all devices, thus
+allowing generic features to be implemented in common code. An example is I2C,
+which stores the bus speed there.
+
+Similarly, parent devices can have data associated with each of their children.
+This is used to provide information common to all children of a particular bus.
+For an I2C bus, this is used to store the I2C address of each child on the bus.
+
+This is all handled automatically by dtoc::
+
+   #include <asm/i2c.h>
+   u8 _sandbox_i2c_priv_i2c_at_0[sizeof(struct sandbox_i2c_priv)]
+      __attribute__ ((section (".priv_data")));
+   #include <i2c.h>
+   u8 _sandbox_i2c_uc_priv_i2c_at_0[sizeof(struct dm_i2c_bus)]
+      __attribute__ ((section (".priv_data")));
+
+   DM_DEVICE_INST(i2c_at_0) = {
+      .driver      = DM_DRIVER_REF(sandbox_i2c),
+      .name      = "sandbox_i2c",
+      .plat_   = &dtv_i2c_at_0,
+      .priv_      = _sandbox_i2c_priv_i2c_at_0,
+      .uclass   = DM_UCLASS_REF(i2c),
+      .uclass_priv_ = _sandbox_i2c_uc_priv_i2c_at_0,
+     ...
+
+Part of driver, for reference::
+
+   static const struct udevice_id sandbox_i2c_ids[] = {
+      { .compatible = "sandbox,i2c" },
+      { }
+   };
+
+   U_BOOT_DRIVER(sandbox_i2c) = {
+      .name   = "sandbox_i2c",
+      .id   = UCLASS_I2C,
+      .of_match = sandbox_i2c_ids,
+      .ops   = &sandbox_i2c_ops,
+      .priv_auto   = sizeof(struct sandbox_i2c_priv),
+   };
+
+Part of I2C uclass, for reference::
+
+   UCLASS_DRIVER(i2c) = {
+      .id         = UCLASS_I2C,
+      .name       = "i2c",
+      .flags      = DM_UC_FLAG_SEQ_ALIAS,
+      .post_bind  = i2c_post_bind,
+      .pre_probe  = i2c_pre_probe,
+      .post_probe = i2c_post_probe,
+      .per_device_auto   = sizeof(struct dm_i2c_bus),
+      .per_child_plat_auto   = sizeof(struct dm_i2c_chip),
+      .child_post_bind = i2c_child_post_bind,
+   };
+
+Here, `_sandbox_i2c_uc_priv_i2c_at_0` is required by the uclass but is declared
+in the device, as required by driver model. The required header file is included
+so that the code will compile without errors. A similar mechanism is used for
+child devices, but is not shown by this example.
+
+It would not be that useful to avoid binding devices but still need to allocate
+uclasses at runtime. So dtoc generates uclass instances as well::
+
+   struct list_head uclass_head = {
+      .prev = &DM_UCLASS_REF(serial)->sibling_node,
+      .next = &DM_UCLASS_REF(clk)->sibling_node,
+   };
+
+   DM_UCLASS_INST(clk) = {
+      .uc_drv      = DM_UCLASS_DRIVER_REF(clk),
+      .sibling_node   = {
+         .prev = &uclass_head,
+         .next = &DM_UCLASS_REF(i2c)->sibling_node,
+      },
+      .dev_head   = {
+         .prev = &DM_DEVICE_REF(clk_sbox)->uclass_node,
+         .next = &DM_DEVICE_REF(clk_fixed)->uclass_node,
+      },
+   };
+
+At the top is the list head. Driver model uses this on start-up, instead of
+creating its own.
+
+Below that are a set of `DM_UCLASS_INST()` macros, each declaring a
+`struct uclass`. The doubly linked lists work as for devices.
+
+All private data is placed into a `.priv_data` section so that it is contiguous
+in the resulting output binary.
+
+
+Indexes
+-------
+
+U-Boot stores drivers, devices and many other things in linker_list structures.
+These are sorted by name, so dtoc knows the order that they will appear when
+the linker runs. Each driver_info / udevice is referenced by its index in the
+linker_list array, called 'idx' in the code.
+
+When CONFIG_OF_PLATDATA_INST is enabled, idx is the udevice index, otherwise it
+is the driver_info index. In either case, indexes are used to reference devices
+using device_get_by_ofplat_idx(). This allows phandles to work as expected.
+
+
+Phases
+------
+
+U-Boot operates in several phases, typically TPL, SPL and U-Boot proper.
+The latter does not use dtoc.
+
+In some rare cases different drivers are used for two phases. For example,
+in TPL it may not be necessary to use the full PCI subsystem, so a simple
+driver can be used instead.
+
+This works in the build system simply by compiling in one driver or the
+other (e.g. PCI driver + uclass for SPL; simple_bus for TPL). But dtoc has
+no way of knowing which code is compiled in for which phase, since it does
+not inspect Makefiles or dependency graphs.
+
+So to make this work for dtoc, we need to be able to explicitly mark
+drivers with their phase. This is done by adding a macro to the driver::
+
+   /* code in tpl.c only compiled into TPL */
+   U_BOOT_DRIVER(pci_x86) = {
+      .name   = "pci_x86",
+      .id   = UCLASS_SIMPLE_BUS,
+      .of_match = of_match_ptr(tpl_fake_pci_ids),
+      DM_PHASE(tpl)
+   };
+
+
+   /* code in pci_x86.c compiled into SPL and U-Boot proper */
+   U_BOOT_DRIVER(pci_x86) = {
+      .name   = "pci_x86",
+      .id   = UCLASS_PCI,
+      .of_match = pci_x86_ids,
+      .ops   = &pci_x86_ops,
+   };
+
+
+Notice that the second driver has the same name but no DM_PHASE(), so it will be
+used for SPL and U-Boot.
+
+Note also that this only affects the code generated by dtoc. You still need to
+make sure that only the required driver is build into each phase.
+
+
+Header files
+------------
+
+With OF_PLATDATA_INST, dtoc must include the correct header file in the
+generated code for any structs that are used, so that the code will compile.
+For example, if `struct ns16550_plat` is used, the code must include the
+`ns16550.h` header file.
+
+Typically dtoc can detect the header file needed for a driver by looking
+for the structs that it uses. For example, if a driver as a `.priv_auto`
+that uses `struct ns16550_plat`, then dtoc can search header files for the
+definition of that struct and use the file.
+
+In some cases, enums are used in drivers, typically with the `.data` field
+of `struct udevice_id`. Since dtoc does not support searching for these,
+you must use the `DM_HDR()` macro to tell dtoc which header to use. This works
+as a macro included in the driver definition::
+
+   static const struct udevice_id apl_syscon_ids[] = {
+      { .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT },
+      { }
+   };
+
+   U_BOOT_DRIVER(intel_apl_punit) = {
+      .name       = "intel_apl_punit",
+      .id         = UCLASS_SYSCON,
+      .of_match   = apl_syscon_ids,
+      .probe      = apl_punit_probe,
+      DM_HEADER(<asm/cpu.h>)    /* for X86_SYSCON_PUNIT */
+   };
+
+
+
+Caveats
+-------
+
+There are various complications with this feature which mean it should only
+be used when strictly necessary, i.e. in SPL with limited memory. Notable
+caveats include:
+
+   - Device tree does not describe data types. But the C code must define a
+     type for each property. These are guessed using heuristics which
+     are wrong in several fairly common cases. For example an 8-byte value
+     is considered to be a 2-item integer array, and is byte-swapped. A
+     boolean value that is not present means 'false', but cannot be
+     included in the structures since there is generally no mention of it
+     in the devicetree file.
+
+   - Naming of nodes and properties is automatic. This means that they follow
+     the naming in the devicetree, which may result in C identifiers that
+     look a bit strange.
+
+   - It is not possible to find a value given a property name. Code must use
+     the associated C member variable directly in the code. This makes
+     the code less robust in the face of devicetree changes. To avoid having
+     a second struct with similar members and names you need to explicitly
+     declare it as an alias with `DM_DRIVER_ALIAS()`.
+
+   - The platform data is provided to drivers as a C structure. The driver
+     must use the same structure to access the data. Since a driver
+     normally also supports devicetree it must use `#ifdef` to separate
+     out this code, since the structures are only available in SPL. This could
+     be fixed fairly easily by making the structs available outside SPL, so
+     that `IS_ENABLED()` could be used.
+
+   - With CONFIG_OF_PLATDATA_INST all binding happens at build-time, meaning
+     that (by default) it is not possible to call `device_bind()` from C code.
+     This means that all devices must have an associated devicetree node and
+     compatible string. For example if a GPIO device currently creates child
+     devices in its `bind()` method, it will not work with
+     CONFIG_OF_PLATDATA_INST. Arguably this is bad practice anyway and the
+     devicetree binding should be updated to declare compatible strings for
+     the child devices. It is possible to disable OF_PLATDATA_NO_BIND but this
+     is not recommended since it increases code size.
+
+
+Internals
+---------
+
+Generated files
+```````````````
+
+When enabled, dtoc generates the following five files:
+
+include/generated/dt-decl.h (OF_PLATDATA_INST only)
+   Contains declarations for all drivers, devices and uclasses. This allows
+   any `struct udevice`, `struct driver` or `struct uclass` to be located by its
+   name
+
+include/generated/dt-structs-gen.h
+   Contains the struct definitions for the devicetree nodes that are used. This
+   is the same as without OF_PLATDATA_INST
+
+spl/dts/dt-plat.c (only with !OF_PLATDATA_INST)
+   Contains the `U_BOOT_DRVINFO()` declarations that U-Boot uses to bind devices
+   at start-up. See above for an example
+
+spl/dts/dt-device.c (only with OF_PLATDATA_INST)
+   Contains `DM_DEVICE_INST()` declarations for each device that can be used at
+   run-time. These are declared in the file along with any private/platform data
+   that they use. Every device has an idx, as above. Since each device must be
+   part of a double-linked list, the nodes are declared in the code as well.
+
+spl/dts/dt-uclass.c (only with OF_PLATDATA_INST)
+   Contains `DM_UCLASS_INST()` declarations for each uclass that can be used at
+   run-time. These are declared in the file along with any private data
+   associated with the uclass itself (the `.priv_auto` member). Since each
+   uclass must be part of a double-linked list, the nodes are declared in the
+   code as well.
+
+The dt-structs.h file includes the generated file
+`(include/generated/dt-structs.h`) if CONFIG_SPL_OF_PLATDATA is enabled.
+Otherwise (such as in U-Boot proper) these structs are not available. This
+prevents them being used inadvertently. All usage must be bracketed with
+`#if CONFIG_IS_ENABLED(OF_PLATDATA)`.
+
+The dt-plat.c file contains the device declarations and is is built in
+spl/dt-plat.c.
+
+
+CONFIG options
+``````````````
+
+Several CONFIG options are used to control the behaviour of of-platdata, all
+available for both SPL and TPL:
+
+OF_PLATDATA
+   This is the main option which enables the of-platdata feature
+
+OF_PLATDATA_PARENT
+   This allows `device_get_parent()` to work. Without this, all devices exist as
+   direct children of the root node. This option is highly desirable (if not
+   always absolutely essential) for buses such as I2C.
+
+OF_PLATDATA_INST
+   This controls the instantiation of devices at build time. With it disabled,
+   only `U_BOOT_DRVINFO()` records are created, with U-Boot handling the binding
+   in `device_bind()` on start-up. With it enabled, only `DM_DEVICE_INST()` and
+   `DM_UCLASS_INST()` records are created, and `device_bind()` is not needed at
+   runtime.
+
+OF_PLATDATA_NO_BIND
+   This controls whether `device_bind()` is supported. It is enabled by default
+   with OF_PLATDATA_INST since code-size reduction is really the main point of
+   the feature. It can be disabled if needed but is not likely to be supported
+   in the long term.
+
+OF_PLATDATA_DRIVER_RT
+   This controls whether the `struct driver_rt` records are used by U-Boot.
+   Normally when a device is bound, U-Boot stores the device pointer in one of
+   these records. There is one for every `struct driver_info` in the system,
+   i.e. one for every device that is bound from those records. It provides a
+   way to locate a device in the code and is used by
+   `device_get_by_ofplat_idx()`. This option is always enabled with of-platdata,
+   provided OF_PLATDATA_INST is not. In that case the records are useless since
+   we don't have any `struct driver_info` records.
+
+OF_PLATDATA_RT
+   This controls whether the `struct udevice_rt` records are used by U-Boot.
+   It moves the updatable fields from `struct udevice` (currently only `flags`)
+   into a separate structure, allowing the records to be kept in read-only
+   memory. It is generally enabled if OF_PLATDATA_INST is enabled. This option
+   also controls whether the private data is used in situ, or first copied into
+   an allocated region. Again this is to allow the private data declared by
+   dtoc-generated code to be in read-only memory. Note that access to private
+   data must be done via accessor functions, such as `dev_get_priv()`, so that
+   the relocation is handled.
+
+READ_ONLY
+   This indicates that the data generated by dtoc should not be modified. Only
+   a few fields actually do get changed in U-Boot, such as device flags. This
+   option causes those to move into an allocated space (see OF_PLATDATA_RT).
+   Also, since updating doubly linked lists is generally impossible when some of
+   the nodes cannot be updated, OF_PLATDATA_NO_BIND is enabled.
+
+Data structures
+```````````````
+
+A few extra data structures are used with of-platdata:
+
+`struct udevice_rt`
+   Run-time information for devices. When OF_PLATDATA_RT is enabled, this holds
+   the flags for each device, so that `struct udevice` can remain unchanged by
+   U-Boot, and potentially reside in read-only memory. Access to flags is then
+   via functions like `dev_get_flags()` and `dev_or_flags()`. This data
+   structure is allocated on start-up, where the private data is also copied.
+   All flags values start at 0 and any changes are handled by `dev_or_flags()`
+   and `dev_bic_flags()`. It would be more correct for the flags to be set to
+   `DM_FLAG_BOUND`, or perhaps `DM_FLAG_BOUND | DM_FLAG_ALLOC_PDATA`, but since
+   there is no code to bind/unbind devices and no code to allocate/free
+   private data / platform data, it doesn't matter.
+
+`struct driver_rt`
+   Run-time information for `struct driver_info` records. When
+   OF_PLATDATA_DRIVER_RT is enabled, this holds a pointer to the device
+   created by each record. This is needed so that is it possible to locate a
+   device from C code. Specifically, the code can use `DM_DRVINFO_GET(name)` to
+   get a reference to a particular `struct driver_info`, with `name` being the
+   name of the devicetree node. This is very convenient. It is also fast, since
+   no    searching or string comparison is needed. This data structure is
+   allocated    on start-up, filled out by `device_bind()` and used by
+   `device_get_by_ofplat_idx()`.
+
+Other changes
+`````````````
+
+Some other changes are made with of-platdata:
+
+Accessor functions
+   Accessing private / platform data via functions such as `dev_get_priv()` has
+   always been encouraged. With OF_PLATDATA_RT this is essential, since the
+   `priv_` and `plat_`  (etc.) values point to the data generated by dtoc, not
+   the read-write copy that is sometimes made on start-up. Changing the
+   private / platform data  pointers has always been discouraged (the API is
+   marked internal) but with OF_PLATDATA_RT this is not currently supported in
+   general, since it assumes that all such pointers point to the relocated data.
+   Note also that the renaming of struct members to have a trailing underscore
+   was partly done to make people aware that they should not be accessed
+   directly.
+
+`gd->uclass_root_s`
+   Normally U-Boot sets up the head of the uclass list here and makes
+   `gd->uclass_root` point to it. With OF_PLATDATA_INST, dtoc generates a
+   declaration of `uclass_head` in `dt-uclass.c` since it needs to link the
+   head node into the list. In that case, `gd->uclass_root_s` is not used and
+   U-Boot just makes `gd->uclass_root` point to `uclass_head`.
+
+`gd->dm_driver_rt`
+   This holds a pointer to a list of `struct driver_rt` records, one for each
+   `struct driver_info`. The list is in alphabetical order by the name used
+   in `U_BOOT_DRVINFO(name)` and indexed by idx, with the first record having
+   an index of 0. It is only used if OF_PLATDATA_INST is not enabled. This is
+   accessed via macros so that it can be used inside IS_ENABLED(), rather than
+   requiring #ifdefs in the C code when it is not present.
+
+`gd->dm_udevice_rt`
+   This holds a pointer to a list of `struct udevice_rt` records, one for each
+   `struct udevice`. The list is in alphabetical order by the name used
+   in `DM_DEVICE_INST(name)` (a C version of the devicetree node) and indexed by
+   idx, with the first record having an index of 0. It is only used if
+   OF_PLATDATA_INST is enabled. This is accessed via macros so that it can be
+   used inside `IS_ENABLED()`, rather than requiring #ifdefs in the C code when
+   it is not present.
+
+`gd->dm_priv_base`
+   When OF_PLATDATA_RT is enabled, the private/platform data for each device is
+   copied into an allocated region by U-Boot on start-up. This points to that
+   region. All calls to accessor functions (e.g. `dev_get_priv()`) then
+   translate from the pointer provided by the caller (assumed to lie between
+   `__priv_data_start` and `__priv_data_end`) to the new allocated region. This
+   member is accessed via macros so that it can be used inside IS_ENABLED(),
+   rather than required #ifdefs in the C code when it is not present.
+
+`struct udevice->flags_`
+   When OF_PLATDATA_RT is enabled, device flags are no-longer part of
+   `struct udevice`, but are instead kept in `struct udevice_rt`, as described
+   above. Flags are accessed via functions, such as `dev_get_flags()` and
+   `dev_or_flags()`.
+
+`struct udevice->node_`
+   When OF_PLATDATA is enabled, there is no devicetree at runtime, so no need
+   for this field. It is removed, just to save space.
+
+`DM_PHASE`
+   This macro is used to indicate which phase of U-Boot a driver is intended
+   for. See above for details.
+
+`DM_HDR`
+   This macro is used to indicate which header file dtoc should use to allow
+   a driver declaration to compile correctly. See above for details.
+
+`device_get_by_ofplat_idx()`
+   There used to be a function called `device_get_by_driver_info()` which
+   looked up a `struct driver_info` pointer and returned the `struct udevice`
+   that was created from it. It was only available for use with of-platdata.
+   This has been removed in favour of `device_get_by_ofplat_idx()` which uses
+   `idx`, the index of the `struct driver_info` or `struct udevice` in the
+   linker_list. Similarly, the `struct phandle_0_arg` (etc.) structs have been
+   updated to use this index instead of a pointer to `struct driver_info`.
+
+`DM_DRVINFO_GET`
+   This has been removed since we now use indexes to obtain a driver from
+   `struct phandle_0_arg` and the like.
+
+Two-pass binding
+   The original of-platdata tried to order `U_BOOT_DRVINFO()` in the generated
+   files so as to have parents declared ahead of children. This was convenient
+   as it avoided any special code in U-Boot. With OF_PLATDATA_INST this does
+   not work as the idx value relies on using alphabetical order for everything,
+   so that dtoc and U-Boot's linker_lists agree on the idx value. Devices are
+   then bound in order of idx, having no regard to parent/child relationships.
+   For this reason, device binding now hapens in multiple passes, with parents
+   being bound before their children. This is important so that children can
+   find their parents in the bind() method if needed.
+
+Root device
+   The root device is generally bound by U-Boot but with OF_PLATDATA_INST it
+   cannot be, since binding needs to be done at build time. So in this case
+   dtoc sets up a root device using `DM_DEVICE_INST()` in `dt-device.c` and
+   U-Boot makes use of that. When OF_PLATDATA_INST is not enabled, U-Boot
+   generally ignores the root node and does not create a `U_BOOT_DRVINFO()`
+   record for it. This means that the idx numbers used by `struct driver_info`
+   (when OF_PLATDATA_INST is disabled) and the idx numbers used by
+   `struct udevice` (when OF_PLATDATA_INST is enabled) differ, since one has a
+   root node and the other does not. This does not actually matter, since only
+   one of them is actually used for any particular build, but it is worth
+   keeping in mind if comparing index values and switching OF_PLATDATA_INST on
+   and off.
+
+`__priv_data_start` and `__priv_data_end`
+   The private/platform data declared by dtoc is all collected together in
+   a linker section and these symbols mark the start and end of it. This allows
+   U-Boot to relocate the area to a new location if needed (with
+   OF_PLATDATA_RT)
+
+`dm_priv_to_rw()`
+   This function converts a private- or platform-data pointer value generated by
+   dtoc into one that can be used by U-Boot. It is a NOP unless OF_PLATDATA_RT
+   is enabled, in which case it translates the address to the relocated
+   region. See above for more information.
+
+The dm_populate_phandle_data() function that was previous needed has now been
+removed, since dtoc can address the drivers directly from dt-plat.c and does
+not need to fix up things at runtime.
+
+The pylibfdt Python module is used to access the devicetree.
+
+
+Credits
+-------
+
+This is an implementation of an idea by Tom Rini <trini@konsulko.com>.
+
+
+Future work
+-----------
+- Consider programmatically reading binding files instead of devicetree
+  contents
+- Allow IS_ENABLED() to be used in the C code instead of #if
+
+
+.. Simon Glass <sjg@chromium.org>
+.. Google, Inc
+.. 6/6/16
+.. Updated Independence Day 2016
+.. Updated 1st October 2020
+.. Updated 5th February 2021
similarity index 99%
rename from doc/driver-model/pci-info.rst
rename to doc/develop/driver-model/pci-info.rst
index 8b9faa1..251601a 100644 (file)
@@ -125,6 +125,7 @@ emulator driver. For example::
                compatible = "sandbox,pci-emul-parent";
                emul_1f: emul@1f,0 {
                        compatible = "sandbox,swap-case";
+                       #emul-cells = <0>;
                };
        };
 
index ac57fdb..3edffbc 100644 (file)
@@ -10,9 +10,11 @@ Implementation
    :maxdepth: 1
 
    commands
+   driver-model/index
    global_data
    logging
    menus
+   uefi/index
    version
 
 Debugging
@@ -24,6 +26,14 @@ Debugging
    crash_dumps
    trace
 
+Packaging
+---------
+
+.. toctree::
+   :maxdepth: 1
+
+   package/index
+
 Testing
 -------
 
@@ -33,3 +43,5 @@ Testing
    coccinelle
    testing
    py_testing
+   tests_writing
+   tests_sandbox
index 60c18c5..f4e9250 100644 (file)
@@ -96,16 +96,45 @@ Also debug() and error() will generate log records  - these use LOG_CATEGORY
 as the category, so you should #define this right at the top of the source
 file to ensure the category is correct.
 
+Generally each log format_string ends with a newline. If it does not, then the
+next log statement will have the LOGRECF_CONT flag set. This can be used to
+continue the statement on the same line as the previous one without emitting
+new header information (such as category/level). This behaviour is implemented
+with log_console. Here is an example that prints a list all on one line with
+the tags at the start:
+
+.. code-block:: c
+
+   log_debug("Here is a list:");
+   for (i = 0; i < count; i++)
+      log_debug(" item %d", i);
+   log_debug("\n");
+
+Also see the special category LOGL_CONT and level LOGC_CONT.
+
 You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This
 can be used whenever your function returns an error value:
 
 .. code-block:: c
 
-   return log_ret(uclass_first_device(UCLASS_MMC, &dev));
+   return log_ret(uclass_first_device_err(UCLASS_MMC, &dev));
 
 This will write a log record when an error code is detected (a value < 0). This
 can make it easier to trace errors that are generated deep in the call stack.
 
+The log_msg_ret() variant will print a short string if CONFIG_LOG_ERROR_RETURN
+is enabled. So long as the string is unique within the function you can normally
+determine exactly which call failed:
+
+.. code-block:: c
+
+   ret = gpio_request_by_name(dev, "cd-gpios", 0, &desc, GPIOD_IS_IN);
+   if (ret)
+      return log_msg_ret("gpio", ret);
+
+Some functions return 0 for success and any other value is an error. For these,
+log_retz() and log_msg_retz() are available.
+
 Convenience functions
 ~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/doc/develop/package/binman.rst b/doc/develop/package/binman.rst
new file mode 120000 (symlink)
index 0000000..2e26e84
--- /dev/null
@@ -0,0 +1 @@
+../../../tools/binman/binman.rst
\ No newline at end of file
diff --git a/doc/develop/package/entries.rst b/doc/develop/package/entries.rst
new file mode 120000 (symlink)
index 0000000..ecedceb
--- /dev/null
@@ -0,0 +1 @@
+../../../tools/binman/entries.rst
\ No newline at end of file
diff --git a/doc/develop/package/index.rst b/doc/develop/package/index.rst
new file mode 100644 (file)
index 0000000..9374be2
--- /dev/null
@@ -0,0 +1,19 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Package U-Boot
+==============
+
+U-Boot uses Flat Image Tree (FIT) as a standard file format for packaging
+images that it it reads and boots. Documentation about FIT is available at
+doc/uImage.FIT
+
+U-Boot also provides binman for cases not covered by FIT. Examples include
+initial execution (since FIT itself does not have an executable header) and
+dealing with device boundaries, such as the read-only/read-write separation in
+SPI flash.
+
+
+.. toctree::
+   :maxdepth: 2
+
+   binman
index 7f01858..c4cecc0 100644 (file)
@@ -13,7 +13,8 @@ results. Advantages of this approach are:
   U-Boot; there can be no disconnect.
 - There is no need to write or embed test-related code into U-Boot itself.
   It is asserted that writing test-related code in Python is simpler and more
-  flexible than writing it all in C.
+  flexible than writing it all in C. But see :doc:`tests_writing` for caveats
+  and more discussion / analysis.
 - It is reasonably simple to interact with U-Boot in this way.
 
 Requirements
index 4bc9ca3..ced13ac 100644 (file)
@@ -8,17 +8,27 @@ tested and what tests you should write when adding a new feature.
 Running tests
 -------------
 
-To run most tests on sandbox, type this:
+To run most tests on sandbox, type this::
 
     make check
 
 in the U-Boot directory. Note that only the pytest suite is run using this
 command.
 
-Some tests take ages to run. To run just the quick ones, type this:
+Some tests take ages to run and are marked with @pytest.mark.slow. To run just
+the quick ones, type this::
 
     make qcheck
 
+It is also possible to run just the tests for tools (patman, binman, etc.).
+Such tests are included with those tools, i.e. no actual U-Boot unit tests are
+run. Type this::
+
+    make tcheck
+
+All of the above use the test/run script with a paremeter to select which tests
+are run.
+
 
 Sandbox
 -------
@@ -26,6 +36,7 @@ U-Boot can be built as a user-space application (e.g. for Linux). This
 allows test to be executed without needing target hardware. The 'sandbox'
 target provides this feature and it is widely used in tests.
 
+See :doc:`tests_sandbox` for more information.
 
 Pytest Suite
 ------------
@@ -35,14 +46,27 @@ either on sandbox or on real hardware. It relies on the U-Boot console to
 inject test commands and check the result. It is slower to run than C code,
 but provides the ability to unify lots of tests and summarise their results.
 
-You can run the tests on sandbox with:
+You can run the tests on sandbox with::
 
-       ./test/py/test.py --bd sandbox --build
+   ./test/py/test.py --bd sandbox --build
 
 This will produce HTML output in build-sandbox/test-log.html
 
+Some tests run with other versions of sandbox. For example sandbox_flattree
+runs the tests with livetree (the hierachical devicetree) disabled. You can
+also select particular tests with -k::
+
+   ./test/py/test.py --bd sandbox_flattree --build -k hello
+
+There are some special tests that run in SPL. For this you need the sandbox_spl
+build::
+
+   ./test/py/test.py --bd sandbox_spl --build -k test_spl
+
 See test/py/README.md for more information about the pytest suite.
 
+See :doc:`tests_sandbox` for how to run tests directly (not through pytest).
+
 
 tbot
 ----
@@ -58,10 +82,14 @@ Ad-hoc tests
 
 There are several ad-hoc tests which run outside the pytest environment:
 
-   test/fs     - File system test (shell script)
-   test/image  - FIT and legacy image tests (shell script and Python)
-   test/stdint - A test that stdint.h can be used in U-Boot (shell script)
-   trace       - Test for the tracing feature (shell script)
+test/fs
+   File system test (shell script)
+test/image
+   FIT and legacy image tests (shell script and Python)
+test/stdint
+   A test that stdint.h can be used in U-Boot (shell script)
+trace
+   Test for the tracing feature (shell script)
 
 TODO: Move these into pytest.
 
@@ -89,6 +117,8 @@ or is covered sparingly. So here are some suggestions:
   is much easier to add onto a test - writing a new large test can seem
   daunting to most contributors.
 
+See doc:`tests_writing` for how to write tests.
+
 
 Future work
 -----------
diff --git a/doc/develop/tests_sandbox.rst b/doc/develop/tests_sandbox.rst
new file mode 100644 (file)
index 0000000..84608dc
--- /dev/null
@@ -0,0 +1,209 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Sandbox tests
+=============
+
+Test Design
+-----------
+
+Most uclasses and many functions of U-Boot have sandbox tests. This allows much
+of the code to be checked in an developer-friendly environment.
+
+Sandbox provides a way to write and run unit tests. The traditional approach to
+unit tests is to build lots of little executables, one for each test or
+category of tests. With sandbox, so far as possible, all the tests share a
+small number of executables (e.g. 'u-boot' for sandbox, 'u-boot-spl' and
+'u-boot' for sandbox_spl) and can be run very quickly. The vast majority of
+tests can run on the 'sandbox' build,
+
+Available tests
+---------------
+
+Some of the available tests are:
+
+  - command_ut: Unit tests for command parsing and handling
+  - compression: Unit tests for U-Boot's compression algorithms, useful for
+      security checking. It supports gzip, bzip2, lzma and lzo.
+  - image: Unit tests for images:
+
+     - test/image/test-imagetools.sh - multi-file images
+     - test/py/tests/test-fit.py     - FIT images
+  - tracing: test/trace/test-trace.sh tests the tracing system (see
+      README.trace)
+  - verified boot: test/py/tests/test_vboot.py
+
+If you change or enhance any U-Boot subsystem, you should write or expand a
+test and include it with your patch series submission. Test coverage in some
+older areas of U-Boot is still somewhat limited and we need to work to improve
+it.
+
+Note that many of these tests are implemented as commands which you can
+run natively on your board if desired (and enabled).
+
+To run all tests, use 'make check'.
+
+
+Running sandbox tests directly
+------------------------------
+
+Typically tests are run using the pytest suite. Running pytests on sandbox is
+easy and always gets things right. For example some tests require files to be
+set up before they can work.
+
+But it is also possible to run some sandbox tests directly. For example, this
+runs the dm_test_gpio() test which you can find in test/dm/gpio.c::
+
+   $ ./u-boot -T -c "ut dm gpio"
+
+
+   U-Boot 2021.01
+
+   Model: sandbox
+   DRAM:  128 MiB
+   WDT:   Started with servicing (60s timeout)
+   MMC:   mmc2: 2 (SD), mmc1: 1 (SD), mmc0: 0 (SD)
+   In:    serial
+   Out:   vidconsole
+   Err:   vidconsole
+   Model: sandbox
+   SCSI:
+   Net:   eth0: eth@10002000, eth5: eth@10003000, eth3: sbe5, eth6: eth@10004000
+   Test: dm_test_gpio: gpio.c
+   Test: dm_test_gpio: gpio.c (flat tree)
+   Failures: 0
+
+The -T option tells the U-Boot sandbox to run with the 'test' devicetree
+(test.dts) instead of -D which selects the normal sandbox.dts - this is
+necessary because many tests rely on nodes or properties in the test devicetree.
+If you try running tests without -T then you may see failures, like::
+
+   $ ./u-boot -c "ut dm gpio"
+
+
+   U-Boot 2021.01
+
+   DRAM:  128 MiB
+   WDT:   Not found!
+   MMC:
+   In:    serial
+   Out:   serial
+   Err:   serial
+   SCSI:
+   Net:   No ethernet found.
+   Please run with test device tree:
+       ./u-boot -d arch/sandbox/dts/test.dtb
+   Test: dm_test_gpio: gpio.c
+   test/dm/gpio.c:37, dm_test_gpio(): 0 == gpio_lookup_name("b4", &dev, &offset, &gpio): Expected 0x0 (0), got 0xffffffea (-22)
+   Test: dm_test_gpio: gpio.c (flat tree)
+   test/dm/gpio.c:37, dm_test_gpio(): 0 == gpio_lookup_name("b4", &dev, &offset, &gpio): Expected 0x0 (0), got 0xffffffea (-22)
+   Failures: 2
+
+The message above should provide a hint if you forget to use the -T flag. Even
+running with -D will produce different results.
+
+You can easily use gdb on these tests, without needing --gdbserver::
+
+   $ gdb u-boot --args -T -c "ut dm gpio"
+   ...
+   (gdb) break dm_test_gpio
+   Breakpoint 1 at 0x1415bd: file test/dm/gpio.c, line 37.
+   (gdb) run -T -c "ut dm gpio"
+   Starting program: u-boot -T -c "ut dm gpio"
+   Test: dm_test_gpio: gpio.c
+
+   Breakpoint 1, dm_test_gpio (uts=0x5555558029a0 <global_dm_test_state>)
+       at files/test/dm/gpio.c:37
+   37          ut_assertok(gpio_lookup_name("b4", &dev, &offset, &gpio));
+   (gdb)
+
+You can then single-step and look at variables as needed.
+
+
+Running sandbox_spl tests directly
+----------------------------------
+
+SPL is the phase before U-Boot proper. It is present in the sandbox_spl build,
+so you can run SPL like this::
+
+   ./spl/u-boot-spl
+
+SPL tests are special in that they run (only in the SPL phase, of course) if the
+-u flag is given::
+
+   ./spl/u-boot-spl -u
+
+   U-Boot SPL 2021.01-00723-g43c77b51be5-dirty (Jan 24 2021 - 16:38:24 -0700)
+   Running 5 driver model tests
+   Test: dm_test_of_plat_base: of_platdata.c (flat tree)
+   Test: dm_test_of_plat_dev: of_platdata.c (flat tree)
+   Test: dm_test_of_plat_parent: of_platdata.c (flat tree)
+   Test: dm_test_of_plat_phandle: of_platdata.c (flat tree)
+   Test: dm_test_of_plat_props: of_platdata.c (flat tree)
+   Failures: 0
+
+
+   U-Boot 2021.01-00723-g43c77b51be5-dirty (Jan 24 2021 - 16:38:24 -0700)
+
+   DRAM:  128 MiB
+   ...
+
+It is not possible to run SPL tests in U-Boot proper, firstly because they are
+not built into U-Boot proper and secondly because the environment is very
+different, e.g. some SPL tests rely on of-platdata which is only available in
+SPL.
+
+Note that after running, SPL continues to boot into U-Boot proper. You can add
+'-c exit' to make U-Boot quit without doing anything further. It is not
+currently possible to run SPL tests and then stop, since the pytests require
+that U-Boot produces the expected banner.
+
+You can use the -k flag to select which tests run::
+
+   ./spl/u-boot-spl -u -k dm_test_of_plat_parent
+
+Of course you can use gdb with sandbox_spl, just as with sandbox.
+
+
+Running all tests directly
+--------------------------
+
+A fast way to run all sandbox tests is::
+
+   ./u-boot -T -c "ut all"
+
+It typically runs single-thread in 6 seconds on 2021 hardware, with 2s of that
+to the delays in the time test.
+
+This should not be considered a substitute for 'make check', but can be helpful
+for git bisect, etc.
+
+
+What tests are built in?
+------------------------
+
+Whatever sandbox build is used, which tests are present is determined by which
+source files are built. For sandbox_spl, the of_platdata tests are built
+because of the build rule in test/dm/Makefile::
+
+   ifeq ($(CONFIG_SPL_BUILD),y)
+   obj-$(CONFIG_SPL_OF_PLATDATA) += of_platdata.o
+   else
+   ...other tests for non-spl
+   endif
+
+You can get a list of tests in a U-Boot ELF file by looking for the
+linker_list::
+
+   $ nm /tmp/b/sandbox_spl/spl/u-boot-spl |grep 2_dm_test
+   000000000001f200 D _u_boot_list_2_dm_test_2_dm_test_of_plat_base
+   000000000001f220 D _u_boot_list_2_dm_test_2_dm_test_of_plat_dev
+   000000000001f240 D _u_boot_list_2_dm_test_2_dm_test_of_plat_parent
+   000000000001f260 D _u_boot_list_2_dm_test_2_dm_test_of_plat_phandle
+   000000000001f280 D _u_boot_list_2_dm_test_2_dm_test_of_plat_props
+
+
+Writing tests
+-------------
+
+See :doc:`tests_writing` for how to write new tests.
+
diff --git a/doc/develop/tests_writing.rst b/doc/develop/tests_writing.rst
new file mode 100644 (file)
index 0000000..1ddf7a3
--- /dev/null
@@ -0,0 +1,346 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2021 Google LLC
+.. sectionauthor:: Simon Glass <sjg@chromium.org>
+
+Writing Tests
+=============
+
+This describes how to write tests in U-Boot and describes the possible options.
+
+Test types
+----------
+
+There are two basic types of test in U-Boot:
+
+  - Python tests, in test/py/tests
+  - C tests, in test/ and its subdirectories
+
+(there are also UEFI tests in lib/efi_selftest/ not considered here.)
+
+Python tests talk to U-Boot via the command line. They support both sandbox and
+real hardware. They typically do not require building test code into U-Boot
+itself. They are fairly slow to run, due to the command-line interface and there
+being two separate processes. Python tests are fairly easy to write. They can
+be a little tricky to debug sometimes due to the voluminous output of pytest.
+
+C tests are written directly in U-Boot. While they can be used on boards, they
+are more commonly used with sandbox, as they obviously add to U-Boot code size.
+C tests are easy to write so long as the required facilities exist. Where they
+do not it can involve refactoring or adding new features to sandbox. They are
+fast to run and easy to debug.
+
+Regardless of which test type is used, all tests are collected and run by the
+pytest framework, so there is typically no need to run them separately. This
+means that C tests can be used when it makes sense, and Python tests when it
+doesn't.
+
+
+This table shows how to decide whether to write a C or Python test:
+
+=====================  ===========================  =============================
+Attribute              C test                       Python test
+=====================  ===========================  =============================
+Fast to run?           Yes                          No (two separate processes)
+Easy to write?         Yes, if required test        Yes
+                       features exist in sandbox
+                       or the target system
+Needs code in U-Boot?  Yes                          No, provided the test can be
+                                                    executed and the result
+                                                    determined using the command
+                                                    line
+Easy to debug?         Yes                          No, since access to the U-Boot
+                                                    state is not available and the
+                                                    amount of output can
+                                                    sometimes require a bit of
+                                                    digging
+Can use gdb?           Yes, directly                Yes, with --gdbserver
+Can run on boards?     Some can, but only if        Some
+                       compiled in and not
+                       dependent on sandboxau
+=====================  ===========================  =============================
+
+
+Python or C
+-----------
+
+Typically in U-Boot we encourage C test using sandbox for all features. This
+allows fast testing, easy development and allows contributors to make changes
+without needing dozens of boards to test with.
+
+When a test requires setup or interaction with the running host (such as to
+generate images and then running U-Boot to check that they can be loaded), or
+cannot be run on sandbox, Python tests should be used. These should typically
+NOT rely on running with sandbox, but instead should function correctly on any
+board supported by U-Boot.
+
+
+How slow are Python tests?
+--------------------------
+
+Under the hood, when running on sandbox, Python tests work by starting a sandbox
+test and connecting to it via a pipe. Each interaction with the U-Boot process
+requires at least a context switch to handle the pipe interaction. The test
+sends a command to U-Boot, which then reacts and shows some output, then the
+test sees that and continues. Of course on real hardware, communications delays
+(e.g. with a serial console) make this slower.
+
+For comparison, consider a test that checks the 'md' (memory dump). All times
+below are approximate, as measured on an AMD 2950X system. Here is is the test
+in Python::
+
+   @pytest.mark.buildconfigspec('cmd_memory')
+   def test_md(u_boot_console):
+       """Test that md reads memory as expected, and that memory can be modified
+       using the mw command."""
+
+       ram_base = u_boot_utils.find_ram_base(u_boot_console)
+       addr = '%08x' % ram_base
+       val = 'a5f09876'
+       expected_response = addr + ': ' + val
+       u_boot_console.run_command('mw ' + addr + ' 0 10')
+       response = u_boot_console.run_command('md ' + addr + ' 10')
+       assert(not (expected_response in response))
+       u_boot_console.run_command('mw ' + addr + ' ' + val)
+       response = u_boot_console.run_command('md ' + addr + ' 10')
+       assert(expected_response in response)
+
+This runs a few commands and checks the output. Note that it runs a command,
+waits for the response and then checks it agains what is expected. If run by
+itself it takes around 800ms, including test collection. For 1000 runs it takes
+19 seconds, or 19ms per run. Of course 1000 runs it not that useful since we
+only want to run it once.
+
+There is no exactly equivalent C test, but here is a similar one that tests 'ms'
+(memory search)::
+
+   /* Test 'ms' command with bytes */
+   static int mem_test_ms_b(struct unit_test_state *uts)
+   {
+      u8 *buf;
+
+      buf = map_sysmem(0, BUF_SIZE + 1);
+      memset(buf, '\0', BUF_SIZE);
+      buf[0x0] = 0x12;
+      buf[0x31] = 0x12;
+      buf[0xff] = 0x12;
+      buf[0x100] = 0x12;
+      ut_assertok(console_record_reset_enable());
+      run_command("ms.b 1 ff 12", 0);
+      ut_assert_nextline("00000030: 00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................");
+      ut_assert_nextline("--");
+      ut_assert_nextline("000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12    ................");
+      ut_assert_nextline("2 matches");
+      ut_assert_console_end();
+
+      ut_asserteq(2, env_get_hex("memmatches", 0));
+      ut_asserteq(0xff, env_get_hex("memaddr", 0));
+      ut_asserteq(0xfe, env_get_hex("mempos", 0));
+
+      unmap_sysmem(buf);
+
+      return 0;
+   }
+   MEM_TEST(mem_test_ms_b, UT_TESTF_CONSOLE_REC);
+
+This runs the command directly in U-Boot, then checks the console output, also
+directly in U-Boot. If run by itself this takes 100ms. For 1000 runs it takes
+660ms, or 0.66ms per run.
+
+So overall running a C test is perhaps 8 times faster individually and the
+interactions are perhaps 25 times faster.
+
+It should also be noted that the C test is fairly easy to debug. You can set a
+breakpoint on do_mem_search(), which is what implements the 'ms' command,
+single step to see what might be wrong, etc. That is also possible with the
+pytest, but requires two terminals and --gdbserver.
+
+
+Why does speed matter?
+----------------------
+
+Many development activities rely on running tests:
+
+  - 'git bisect run make qcheck' can be used to find a failing commit
+  - test-driven development relies on quick iteration of build/test
+  - U-Boot's continuous integration (CI) systems make use of tests. Running
+      all sandbox tests typically takes 90 seconds and running each qemu test
+      takes about 30 seconds. This is currently dwarfed by the time taken to
+      build all boards
+
+As U-Boot continues to grow its feature set, fast and reliable tests are a
+critical factor factor in developer productivity and happiness.
+
+
+Writing C tests
+---------------
+
+C tests are arranged into suites which are typically executed by the 'ut'
+command. Each suite is in its own file. This section describes how to accomplish
+some common test tasks.
+
+(there are also UEFI C tests in lib/efi_selftest/ not considered here.)
+
+Add a new driver model test
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use this when adding a test for a new or existing uclass, adding new operations
+or features to a uclass, adding new ofnode or dev_read_() functions, or anything
+else related to driver model.
+
+Find a suitable place for your test, perhaps near other test functions in
+existing code, or in a new file. Each uclass should have its own test file.
+
+Declare the test with::
+
+   /* Test that ... */
+   static int dm_test_uclassname_what(struct unit_test_state *uts)
+   {
+      /* test code here */
+
+      return 0;
+   }
+   DM_TEST(dm_test_uclassname_what, UT_TESTF_SCAN_FDT);
+
+Replace 'uclassname' with the name of your uclass, if applicable. Replace 'what'
+with what you are testing.
+
+The flags for DM_TEST() are defined in test/test.h and you typically want
+UT_TESTF_SCAN_FDT so that the devicetree is scanned and all devices are bound
+and ready for use. The DM_TEST macro adds UT_TESTF_DM automatically so that
+the test runner knows it is a driver model test.
+
+Driver model tests are special in that the entire driver model state is
+recreated anew for each test. This ensures that if a previous test deletes a
+device, for example, it does not affect subsequent tests. Driver model tests
+also run both with livetree and flattree, to ensure that both devicetree
+implementations work as expected.
+
+Example commit: c48cb7ebfb4 ("sandbox: add ADC unit tests") [1]
+
+[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/c48cb7ebfb4
+
+
+Add a C test to an existing suite
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use this when you are adding to or modifying an existing feature outside driver
+model. An example is bloblist.
+
+Add a new function in the same file as the rest of the suite and register it
+with the suite. For example, to add a new mem_search test::
+
+   /* Test 'ms' command with 32-bit values */
+   static int mem_test_ms_new_thing(struct unit_test_state *uts)
+   {
+         /* test code here*/
+
+         return 0;
+   }
+   MEM_TEST(mem_test_ms_new_thing, UT_TESTF_CONSOLE_REC);
+
+Note that the MEM_TEST() macros is defined at the top of the file.
+
+Example commit: 9fe064646d2 ("bloblist: Support relocating to a larger space") [1]
+
+[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/9fe064646d2
+
+
+Add a new test suite
+~~~~~~~~~~~~~~~~~~~~
+
+Each suite should focus on one feature or subsystem, so if you are writing a
+new one of those, you should add a new suite.
+
+Create a new file in test/ or a subdirectory and define a macro to register the
+suite. For example::
+
+   #include <common.h>
+   #include <console.h>
+   #include <mapmem.h>
+   #include <dm/test.h>
+   #include <test/ut.h>
+
+   /* Declare a new wibble test */
+   #define WIBBLE_TEST(_name, _flags)   UNIT_TEST(_name, _flags, wibble_test)
+
+   /* Tetss go here */
+
+   /* At the bottom of the file: */
+
+   int do_ut_wibble(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+   {
+     struct unit_test *tests = UNIT_TEST_SUITE_START(wibble_test);
+     const int n_ents = UNIT_TEST_SUITE_COUNT(wibble_test);
+
+     return cmd_ut_category("cmd_wibble", "wibble_test_", tests, n_ents, argc, argv);
+   }
+
+Then add new tests to it as above.
+
+Register this new suite in test/cmd_ut.c by adding to cmd_ut_sub[]::
+
+  /* Within cmd_ut_sub[]... */
+
+  U_BOOT_CMD_MKENT(wibble, CONFIG_SYS_MAXARGS, 1, do_ut_wibble, "", ""),
+
+and adding new help to ut_help_text[]::
+
+  "ut wibble - Test the wibble feature\n"
+
+If your feature is conditional on a particular Kconfig, then you can use #ifdef
+to control that.
+
+Finally, add the test to the build by adding to the Makefile in the same
+directory::
+
+  obj-$(CONFIG_$(SPL_)CMDLINE) += wibble.o
+
+Note that CMDLINE is never enabled in SPL, so this test will only be present in
+U-Boot proper. See below for how to do SPL tests.
+
+As before, you can add an extra Kconfig check if needed::
+
+  ifneq ($(CONFIG_$(SPL_)WIBBLE),)
+  obj-$(CONFIG_$(SPL_)CMDLINE) += wibble.o
+  endif
+
+
+Example commit: 919e7a8fb64 ("test: Add a simple test for bloblist") [1]
+
+[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/919e7a8fb64
+
+
+Making the test run from pytest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All C tests must run from pytest. Typically this is automatic, since pytest
+scans the U-Boot executable for available tests to run. So long as you have a
+'ut' subcommand for your test suite, it will run. The same applies for driver
+model tests since they use the 'ut dm' subcommand.
+
+See test/py/tests/test_ut.py for how unit tests are run.
+
+
+Add a C test for SPL
+~~~~~~~~~~~~~~~~~~~~
+
+Note: C tests are only available for sandbox_spl at present. There is currently
+no mechanism in other boards to existing SPL tests even if they are built into
+the image.
+
+SPL tests cannot be run from the 'ut' command since there are no commands
+available in SPL. Instead, sandbox (only) calls ut_run_list() on start-up, when
+the -u flag is given. This runs the available unit tests, no matter what suite
+they are in.
+
+To create a new SPL test, follow the same rules as above, either adding to an
+existing suite or creating a new one.
+
+An example SPL test is spl_test_load().
+
+
+Writing Python tests
+--------------------
+
+See :doc:`py_testing` for brief notes how to write Python tests. You
+should be able to use the existing tests in test/py/tests as examples.
similarity index 51%
rename from doc/uefi/index.rst
rename to doc/develop/uefi/index.rst
index b790a91..7e65dbc 100644 (file)
@@ -3,6 +3,10 @@
 Unified Extensible Firmware (UEFI)
 ==================================
 
+U-Boot provides an implementation of the UEFI API allowing to run UEFI
+compliant software like Linux, GRUB, and iPXE. Furthermore U-Boot itself
+can be run an UEFI payload.
+
 .. toctree::
    :maxdepth: 2
 
similarity index 99%
rename from doc/uefi/uefi.rst
rename to doc/develop/uefi/uefi.rst
index 5a67737..b3494c2 100644 (file)
@@ -178,7 +178,7 @@ Now in U-Boot install the keys on your board::
 
 Set up boot parameters on your board::
 
-    efidebug boot add 1 HELLO mmc 0:1 /helloworld.efi.signed ""
+    efidebug boot add -b 1 HELLO mmc 0:1 /helloworld.efi.signed ""
 
 Now your board can run the signed image via the boot manager (see below).
 You can also try this sequence by running Pytest, test_efi_secboot,
index 9252dc1..6e936a0 100644 (file)
@@ -25,9 +25,10 @@ ioset settings. Use the macros from boot/dts/<soc>-pinfunc.h file to get the
 right representation of the pin.
 
 Optional properties:
-- GENERIC_PINCONFIG: generic pinconfig options to use, bias-disable,
-bias-pull-down, bias-pull-up, drive-open-drain, input-schmitt-enable,
-input-debounce.
+- GENERIC_PINCONFIG: generic pinconfig options to use:
+       - bias-disable, bias-pull-down, bias-pull-up, drive-open-drain,
+         input-schmitt-enable, input-debounce
+       - slew-rate: 0 - disabled, 1 - enabled (default)
 - atmel,drive-strength: 0 or 1 for low drive, 2 for medium drive and 3 for
 high drive. The default value is low drive.
 
diff --git a/doc/device-tree-bindings/sysinfo/google,coral.txt b/doc/device-tree-bindings/sysinfo/google,coral.txt
new file mode 100644 (file)
index 0000000..d8a1a79
--- /dev/null
@@ -0,0 +1,37 @@
+Google Coral sysinfo information
+================================
+
+This binding allows information about the board to be described. It includes
+the SMBIOS binding as well.
+
+Required properties:
+
+  - compatible: "google,coral"
+  - recovery-gpios: GPIO to use for recovery button (-1 if none)
+  - wite-protect-gpios: GPIO to use for write-protect screw
+  - phase-enforce-gpios: GPIO to indicate the board is in final ship mode
+  - memconfig-gpios: 4 GPIOs to use to read memory config (as base2 int)
+
+Optional properties:
+  - skuconfig-gpios: 2 GPIOs to use to read SKU ID. If not present, the
+       Chromium OS EC SKU_ID is used instead
+
+Example:
+
+board: board {
+       compatible = "google,coral";
+       recovery-gpios = <&gpio_nw (-1) GPIO_ACTIVE_LOW>;
+       write-protect-gpios = <&gpio_nw GPIO_75 GPIO_ACTIVE_HIGH>;
+       phase-enforce-gpios = <&gpio_n GPIO_10 GPIO_ACTIVE_HIGH>;
+       memconfig-gpios = <&gpio_nw GPIO_101 GPIO_ACTIVE_HIGH
+               &gpio_nw GPIO_102 GPIO_ACTIVE_HIGH
+               &gpio_n GPIO_38 GPIO_ACTIVE_HIGH
+               &gpio_n GPIO_45 GPIO_ACTIVE_HIGH>;
+
+       /*
+        * This is used for reef only:
+        *
+        * skuconfig-gpios = <&gpio_nw GPIO_16 GPIO_ACTIVE_HIGH
+        *      &gpio_nw GPIO_17 GPIO_ACTIVE_HIGH>;
+        */
+ };
diff --git a/doc/driver-model/of-plat.rst b/doc/driver-model/of-plat.rst
deleted file mode 100644 (file)
index 4ef2fe6..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-Compiled-in Device Tree / Platform Data
-=======================================
-
-
-Introduction
-------------
-
-Device tree is the standard configuration method in U-Boot. It is used to
-define what devices are in the system and provide configuration information
-to these devices.
-
-The overhead of adding device tree access to U-Boot is fairly modest,
-approximately 3KB on Thumb 2 (plus the size of the DT itself). This means
-that in most cases it is best to use device tree for configuration.
-
-However there are some very constrained environments where U-Boot needs to
-work. These include SPL with severe memory limitations. For example, some
-SoCs require a 16KB SPL image which must include a full MMC stack. In this
-case the overhead of device tree access may be too great.
-
-It is possible to create platform data manually by defining C structures
-for it, and reference that data in a U_BOOT_DRVINFO() declaration. This
-bypasses the use of device tree completely, effectively creating a parallel
-configuration mechanism. But it is an available option for SPL.
-
-As an alternative, a new 'of-platdata' feature is provided. This converts the
-device tree contents into C code which can be compiled into the SPL binary.
-This saves the 3KB of code overhead and perhaps a few hundred more bytes due
-to more efficient storage of the data.
-
-Note: Quite a bit of thought has gone into the design of this feature.
-However it still has many rough edges and comments and suggestions are
-strongly encouraged! Quite possibly there is a much better approach.
-
-
-Caveats
--------
-
-There are many problems with this features. It should only be used when
-strictly necessary. Notable problems include:
-
-   - Device tree does not describe data types. But the C code must define a
-     type for each property. These are guessed using heuristics which
-     are wrong in several fairly common cases. For example an 8-byte value
-     is considered to be a 2-item integer array, and is byte-swapped. A
-     boolean value that is not present means 'false', but cannot be
-     included in the structures since there is generally no mention of it
-     in the device tree file.
-
-   - Naming of nodes and properties is automatic. This means that they follow
-     the naming in the device tree, which may result in C identifiers that
-     look a bit strange.
-
-   - It is not possible to find a value given a property name. Code must use
-     the associated C member variable directly in the code. This makes
-     the code less robust in the face of device-tree changes. It also
-     makes it very unlikely that your driver code will be useful for more
-     than one SoC. Even if the code is common, each SoC will end up with
-     a different C struct name, and a likely a different format for the
-     platform data.
-
-   - The platform data is provided to drivers as a C structure. The driver
-     must use the same structure to access the data. Since a driver
-     normally also supports device tree it must use #ifdef to separate
-     out this code, since the structures are only available in SPL.
-
-
-How it works
-------------
-
-The feature is enabled by CONFIG OF_PLATDATA. This is only available in
-SPL/TPL and should be tested with:
-
-.. code-block:: c
-
-    #if CONFIG_IS_ENABLED(OF_PLATDATA)
-
-A new tool called 'dtoc' converts a device tree file either into a set of
-struct declarations, one for each compatible node, and a set of
-U_BOOT_DRVINFO() declarations along with the actual platform data for each
-device. As an example, consider this MMC node:
-
-.. code-block:: none
-
-    sdmmc: dwmmc@ff0c0000 {
-            compatible = "rockchip,rk3288-dw-mshc";
-            clock-freq-min-max = <400000 150000000>;
-            clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
-                     <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
-            clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
-            fifo-depth = <0x100>;
-            interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
-            reg = <0xff0c0000 0x4000>;
-            bus-width = <4>;
-            cap-mmc-highspeed;
-            cap-sd-highspeed;
-            card-detect-delay = <200>;
-            disable-wp;
-            num-slots = <1>;
-            pinctrl-names = "default";
-            pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
-                vmmc-supply = <&vcc_sd>;
-                status = "okay";
-                u-boot,dm-pre-reloc;
-        };
-
-
-Some of these properties are dropped by U-Boot under control of the
-CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce
-the following C struct declaration:
-
-.. code-block:: c
-
-    struct dtd_rockchip_rk3288_dw_mshc {
-            fdt32_t         bus_width;
-            bool            cap_mmc_highspeed;
-            bool            cap_sd_highspeed;
-            fdt32_t         card_detect_delay;
-            fdt32_t         clock_freq_min_max[2];
-            struct phandle_1_arg clocks[4];
-            bool            disable_wp;
-            fdt32_t         fifo_depth;
-            fdt32_t         interrupts[3];
-            fdt32_t         num_slots;
-            fdt32_t         reg[2];
-            fdt32_t         vmmc_supply;
-    };
-
-and the following device declarations:
-
-.. code-block:: c
-
-    /* Node /clock-controller@ff760000 index 0 */
-    ...
-
-    /* Node /dwmmc@ff0c0000 index 2 */
-    static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = {
-            .fifo_depth             = 0x100,
-            .cap_sd_highspeed       = true,
-            .interrupts             = {0x0, 0x20, 0x4},
-            .clock_freq_min_max     = {0x61a80, 0x8f0d180},
-            .vmmc_supply            = 0xb,
-            .num_slots              = 0x1,
-            .clocks                 = {{0, 456},
-                                       {0, 68},
-                                       {0, 114},
-                                       {0, 118}},
-            .cap_mmc_highspeed      = true,
-            .disable_wp             = true,
-            .bus_width              = 0x4,
-            .u_boot_dm_pre_reloc    = true,
-            .reg                    = {0xff0c0000, 0x4000},
-            .card_detect_delay      = 0xc8,
-    };
-
-    U_BOOT_DRVINFO(dwmmc_at_ff0c0000) = {
-            .name           = "rockchip_rk3288_dw_mshc",
-            .plat       = &dtv_dwmmc_at_ff0c0000,
-            .plat_size  = sizeof(dtv_dwmmc_at_ff0c0000),
-            .parent_idx     = -1,
-    };
-
-The device is then instantiated at run-time and the platform data can be
-accessed using:
-
-.. code-block:: c
-
-    struct udevice *dev;
-    struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_plat(dev);
-
-This avoids the code overhead of converting the device tree data to
-platform data in the driver. The of_to_plat() method should
-therefore do nothing in such a driver.
-
-Note that for the platform data to be matched with a driver, the 'name'
-property of the U_BOOT_DRVINFO() declaration has to match a driver declared
-via U_BOOT_DRIVER(). This effectively means that a U_BOOT_DRIVER() with a
-'name' corresponding to the devicetree 'compatible' string (after converting
-it to a valid name for C) is needed, so a dedicated driver is required for
-each 'compatible' string.
-
-In order to make this a bit more flexible DM_DRIVER_ALIAS macro can be
-used to declare an alias for a driver name, typically a 'compatible' string.
-This macro produces no code, but it is by dtoc tool.
-
-The parent_idx is the index of the parent driver_info structure within its
-linker list (instantiated by the U_BOOT_DRVINFO() macro). This is used to support
-dev_get_parent().
-
-During the build process dtoc parses both U_BOOT_DRIVER and DM_DRIVER_ALIAS
-to build a list of valid driver names and driver aliases. If the 'compatible'
-string used for a device does not not match a valid driver name, it will be
-checked against the list of driver aliases in order to get the right driver
-name to use. If in this step there is no match found a warning is issued to
-avoid run-time failures.
-
-Where a node has multiple compatible strings, a #define is used to make them
-equivalent, e.g.:
-
-.. code-block:: c
-
-    #define dtd_rockchip_rk3299_dw_mshc dtd_rockchip_rk3288_dw_mshc
-
-
-Converting of-platdata to a useful form
----------------------------------------
-
-Of course it would be possible to use the of-platdata directly in your driver
-whenever configuration information is required. However this means that the
-driver will not be able to support device tree, since the of-platdata
-structure is not available when device tree is used. It would make no sense
-to use this structure if device tree were available, since the structure has
-all the limitations metioned in caveats above.
-
-Therefore it is recommended that the of-platdata structure should be used
-only in the probe() method of your driver. It cannot be used in the
-of_to_plat() method since this is not called when platform data is
-already present.
-
-
-How to structure your driver
-----------------------------
-
-Drivers should always support device tree as an option. The of-platdata
-feature is intended as a add-on to existing drivers.
-
-Your driver should convert the plat struct in its probe() method. The
-existing device tree decoding logic should be kept in the
-of_to_plat() method and wrapped with #if.
-
-For example:
-
-.. code-block:: c
-
-    #include <dt-structs.h>
-
-    struct mmc_plat {
-    #if CONFIG_IS_ENABLED(OF_PLATDATA)
-            /* Put this first since driver model will copy the data here */
-            struct dtd_mmc dtplat;
-    #endif
-            /*
-             * Other fields can go here, to be filled in by decoding from
-             * the device tree (or the C structures when of-platdata is used).
-             */
-            int fifo_depth;
-    };
-
-    static int mmc_of_to_plat(struct udevice *dev)
-    {
-    #if !CONFIG_IS_ENABLED(OF_PLATDATA)
-            /* Decode the device tree data */
-            struct mmc_plat *plat = dev_get_plat(dev);
-            const void *blob = gd->fdt_blob;
-            int node = dev_of_offset(dev);
-
-            plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0);
-    #endif
-
-            return 0;
-    }
-
-    static int mmc_probe(struct udevice *dev)
-    {
-            struct mmc_plat *plat = dev_get_plat(dev);
-
-    #if CONFIG_IS_ENABLED(OF_PLATDATA)
-            /* Decode the of-platdata from the C structures */
-            struct dtd_mmc *dtplat = &plat->dtplat;
-
-            plat->fifo_depth = dtplat->fifo_depth;
-    #endif
-            /* Set up the device from the plat data */
-            writel(plat->fifo_depth, ...)
-    }
-
-    static const struct udevice_id mmc_ids[] = {
-            { .compatible = "vendor,mmc" },
-            { }
-    };
-
-    U_BOOT_DRIVER(mmc_drv) = {
-            .name           = "mmc_drv",
-            .id             = UCLASS_MMC,
-            .of_match       = mmc_ids,
-            .of_to_plat = mmc_of_to_plat,
-            .probe          = mmc_probe,
-            .priv_auto = sizeof(struct mmc_priv),
-            .plat_auto = sizeof(struct mmc_plat),
-    };
-
-    DM_DRIVER_ALIAS(mmc_drv, vendor_mmc) /* matches compatible string */
-
-Note that struct mmc_plat is defined in the C file, not in a header. This
-is to avoid needing to include dt-structs.h in a header file. The idea is to
-keep the use of each of-platdata struct to the smallest possible code area.
-There is just one driver C file for each struct, that can convert from the
-of-platdata struct to the standard one used by the driver.
-
-In the case where SPL_OF_PLATDATA is enabled, plat_auto is
-still used to allocate space for the platform data. This is different from
-the normal behaviour and is triggered by the use of of-platdata (strictly
-speaking it is a non-zero plat_size which triggers this).
-
-The of-platdata struct contents is copied from the C structure data to the
-start of the newly allocated area. In the case where device tree is used,
-the platform data is allocated, and starts zeroed. In this case the
-of_to_plat() method should still set up the platform data (and the
-of-platdata struct will not be present).
-
-SPL must use either of-platdata or device tree. Drivers cannot use both at
-the same time, but they must support device tree. Supporting of-platdata is
-optional.
-
-The device tree becomes in accessible when CONFIG_SPL_OF_PLATDATA is enabled,
-since the device-tree access code is not compiled in. A corollary is that
-a board can only move to using of-platdata if all the drivers it uses support
-it. There would be little point in having some drivers require the device
-tree data, since then libfdt would still be needed for those drivers and
-there would be no code-size benefit.
-
-Internals
----------
-
-The dt-structs.h file includes the generated file
-(include/generated//dt-structs.h) if CONFIG_SPL_OF_PLATDATA is enabled.
-Otherwise (such as in U-Boot proper) these structs are not available. This
-prevents them being used inadvertently. All usage must be bracketed with
-#if CONFIG_IS_ENABLED(OF_PLATDATA).
-
-The dt-plat.c file contains the device declarations and is is built in
-spl/dt-plat.c.
-
-The dm_populate_phandle_data() function that was previous needed has now been
-removed, since dtoc can address the drivers directly from dt-plat.c and does
-not need to fix up things at runtime.
-
-The pylibfdt Python module is used to access the devicetree.
-
-
-Credits
--------
-
-This is an implementation of an idea by Tom Rini <trini@konsulko.com>.
-
-
-Future work
------------
-- Consider programmatically reading binding files instead of device tree
-  contents
-
-
-.. Simon Glass <sjg@chromium.org>
-.. Google, Inc
-.. 6/6/16
-.. Updated Independence Day 2016
-.. Updated 1st October 2020
index 4c44955..02de1d4 100644 (file)
@@ -38,29 +38,6 @@ want to contribute to U-Boot.
 
    develop/index
 
-Unified Extensible Firmware (UEFI)
-----------------------------------
-
-U-Boot provides an implementation of the UEFI API allowing to run UEFI
-compliant software like Linux, GRUB, and iPXE. Furthermore U-Boot itself
-can be run an UEFI payload.
-
-.. toctree::
-   :maxdepth: 2
-
-   uefi/index
-
-Driver-Model documentation
---------------------------
-
-The following holds information on the U-Boot device driver framework:
-driver-model, including the design details of itself and several driver
-subsystems.
-
-.. toctree::
-   :maxdepth: 2
-
-   driver-model/index
 
 U-Boot API documentation
 ------------------------
@@ -110,6 +87,14 @@ Android-specific features available in U-Boot.
 
    android/index
 
+Chromium OS-specific doc
+------------------------
+
+.. toctree::
+   :maxdepth: 2
+
+   chromium/index
+
 Indices and tables
 ==================
 
diff --git a/doc/usage/fit.rst b/doc/usage/fit.rst
new file mode 100644 (file)
index 0000000..7037434
--- /dev/null
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Flat Image Tree (FIT)
+=====================
+
+U-Boot uses Flat Image Tree (FIT) as a standard file format for packaging
+images that it it reads and boots. Documentation about FIT is available at
+doc/uImage.FIT
index 6c59bba..5faf279 100644 (file)
@@ -6,6 +6,7 @@ Use U-Boot
 
    dfu
    fdt_overlays
+   fit
    netconsole
    partitions
 
@@ -21,6 +22,7 @@ Shell commands
    booti
    bootmenu
    button
+   x86/cbsysinfo
    conitrace
    echo
    exception
@@ -30,7 +32,9 @@ Shell commands
    load
    loady
    mbr
+   md
    pstore
    qfw
    sbi
    true
+   scp03
diff --git a/doc/usage/md.rst b/doc/usage/md.rst
new file mode 100644 (file)
index 0000000..4c1073e
--- /dev/null
@@ -0,0 +1,106 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+md command
+==========
+
+Synopis
+-------
+
+::
+
+    md <address>[<data_size>] [<length>]
+
+Description
+-----------
+
+The md command is used to dump the contents of memory. It uses a standard
+format that includes the address, hex data and ASCII display. It supports
+various data sizes and uses the endianness of the target.
+
+The specified data_size and length become the defaults for future memory
+commands commands.
+
+address
+    start address to display
+
+data_size
+    size of each value to display (defaults to .l):
+
+    =========  ===================
+    data_size  Output size
+    =========  ===================
+    .b         byte
+    .w         word (16 bits)
+    .l         long (32 bits)
+    .q         quadword (64 bits)
+    =========  ===================
+
+length
+    number of values to dump. Defaults to 40 (0d64). Note that this is not
+    the same as the number of bytes, unless .b is used.
+
+Note that the format of 'md.b' can be emulated from linux with::
+
+    # This works but requires using sed to get the extra spaces
+    # <addr> is the address, <f> is the filename
+    xxd -o <addr> -g1 <f> |sed 's/  /    /' >bad
+
+    # This uses a single tool but the offset always starts at 0
+    # <f> is the filename
+    hexdump -v -e '"%08.8_ax: " 16/1 "%02x " "    "' -e '16/1 "%_p" "\n" ' <f>
+
+
+Example
+-------
+
+::
+
+    => md 10000
+    00010000: 00010000 00000000 f0f30f00 00005596    .............U..
+    00010010: 10011010 00000000 10011010 00000000    ................
+    00010020: 10011050 00000000 b96d4cd8 00007fff    P........Lm.....
+    00010030: 00000000 00000000 f0f30f18 00005596    .............U..
+    00010040: 10011040 00000000 10011040 00000000    @.......@.......
+    00010050: b96d4cd8 00007fff 10011020 00000000    .Lm..... .......
+    00010060: 00000003 000000c3 00000000 00000000    ................
+    00010070: 00000000 00000000 f0e892f3 00005596    .............U..
+    00010080: 00000000 000000a1 00000000 00000000    ................
+    00010090: 00000000 00000000 f0e38aa6 00005596    .............U..
+    000100a0: 00000000 000000a6 00000022 00000000    ........".......
+    000100b0: 00000001 00000000 f0e38aa1 00005596    .............U..
+    000100c0: 00000000 000000be 00000000 00000000    ................
+    000100d0: 00000000 00000000 00000000 00000000    ................
+    000100e0: 00000000 00000000 00000000 00000000    ................
+    000100f0: 00000000 00000000 00000000 00000000    ................
+    => md.b 10000
+    00010000: 00 00 01 00 00 00 00 00 00 0f f3 f0 96 55 00 00    .............U..
+    00010010: 10 10 01 10 00 00 00 00 10 10 01 10 00 00 00 00    ................
+    00010020: 50 10 01 10 00 00 00 00 d8 4c 6d b9 ff 7f 00 00    P........Lm.....
+    00010030: 00 00 00 00 00 00 00 00 18 0f f3 f0 96 55 00 00    .............U..
+    => md.b 10000 10
+    00010000: 00 00 01 00 00 00 00 00 00 0f f3 f0 96 55 00 00    .............U..
+    =>
+    00010010: 10 10 01 10 00 00 00 00 10 10 01 10 00 00 00 00    ................
+    =>
+    00010020: 50 10 01 10 00 00 00 00 d8 4c 6d b9 ff 7f 00 00    P........Lm.....
+    =>
+    => md.q 10000
+    00010000: 0000000000010000 00005596f0f30f00    .............U..
+    00010010: 0000000010011010 0000000010011010    ................
+    00010020: 0000000010011050 00007fffb96d4cd8    P........Lm.....
+    00010030: 0000000000000000 00005596f0f30f18    .............U..
+    00010040: 0000000010011040 0000000010011040    @.......@.......
+    00010050: 00007fffb96d4cd8 0000000010011020    .Lm..... .......
+    00010060: 000000c300000003 0000000000000000    ................
+    00010070: 0000000000000000 00005596f0e892f3    .............U..
+
+The empty commands cause a 'repeat', so that md shows the next available data
+in the same format as before.
+
+
+Return value
+------------
+
+The return value $? is always 0 (true).
+
+
diff --git a/doc/usage/scp03.rst b/doc/usage/scp03.rst
new file mode 100644 (file)
index 0000000..7ff87ed
--- /dev/null
@@ -0,0 +1,33 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+scp03 command
+=============
+
+Synopsis
+--------
+
+::
+
+    scp03 enable
+    scp03 provision
+
+Description
+-----------
+
+The *scp03* command calls into a Trusted Application executing in a
+Trusted Execution Environment to enable (if present) the Secure
+Channel Protocol 03 stablished between the processor and the secure
+element.
+
+This protocol encrypts all the communication between the processor and
+the secure element using a set of pre-defined keys. These keys can be
+rotated (provisioned) using the *provision* request.
+
+See also
+--------
+
+For some information on the internals implemented in the TEE, please
+check the GlobalPlatform documentation on `Secure Channel Protocol '03'`_
+
+.. _Secure Channel Protocol '03':
+   https://globalplatform.org/wp-content/uploads/2014/07/GPC_2.3_D_SCP03_v1.1.2_PublicRelease.pdf
diff --git a/doc/usage/x86/cbsysinfo.rst b/doc/usage/x86/cbsysinfo.rst
new file mode 100644 (file)
index 0000000..8c03a85
--- /dev/null
@@ -0,0 +1,25 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+cbsysinfo
+=========
+
+Synopis
+-------
+
+::
+
+    cbsysinfo
+
+
+Description
+-----------
+
+This displays information obtained from the coreboot sysinfo table. It is only
+useful when booting U-Boot from coreboot.
+
+Example
+-------
+
+::
+
+    => cbsysinfo
index c562a71..3510dab 100644 (file)
@@ -38,7 +38,7 @@ ifdef CONFIG_SPL_BUILD
 
 obj-$(CONFIG_SPL_BOOTCOUNT_LIMIT) += bootcount/
 obj-$(CONFIG_SPL_CACHE_SUPPORT) += cache/
-obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/
+obj-$(CONFIG_SPL_CPU) += cpu/
 obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/
 obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
 obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/
index e2f229b..1c2c3b4 100644 (file)
@@ -89,7 +89,7 @@ static unsigned long host_block_write(struct blk_desc *block_dev,
 }
 
 #ifdef CONFIG_BLK
-int host_dev_bind(int devnum, char *filename)
+int host_dev_bind(int devnum, char *filename, bool removable)
 {
        struct host_block_dev *host_dev;
        struct udevice *dev;
@@ -146,7 +146,7 @@ int host_dev_bind(int devnum, char *filename)
        }
 
        desc = blk_get_devnum_by_type(IF_TYPE_HOST, devnum);
-       desc->removable = 1;
+       desc->removable = removable;
        snprintf(desc->vendor, BLK_VEN_SIZE, "U-Boot");
        snprintf(desc->product, BLK_PRD_SIZE, "hostfile");
        snprintf(desc->revision, BLK_REV_SIZE, "1.0");
@@ -160,7 +160,7 @@ err:
        return ret;
 }
 #else
-int host_dev_bind(int dev, char *filename)
+int host_dev_bind(int dev, char *filename, bool removable)
 {
        struct host_block_dev *host_dev = find_host_device(dev);
 
@@ -195,7 +195,7 @@ int host_dev_bind(int dev, char *filename)
        blk_dev->block_write = host_block_write;
        blk_dev->devnum = dev;
        blk_dev->part_type = PART_TYPE_UNKNOWN;
-       blk_dev->removable = 1;
+       blk_dev->removable = removable;
        snprintf(blk_dev->vendor, BLK_VEN_SIZE, "U-Boot");
        snprintf(blk_dev->product, BLK_PRD_SIZE, "hostfile");
        snprintf(blk_dev->revision, BLK_REV_SIZE, "1.0");
index b87288d..4ab3c40 100644 (file)
@@ -39,7 +39,7 @@ int clk_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells,
 {
        int ret;
 
-       ret = device_get_by_driver_info_idx(cells->idx, &clk->dev);
+       ret = device_get_by_ofplat_idx(cells->idx, &clk->dev);
        if (ret)
                return ret;
        clk->id = cells->arg[0];
index 3c5a83c..09f9ef2 100644 (file)
@@ -25,18 +25,24 @@ const struct clk_ops clk_fixed_rate_ops = {
        .enable = dummy_enable,
 };
 
-static int clk_fixed_rate_of_to_plat(struct udevice *dev)
+void clk_fixed_rate_ofdata_to_plat_(struct udevice *dev,
+                                   struct clk_fixed_rate *plat)
 {
-       struct clk *clk = &to_clk_fixed_rate(dev)->clk;
+       struct clk *clk = &plat->clk;
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
-       to_clk_fixed_rate(dev)->fixed_rate =
-               dev_read_u32_default(dev, "clock-frequency", 0);
+       plat->fixed_rate = dev_read_u32_default(dev, "clock-frequency", 0);
 #endif
        /* Make fixed rate clock accessible from higher level struct clk */
        /* FIXME: This is not allowed */
        dev_set_uclass_priv(dev, clk);
+
        clk->dev = dev;
        clk->enable_count = 0;
+}
+
+static int clk_fixed_rate_of_to_plat(struct udevice *dev)
+{
+       clk_fixed_rate_ofdata_to_plat_(dev, to_clk_fixed_rate(dev));
 
        return 0;
 }
index b28b67b..57acf7d 100644 (file)
@@ -9,13 +9,7 @@
 #include <errno.h>
 #include <malloc.h>
 #include <asm/clk.h>
-
-struct sandbox_clk_priv {
-       bool probed;
-       ulong rate[SANDBOX_CLK_ID_COUNT];
-       bool enabled[SANDBOX_CLK_ID_COUNT];
-       bool requested[SANDBOX_CLK_ID_COUNT];
-};
+#include <linux/clk-provider.h>
 
 static ulong sandbox_clk_get_rate(struct clk *clk)
 {
@@ -178,3 +172,35 @@ int sandbox_clk_query_requested(struct udevice *dev, int id)
                return -EINVAL;
        return priv->requested[id];
 }
+
+int clk_fixed_rate_of_to_plat(struct udevice *dev)
+{
+       struct clk_fixed_rate *cplat;
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+       struct sandbox_clk_fixed_rate_plat *plat = dev_get_plat(dev);
+
+       cplat = &plat->fixed;
+       cplat->fixed_rate = plat->dtplat.clock_frequency;
+#else
+       cplat = to_clk_fixed_rate(dev);
+#endif
+       clk_fixed_rate_ofdata_to_plat_(dev, cplat);
+
+       return 0;
+}
+
+static const struct udevice_id sandbox_clk_fixed_rate_match[] = {
+       { .compatible = "sandbox,fixed-clock" },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sandbox_fixed_clock) = {
+       .name = "sandbox_fixed_clock",
+       .id = UCLASS_CLK,
+       .of_match = sandbox_clk_fixed_rate_match,
+       .of_to_plat = clk_fixed_rate_of_to_plat,
+       .plat_auto = sizeof(struct sandbox_clk_fixed_rate_plat),
+       .ops = &clk_fixed_rate_ops,
+       .flags = DM_FLAG_PRE_RELOC,
+};
index c4e4481..f665fd3 100644 (file)
 #include <dm/device_compat.h>
 #include <linux/err.h>
 
-struct sandbox_clk_test {
-       struct clk clks[SANDBOX_CLK_TEST_NON_DEVM_COUNT];
-       struct clk *clkps[SANDBOX_CLK_TEST_ID_COUNT];
-       struct clk_bulk bulk;
-};
-
 static const char * const sandbox_clk_test_names[] = {
        [SANDBOX_CLK_TEST_ID_FIXED] = "fixed",
        [SANDBOX_CLK_TEST_ID_SPI] = "spi",
index 609d8e3..13a623f 100644 (file)
@@ -97,8 +97,7 @@ static const resource_size_t zynqmp_crl_apb_clkc_base = 0xff5e0020;
 #define CLK_CTRL_DIV1_MASK     (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
 #define CLK_CTRL_DIV0_SHIFT    8
 #define CLK_CTRL_DIV0_MASK     (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
-#define CLK_CTRL_SRCSEL_SHIFT  0
-#define CLK_CTRL_SRCSEL_MASK   (0x3 << CLK_CTRL_SRCSEL_SHIFT)
+#define CLK_CTRL_SRCSEL_MASK   0x7
 #define PLLCTRL_FBDIV_MASK     0x7f00
 #define PLLCTRL_FBDIV_SHIFT    8
 #define PLLCTRL_RESET_MASK     1
@@ -132,7 +131,7 @@ enum zynqmp_clk {
        iou_switch,
        gem_tsu_ref, gem_tsu,
        gem0_ref, gem1_ref, gem2_ref, gem3_ref,
-       gem0_rx, gem1_rx, gem2_rx, gem3_rx,
+       gem0_tx, gem1_tx, gem2_tx, gem3_tx,
        qspi_ref,
        sdio0_ref, sdio1_ref,
        uart0_ref, uart1_ref,
@@ -152,7 +151,7 @@ static const char * const clk_names[clk_max] = {
        "iopll", "rpll", "apll", "dpll",
        "vpll", "iopll_to_fpd", "rpll_to_fpd",
        "apll_to_lpd", "dpll_to_lpd", "vpll_to_lpd",
-       "acpu", "acpu_half", "dbf_fpd", "dbf_lpd",
+       "acpu", "acpu_half", "dbg_fpd", "dbg_lpd",
        "dbg_trace", "dbg_tstmp", "dp_video_ref",
        "dp_audio_ref", "dp_stc_ref", "gdma_ref",
        "dpdma_ref", "ddr_ref", "sata_ref", "pcie_ref",
@@ -172,6 +171,38 @@ static const char * const clk_names[clk_max] = {
        "ams_ref", "pl0", "pl1", "pl2", "pl3", "wdt"
 };
 
+static const u32 pll_src[][4] = {
+       {apll, 0xff, dpll, vpll},               /* acpu */
+       {dpll, vpll, 0xff, 0xff},               /* ddr_ref */
+       {rpll, iopll, 0xff, 0xff},              /* dll_ref */
+       {iopll, 0xff, rpll, dpll_to_lpd},       /* gem_tsu_ref */
+       {iopll, 0xff, rpll, dpll},              /* peripheral */
+       {apll, 0xff, iopll_to_fpd, dpll},       /* wdt */
+       {iopll_to_fpd, 0xff, dpll, apll},       /* dbg_fpd */
+       {iopll, 0xff, rpll, dpll_to_lpd},       /* timestamp_ref */
+       {iopll_to_fpd, 0xff, apll, dpll},       /* sata_ref */
+       {iopll_to_fpd, 0xff, rpll_to_fpd, dpll},/* pcie_ref */
+       {iopll_to_fpd, 0xff, vpll, dpll},       /* gpu_ref */
+       {apll, 0xff, vpll, dpll},               /* topsw_main_ref */
+       {rpll, 0xff, iopll, dpll_to_lpd},       /* cpu_r5_ref */
+};
+
+enum zynqmp_clk_pll_src {
+       ACPU_CLK_SRC = 0,
+       DDR_CLK_SRC,
+       DLL_CLK_SRC,
+       GEM_TSU_CLK_SRC,
+       PERI_CLK_SRC,
+       WDT_CLK_SRC,
+       DBG_FPD_CLK_SRC,
+       TIMESTAMP_CLK_SRC,
+       SATA_CLK_SRC,
+       PCIE_CLK_SRC,
+       GPU_CLK_SRC,
+       TOPSW_MAIN_CLK_SRC,
+       CPU_R5_CLK_SRC
+};
+
 struct zynqmp_clk_priv {
        unsigned long ps_clk_freq;
        unsigned long video_clk;
@@ -195,12 +226,38 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
                return CRF_APB_VPLL_CTRL;
        case acpu:
                return CRF_APB_ACPU_CTRL;
+       case dbg_fpd:
+               return CRF_APB_DBG_FPD_CTRL;
+       case dbg_trace:
+               return CRF_APB_DBG_TRACE_CTRL;
+       case dbg_tstmp:
+               return CRF_APB_DBG_TSTMP_CTRL;
+       case gpu_ref ...  gpu_pp1_ref:
+               return CRF_APB_GPU_REF_CTRL;
        case ddr_ref:
                return CRF_APB_DDR_CTRL;
+       case sata_ref:
+               return CRF_APB_SATA_REF_CTRL;
+       case pcie_ref:
+               return CRF_APB_PCIE_REF_CTRL;
+       case gdma_ref:
+               return CRF_APB_GDMA_REF_CTRL;
+       case dpdma_ref:
+               return CRF_APB_DPDMA_REF_CTRL;
+       case topsw_main:
+               return CRF_APB_TOPSW_MAIN_CTRL;
+       case topsw_lsbus:
+               return CRF_APB_TOPSW_LSBUS_CTRL;
+       case lpd_switch:
+               return CRL_APB_LPD_SWITCH_CTRL;
+       case lpd_lsbus:
+               return CRL_APB_LPD_LSBUS_CTRL;
        case qspi_ref:
                return CRL_APB_QSPI_REF_CTRL;
        case usb3_dual_ref:
                return CRL_APB_USB3_DUAL_REF_CTRL;
+       case gem_tsu_ref:
+               return CRL_APB_GEM_TSU_REF_CTRL;
        case gem0_ref:
                return CRL_APB_GEM0_REF_CTRL;
        case gem1_ref:
@@ -213,6 +270,8 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
                return CRL_APB_USB0_BUS_REF_CTRL;
        case usb1_bus_ref:
                return CRL_APB_USB1_BUS_REF_CTRL;
+       case cpu_r5:
+               return CRL_APB_CPU_R5_CTRL;
        case uart0_ref:
                return CRL_APB_UART0_REF_CTRL;
        case uart1_ref:
@@ -235,6 +294,14 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
                return CRL_APB_CAN0_REF_CTRL;
        case can1_ref:
                return CRL_APB_CAN1_REF_CTRL;
+       case dll_ref:
+               return CRL_APB_DLL_REF_CTRL;
+       case adma_ref:
+               return CRL_APB_ADMA_REF_CTRL;
+       case timestamp_ref:
+               return CRL_APB_TIMESTAMP_REF_CTRL;
+       case ams_ref:
+               return CRL_APB_AMS_REF_CTRL;
        case pl0:
                return CRL_APB_PL0_REF_CTRL;
        case pl1:
@@ -253,68 +320,6 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
        return 0;
 }
 
-static enum zynqmp_clk zynqmp_clk_get_cpu_pll(u32 clk_ctrl)
-{
-       u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
-                     CLK_CTRL_SRCSEL_SHIFT;
-
-       switch (srcsel) {
-       case 2:
-               return dpll;
-       case 3:
-               return vpll;
-       case 0 ... 1:
-       default:
-               return apll;
-       }
-}
-
-static enum zynqmp_clk zynqmp_clk_get_ddr_pll(u32 clk_ctrl)
-{
-       u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
-                     CLK_CTRL_SRCSEL_SHIFT;
-
-       switch (srcsel) {
-       case 1:
-               return vpll;
-       case 0:
-       default:
-               return dpll;
-       }
-}
-
-static enum zynqmp_clk zynqmp_clk_get_peripheral_pll(u32 clk_ctrl)
-{
-       u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
-                     CLK_CTRL_SRCSEL_SHIFT;
-
-       switch (srcsel) {
-       case 2:
-               return rpll;
-       case 3:
-               return dpll;
-       case 0 ... 1:
-       default:
-               return iopll;
-       }
-}
-
-static enum zynqmp_clk zynqmp_clk_get_wdt_pll(u32 clk_ctrl)
-{
-       u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
-                     CLK_CTRL_SRCSEL_SHIFT;
-
-       switch (srcsel) {
-       case 2:
-               return iopll_to_fpd;
-       case 3:
-               return dpll;
-       case 0 ... 1:
-       default:
-               return apll;
-       }
-}
-
 static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
                                    struct zynqmp_clk_priv *priv,
                                    bool is_pre_src)
@@ -378,7 +383,7 @@ static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
 static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
                                     enum zynqmp_clk id)
 {
-       u32 clk_ctrl, div;
+       u32 clk_ctrl, div, srcsel;
        enum zynqmp_clk pll;
        int ret;
        unsigned long pllrate;
@@ -391,7 +396,8 @@ static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
 
        div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
 
-       pll = zynqmp_clk_get_cpu_pll(clk_ctrl);
+       srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+       pll = pll_src[ACPU_CLK_SRC][srcsel];
        pllrate = zynqmp_clk_get_pll_rate(priv, pll);
        if (IS_ERR_VALUE(pllrate))
                return pllrate;
@@ -401,7 +407,7 @@ static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
 
 static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
 {
-       u32 clk_ctrl, div;
+       u32 clk_ctrl, div, srcsel;
        enum zynqmp_clk pll;
        int ret;
        ulong pllrate;
@@ -414,7 +420,8 @@ static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
 
        div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
 
-       pll = zynqmp_clk_get_ddr_pll(clk_ctrl);
+       srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+       pll = pll_src[DDR_CLK_SRC][srcsel];
        pllrate = zynqmp_clk_get_pll_rate(priv, pll);
        if (IS_ERR_VALUE(pllrate))
                return pllrate;
@@ -422,11 +429,33 @@ static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
        return DIV_ROUND_CLOSEST(pllrate, div);
 }
 
+static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
+{
+       u32 clk_ctrl, srcsel;
+       enum zynqmp_clk pll;
+       ulong pllrate;
+       int ret;
+
+       ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
+       if (ret) {
+               printf("%s mio read fail\n", __func__);
+               return -EIO;
+       }
+
+       srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+       pll = pll_src[DLL_CLK_SRC][srcsel];
+       pllrate = zynqmp_clk_get_pll_rate(priv, pll);
+       if (IS_ERR_VALUE(pllrate))
+               return pllrate;
+
+       return pllrate;
+}
+
 static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
-                                         enum zynqmp_clk id, bool two_divs)
+                                           enum zynqmp_clk id, bool two_divs)
 {
        enum zynqmp_clk pll;
-       u32 clk_ctrl, div0;
+       u32 clk_ctrl, div0, srcsel;
        u32 div1 = 1;
        int ret;
        ulong pllrate;
@@ -446,8 +475,13 @@ static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
                if (!div1)
                        div1 = 1;
        }
+       srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+
+       if (id == gem_tsu_ref)
+               pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
+       else
+               pll = pll_src[PERI_CLK_SRC][srcsel];
 
-       pll = zynqmp_clk_get_peripheral_pll(clk_ctrl);
        pllrate = zynqmp_clk_get_pll_rate(priv, pll);
        if (IS_ERR_VALUE(pllrate))
                return pllrate;
@@ -457,11 +491,11 @@ static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
                        DIV_ROUND_CLOSEST(pllrate, div0), div1);
 }
 
-static ulong zynqmp_clk_get_wdt_rate(struct zynqmp_clk_priv *priv,
-                                    enum zynqmp_clk id, bool two_divs)
+static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
+                                        enum zynqmp_clk id, bool two_divs)
 {
        enum zynqmp_clk pll;
-       u32 clk_ctrl, div0;
+       u32 clk_ctrl, div0, srcsel;
        u32 div1 = 1;
        int ret;
        ulong pllrate;
@@ -475,8 +509,45 @@ static ulong zynqmp_clk_get_wdt_rate(struct zynqmp_clk_priv *priv,
        div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
        if (!div0)
                div0 = 1;
+       srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
 
-       pll = zynqmp_clk_get_wdt_pll(clk_ctrl);
+       switch (id) {
+       case wdt:
+       case dbg_trace:
+       case topsw_lsbus:
+               pll = pll_src[WDT_CLK_SRC][srcsel];
+               break;
+       case dbg_fpd:
+       case dbg_tstmp:
+               pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
+               break;
+       case timestamp_ref:
+               pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
+               break;
+       case sata_ref:
+               pll = pll_src[SATA_CLK_SRC][srcsel];
+               break;
+       case pcie_ref:
+               pll = pll_src[PCIE_CLK_SRC][srcsel];
+               break;
+       case gpu_ref ... gpu_pp1_ref:
+               pll = pll_src[GPU_CLK_SRC][srcsel];
+               break;
+       case gdma_ref:
+       case dpdma_ref:
+       case topsw_main:
+               pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
+               break;
+       case cpu_r5:
+       case ams_ref:
+       case adma_ref:
+       case lpd_lsbus:
+       case lpd_switch:
+               pll = pll_src[CPU_R5_CLK_SRC][srcsel];
+               break;
+       default:
+               return -ENXIO;
+       }
        if (two_divs) {
                ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
                if (ret) {
@@ -533,7 +604,7 @@ static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
        enum zynqmp_clk pll;
        u32 clk_ctrl, div0 = 0, div1 = 0;
        ulong pll_rate, new_rate;
-       u32 reg;
+       u32 reg, srcsel;
        int ret;
        u32 mask;
 
@@ -544,7 +615,8 @@ static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
                return -EIO;
        }
 
-       pll = zynqmp_clk_get_peripheral_pll(clk_ctrl);
+       srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+       pll = pll_src[PERI_CLK_SRC][srcsel];
        pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
        if (IS_ERR_VALUE(pll_rate))
                return pll_rate;
@@ -588,14 +660,31 @@ static ulong zynqmp_clk_get_rate(struct clk *clk)
                return zynqmp_clk_get_cpu_rate(priv, id);
        case ddr_ref:
                return zynqmp_clk_get_ddr_rate(priv);
+       case dll_ref:
+               return zynqmp_clk_get_dll_rate(priv);
+       case gem_tsu_ref:
+       case pl0 ... pl3:
        case gem0_ref ... gem3_ref:
        case qspi_ref ... can1_ref:
-       case pl0 ... pl3:
+       case usb0_bus_ref ... usb3_dual_ref:
                two_divs = true;
                return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
        case wdt:
+       case topsw_lsbus:
+       case sata_ref ... gpu_pp1_ref:
                two_divs = true;
-               return zynqmp_clk_get_wdt_rate(priv, id, two_divs);
+       case cpu_r5:
+       case dbg_fpd:
+       case ams_ref:
+       case adma_ref:
+       case lpd_lsbus:
+       case dbg_trace:
+       case dbg_tstmp:
+       case lpd_switch:
+       case topsw_main:
+       case timestamp_ref:
+       case gdma_ref ... dpdma_ref:
+               return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
        default:
                return -ENXIO;
        }
index 81f6880..cb960f8 100644 (file)
@@ -45,6 +45,9 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
        bool auto_seq = true;
        void *ptr;
 
+       if (CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND))
+               return -ENOSYS;
+
        if (devp)
                *devp = NULL;
        if (!name)
@@ -395,26 +398,31 @@ int device_of_to_plat(struct udevice *dev)
        if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
                return 0;
 
-       /* Ensure all parents have ofdata */
-       if (dev->parent) {
-               ret = device_of_to_plat(dev->parent);
+       /*
+        * This is not needed if binding is disabled, since data is allocated
+        * at build time.
+        */
+       if (!CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND)) {
+               /* Ensure all parents have ofdata */
+               if (dev->parent) {
+                       ret = device_of_to_plat(dev->parent);
+                       if (ret)
+                               goto fail;
+
+                       /*
+                        * The device might have already been probed during
+                        * the call to device_probe() on its parent device
+                        * (e.g. PCI bridge devices). Test the flags again
+                        * so that we don't mess up the device.
+                        */
+                       if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
+                               return 0;
+               }
+
+               ret = device_alloc_priv(dev);
                if (ret)
                        goto fail;
-
-               /*
-                * The device might have already been probed during
-                * the call to device_probe() on its parent device
-                * (e.g. PCI bridge devices). Test the flags again
-                * so that we don't mess up the device.
-                */
-               if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
-                       return 0;
        }
-
-       ret = device_alloc_priv(dev);
-       if (ret)
-               goto fail;
-
        drv = dev->driver;
        assert(drv);
 
@@ -592,7 +600,7 @@ void *dev_get_plat(const struct udevice *dev)
                return NULL;
        }
 
-       return dev->plat_;
+       return dm_priv_to_rw(dev->plat_);
 }
 
 void *dev_get_parent_plat(const struct udevice *dev)
@@ -602,7 +610,7 @@ void *dev_get_parent_plat(const struct udevice *dev)
                return NULL;
        }
 
-       return dev->parent_plat_;
+       return dm_priv_to_rw(dev->parent_plat_);
 }
 
 void *dev_get_uclass_plat(const struct udevice *dev)
@@ -612,7 +620,7 @@ void *dev_get_uclass_plat(const struct udevice *dev)
                return NULL;
        }
 
-       return dev->uclass_plat_;
+       return dm_priv_to_rw(dev->uclass_plat_);
 }
 
 void *dev_get_priv(const struct udevice *dev)
@@ -622,7 +630,7 @@ void *dev_get_priv(const struct udevice *dev)
                return NULL;
        }
 
-       return dev->priv_;
+       return dm_priv_to_rw(dev->priv_);
 }
 
 void *dev_get_uclass_priv(const struct udevice *dev)
@@ -632,7 +640,7 @@ void *dev_get_uclass_priv(const struct udevice *dev)
                return NULL;
        }
 
-       return dev->uclass_priv_;
+       return dm_priv_to_rw(dev->uclass_priv_);
 }
 
 void *dev_get_parent_priv(const struct udevice *dev)
@@ -642,7 +650,7 @@ void *dev_get_parent_priv(const struct udevice *dev)
                return NULL;
        }
 
-       return dev->parent_priv_;
+       return dm_priv_to_rw(dev->parent_priv_);
 }
 
 static int device_get_device_tail(struct udevice *dev, int ret,
@@ -803,27 +811,19 @@ int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp)
 }
 
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
-int device_get_by_driver_info(const struct driver_info *info,
-                             struct udevice **devp)
+int device_get_by_ofplat_idx(uint idx, struct udevice **devp)
 {
-       struct driver_info *info_base =
-               ll_entry_start(struct driver_info, driver_info);
-       int idx = info - info_base;
-       struct driver_rt *drt = gd_dm_driver_rt() + idx;
        struct udevice *dev;
 
-       dev = drt->dev;
-       *devp = NULL;
-
-       return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
-}
+       if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+               struct udevice *base = ll_entry_start(struct udevice, udevice);
 
-int device_get_by_driver_info_idx(uint idx, struct udevice **devp)
-{
-       struct driver_rt *drt = gd_dm_driver_rt() + idx;
-       struct udevice *dev;
+               dev = base + idx;
+       } else {
+               struct driver_rt *drt = gd_dm_driver_rt() + idx;
 
-       dev = drt->dev;
+               dev = drt->dev;
+       }
        *devp = NULL;
 
        return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
@@ -1136,3 +1136,36 @@ int dev_enable_by_path(const char *path)
        return lists_bind_fdt(parent, node, NULL, false);
 }
 #endif
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT)
+static struct udevice_rt *dev_get_rt(const struct udevice *dev)
+{
+       struct udevice *base = ll_entry_start(struct udevice, udevice);
+       int idx = dev - base;
+
+       struct udevice_rt *urt = gd_dm_udevice_rt() + idx;
+
+       return urt;
+}
+
+u32 dev_get_flags(const struct udevice *dev)
+{
+       const struct udevice_rt *urt = dev_get_rt(dev);
+
+       return urt->flags_;
+}
+
+void dev_or_flags(const struct udevice *dev, u32 or)
+{
+       struct udevice_rt *urt = dev_get_rt(dev);
+
+       urt->flags_ |= or;
+}
+
+void dev_bic_flags(const struct udevice *dev, u32 bic)
+{
+       struct udevice_rt *urt = dev_get_rt(dev);
+
+       urt->flags_ &= ~bic;
+}
+#endif /* OF_PLATDATA_RT */
index 5bc6ca1..b3e384d 100644 (file)
@@ -372,7 +372,7 @@ int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
        bus_node->count_cells(dev, &na, &ns);
        if (!OF_CHECK_COUNTS(na, ns)) {
                printf("Bad cell count for %s\n", of_node_full_name(dev));
-               return -EINVAL;
+               ret = -EINVAL;
                goto out_parent;
        }
 
@@ -380,7 +380,7 @@ int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
        bus_node->count_cells(parent, &pna, &pns);
        if (!OF_CHECK_COUNTS(pna, pns)) {
                printf("Bad cell count for %s\n", of_node_full_name(parent));
-               return -EINVAL;
+               ret = -EINVAL;
                goto out_parent;
        }
 
index 9bc682c..d9a19c5 100644 (file)
@@ -11,6 +11,7 @@
 #include <fdtdec.h>
 #include <log.h>
 #include <malloc.h>
+#include <asm-generic/sections.h>
 #include <asm/global_data.h>
 #include <linux/libfdt.h>
 #include <dm/acpi.h>
@@ -129,6 +130,36 @@ void fix_devices(void)
        }
 }
 
+static int dm_setup_inst(void)
+{
+       DM_ROOT_NON_CONST = DM_DEVICE_GET(root);
+
+       if (CONFIG_IS_ENABLED(OF_PLATDATA_RT)) {
+               struct udevice_rt *urt;
+               void *base;
+               int n_ents;
+               uint size;
+
+               /* Allocate the udevice_rt table */
+               n_ents = ll_entry_count(struct udevice, udevice);
+               urt = calloc(n_ents, sizeof(struct udevice_rt));
+               if (!urt)
+                       return log_msg_ret("urt", -ENOMEM);
+               gd_set_dm_udevice_rt(urt);
+
+               /* Now allocate space for the priv/plat data, and copy it in */
+               size = __priv_data_end - __priv_data_start;
+
+               base = calloc(1, size);
+               if (!base)
+                       return log_msg_ret("priv", -ENOMEM);
+               memcpy(base, __priv_data_start, size);
+               gd_set_dm_priv_base(base);
+       }
+
+       return 0;
+}
+
 int dm_init(bool of_live)
 {
        int ret;
@@ -140,8 +171,12 @@ int dm_init(bool of_live)
                dm_warn("Virtual root driver already exists!\n");
                return -EINVAL;
        }
-       gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;
-       INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);
+       if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+               gd->uclass_root = &uclass_head;
+       } else {
+               gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;
+               INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);
+       }
 
        if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) {
                fix_drivers();
@@ -149,14 +184,23 @@ int dm_init(bool of_live)
                fix_devices();
        }
 
-       ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
-       if (ret)
-               return ret;
-       if (CONFIG_IS_ENABLED(OF_CONTROL))
-               dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root());
-       ret = device_probe(DM_ROOT_NON_CONST);
-       if (ret)
-               return ret;
+       if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+               ret = dm_setup_inst();
+               if (ret) {
+                       log_debug("dm_setup_inst() failed: %d\n", ret);
+                       return ret;
+               }
+       } else {
+               ret = device_bind_by_name(NULL, false, &root_info,
+                                         &DM_ROOT_NON_CONST);
+               if (ret)
+                       return ret;
+               if (CONFIG_IS_ENABLED(OF_CONTROL))
+                       dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root());
+               ret = device_probe(DM_ROOT_NON_CONST);
+               if (ret)
+                       return ret;
+       }
 
        return 0;
 }
@@ -185,7 +229,7 @@ int dm_scan_plat(bool pre_reloc_only)
 {
        int ret;
 
-       if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+       if (CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT)) {
                struct driver_rt *dyn;
                int n_ents;
 
@@ -303,6 +347,15 @@ __weak int dm_scan_other(bool pre_reloc_only)
        return 0;
 }
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA_INST) && CONFIG_IS_ENABLED(READ_ONLY)
+void *dm_priv_to_rw(void *priv)
+{
+       long offset = priv - (void *)__priv_data_start;
+
+       return gd_dm_priv_base() + offset;
+}
+#endif
+
 /**
  * dm_scan() - Scan tables to bind devices
  *
@@ -347,10 +400,12 @@ int dm_init_and_scan(bool pre_reloc_only)
                debug("dm_init() failed: %d\n", ret);
                return ret;
        }
-       ret = dm_scan(pre_reloc_only);
-       if (ret) {
-               log_debug("dm_scan() failed: %d\n", ret);
-               return ret;
+       if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+               ret = dm_scan(pre_reloc_only);
+               if (ret) {
+                       log_debug("dm_scan() failed: %d\n", ret);
+                       return ret;
+               }
        }
 
        return 0;
index 1a4ea7a..117d35a 100644 (file)
@@ -148,8 +148,11 @@ int uclass_get(enum uclass_id id, struct uclass **ucp)
 
        *ucp = NULL;
        uc = uclass_find(id);
-       if (!uc)
+       if (!uc) {
+               if (CONFIG_IS_ENABLED(OF_PLATDATA_INST))
+                       return -ENOENT;
                return uclass_add(id, ucp);
+       }
        *ucp = uc;
 
        return 0;
@@ -391,7 +394,7 @@ done:
        return ret;
 }
 
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
                                  const char *name, struct udevice **devp)
 {
index 76b629a..8f8c425 100644 (file)
@@ -87,7 +87,23 @@ static unsigned int dfu_polltimeout_sf(struct dfu_entity *dfu)
 
 static void dfu_free_entity_sf(struct dfu_entity *dfu)
 {
-       spi_flash_free(dfu->data.sf.dev);
+       /*
+        * In the DM case it is not necessary to free the SPI device.
+        * For the non-DM case we must ensure that the the SPI device is only
+        * freed once.
+        */
+       if (!CONFIG_IS_ENABLED(DM_SPI_FLASH)) {
+               struct spi_flash *dev = dfu->data.sf.dev;
+
+               if (!dev)
+                       return;
+               dfu->data.sf.dev = NULL;
+               list_for_each_entry(dfu, &dfu_list, list) {
+                       if (dfu->data.sf.dev == dev)
+                               dfu->data.sf.dev = NULL;
+               }
+               spi_flash_free(dev);
+       }
 }
 
 static struct spi_flash *parse_dev(char *devstr)
index 4a9b74e..f24db87 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright (c) 2013 Google, Inc
  */
 
+#define LOG_CATEGORY   UCLASS_GPIO
+
 #include <common.h>
 #include <dm.h>
 #include <log.h>
@@ -21,6 +23,7 @@
 #include <dm/device_compat.h>
 #include <linux/bug.h>
 #include <linux/ctype.h>
+#include <linux/delay.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -220,7 +223,7 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
 static int gpio_find_and_xlate(struct gpio_desc *desc,
                               struct ofnode_phandle_args *args)
 {
-       struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+       const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
 
        if (ops->xlate)
                return ops->xlate(desc->dev, desc, args);
@@ -353,6 +356,7 @@ int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc)
 
 int dm_gpio_request(struct gpio_desc *desc, const char *label)
 {
+       const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
        struct udevice *dev = desc->dev;
        struct gpio_dev_priv *uc_priv;
        char *str;
@@ -364,8 +368,8 @@ int dm_gpio_request(struct gpio_desc *desc, const char *label)
        str = strdup(label);
        if (!str)
                return -ENOMEM;
-       if (gpio_get_ops(dev)->request) {
-               ret = gpio_get_ops(dev)->request(dev, desc->offset, label);
+       if (ops->request) {
+               ret = ops->request(dev, desc->offset, label);
                if (ret) {
                        free(str);
                        return ret;
@@ -442,14 +446,15 @@ int gpio_requestf(unsigned gpio, const char *fmt, ...)
 
 int _dm_gpio_free(struct udevice *dev, uint offset)
 {
+       const struct dm_gpio_ops *ops = gpio_get_ops(dev);
        struct gpio_dev_priv *uc_priv;
        int ret;
 
        uc_priv = dev_get_uclass_priv(dev);
        if (!uc_priv->name[offset])
                return -ENXIO;
-       if (gpio_get_ops(dev)->rfree) {
-               ret = gpio_get_ops(dev)->rfree(dev, offset);
+       if (ops->rfree) {
+               ret = ops->rfree(dev, offset);
                if (ret)
                        return ret;
        }
@@ -515,11 +520,8 @@ int gpio_direction_input(unsigned gpio)
        ret = gpio_to_device(gpio, &desc);
        if (ret)
                return ret;
-       ret = check_reserved(&desc, "dir_input");
-       if (ret)
-               return ret;
 
-       return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset);
+       return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN);
 }
 
 /**
@@ -534,24 +536,25 @@ int gpio_direction_input(unsigned gpio)
 int gpio_direction_output(unsigned gpio, int value)
 {
        struct gpio_desc desc;
+       ulong flags;
        int ret;
 
        ret = gpio_to_device(gpio, &desc);
        if (ret)
                return ret;
-       ret = check_reserved(&desc, "dir_output");
-       if (ret)
-               return ret;
 
-       return gpio_get_ops(desc.dev)->direction_output(desc.dev,
-                                                       desc.offset, value);
+       flags = GPIOD_IS_OUT;
+       if (value)
+               flags |= GPIOD_IS_OUT_ACTIVE;
+       return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, flags);
 }
 
 static int _gpio_get_value(const struct gpio_desc *desc)
 {
+       const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
        int value;
 
-       value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset);
+       value = ops->get_value(desc->dev, desc->offset);
 
        return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
 }
@@ -569,6 +572,7 @@ int dm_gpio_get_value(const struct gpio_desc *desc)
 
 int dm_gpio_set_value(const struct gpio_desc *desc, int value)
 {
+       const struct dm_gpio_ops *ops;
        int ret;
 
        ret = check_reserved(desc, "set_value");
@@ -578,21 +582,33 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value)
        if (desc->flags & GPIOD_ACTIVE_LOW)
                value = !value;
 
+       /* GPIOD_ are directly managed by driver in set_flags */
+       ops = gpio_get_ops(desc->dev);
+       if (ops->set_flags) {
+               ulong flags = desc->flags;
+
+               if (value)
+                       flags |= GPIOD_IS_OUT_ACTIVE;
+               else
+                       flags &= ~GPIOD_IS_OUT_ACTIVE;
+               return ops->set_flags(desc->dev, desc->offset, flags);
+       }
+
        /*
         * Emulate open drain by not actively driving the line high or
         * Emulate open source by not actively driving the line low
         */
        if ((desc->flags & GPIOD_OPEN_DRAIN && value) ||
            (desc->flags & GPIOD_OPEN_SOURCE && !value))
-               return gpio_get_ops(desc->dev)->direction_input(desc->dev,
-                                                               desc->offset);
+               return ops->direction_input(desc->dev, desc->offset);
        else if (desc->flags & GPIOD_OPEN_DRAIN ||
                 desc->flags & GPIOD_OPEN_SOURCE)
-               return gpio_get_ops(desc->dev)->direction_output(desc->dev,
-                                                               desc->offset,
-                                                               value);
+               return ops->direction_output(desc->dev, desc->offset, value);
+
+       ret = ops->set_value(desc->dev, desc->offset, value);
+       if (ret)
+               return ret;
 
-       gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value);
        return 0;
 }
 
@@ -620,10 +636,21 @@ static int check_dir_flags(ulong flags)
        return 0;
 }
 
-static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+/**
+ * _dm_gpio_set_flags() - Send flags to the driver
+ *
+ * This uses the best available method to send the given flags to the driver.
+ * Note that if flags & GPIOD_ACTIVE_LOW, the driver sees the opposite value
+ * of GPIOD_IS_OUT_ACTIVE.
+ *
+ * @desc:      GPIO description
+ * @flags:     flags value to set
+ * @return 0 if OK, -ve on error
+ */
+static int _dm_gpio_set_flags(struct gpio_desc *desc, ulong flags)
 {
        struct udevice *dev = desc->dev;
-       struct dm_gpio_ops *ops = gpio_get_ops(dev);
+       const struct dm_gpio_ops *ops = gpio_get_ops(dev);
        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
        int ret = 0;
 
@@ -638,38 +665,52 @@ static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
                return ret;
        }
 
-       /* GPIOD_ are directly managed by driver in set_dir_flags*/
-       if (ops->set_dir_flags) {
-               ret = ops->set_dir_flags(dev, desc->offset, flags);
+       /* If active low, invert the output state */
+       if ((flags & (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)) ==
+               (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW))
+               flags ^= GPIOD_IS_OUT_ACTIVE;
+
+       /* GPIOD_ are directly managed by driver in set_flags */
+       if (ops->set_flags) {
+               ret = ops->set_flags(dev, desc->offset, flags);
        } else {
                if (flags & GPIOD_IS_OUT) {
-                       ret = ops->direction_output(dev, desc->offset,
-                                                   GPIOD_FLAGS_OUTPUT(flags));
+                       bool value = flags & GPIOD_IS_OUT_ACTIVE;
+
+                       ret = ops->direction_output(dev, desc->offset, value);
                } else if (flags & GPIOD_IS_IN) {
                        ret = ops->direction_input(dev, desc->offset);
                }
        }
 
-       /* save the flags also in descriptor */
-       if (!ret)
-               desc->flags = flags;
-
        return ret;
 }
 
-int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set)
 {
+       ulong flags;
        int ret;
 
        ret = check_reserved(desc, "set_dir_flags");
        if (ret)
                return ret;
 
-       /* combine the requested flags (for IN/OUT) and the descriptor flags */
-       flags |= desc->flags;
-       ret = _dm_gpio_set_dir_flags(desc, flags);
+       flags = (desc->flags & ~clr) | set;
 
-       return ret;
+       ret = _dm_gpio_set_flags(desc, flags);
+       if (ret)
+               return ret;
+
+       /* save the flags also in descriptor */
+       desc->flags = flags;
+
+       return 0;
+}
+
+int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+{
+       /* combine the requested flags (for IN/OUT) and the descriptor flags */
+       return dm_gpio_clrset_flags(desc, GPIOD_MASK_DIR, flags);
 }
 
 int dm_gpio_set_dir(struct gpio_desc *desc)
@@ -680,42 +721,57 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
        if (ret)
                return ret;
 
-       return _dm_gpio_set_dir_flags(desc, desc->flags);
+       return _dm_gpio_set_flags(desc, desc->flags);
+}
+
+int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
+                         ulong set)
+{
+       int ret;
+       int i;
+
+       for (i = 0; i < count; i++) {
+               ret = dm_gpio_clrset_flags(&desc[i], clr, set);
+               if (ret)
+                       return log_ret(ret);
+       }
+
+       return 0;
 }
 
-int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags)
+int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
 {
        struct udevice *dev = desc->dev;
        int ret, value;
-       struct dm_gpio_ops *ops = gpio_get_ops(dev);
-       ulong dir_flags;
+       const struct dm_gpio_ops *ops = gpio_get_ops(dev);
+       ulong flags;
 
-       ret = check_reserved(desc, "get_dir_flags");
+       ret = check_reserved(desc, "get_flags");
        if (ret)
                return ret;
 
        /* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */
-       if (ops->get_dir_flags) {
-               ret = ops->get_dir_flags(dev, desc->offset, &dir_flags);
+       if (ops->get_flags) {
+               ret = ops->get_flags(dev, desc->offset, &flags);
                if (ret)
                        return ret;
 
                /* GPIOD_ACTIVE_LOW is saved in desc->flags */
-               value = dir_flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
+               value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
                if (desc->flags & GPIOD_ACTIVE_LOW)
                        value = !value;
-               dir_flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
-               dir_flags |= (desc->flags & GPIOD_ACTIVE_LOW);
+               flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
+               flags |= (desc->flags & GPIOD_ACTIVE_LOW);
                if (value)
-                       dir_flags |= GPIOD_IS_OUT_ACTIVE;
+                       flags |= GPIOD_IS_OUT_ACTIVE;
        } else {
-               dir_flags = desc->flags;
+               flags = desc->flags;
                /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */
-               dir_flags &= ~GPIOD_IS_OUT_ACTIVE;
+               flags &= ~GPIOD_IS_OUT_ACTIVE;
                if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc))
-                       dir_flags |= GPIOD_IS_OUT_ACTIVE;
+                       flags |= GPIOD_IS_OUT_ACTIVE;
        }
-       *flags = dir_flags;
+       *flagsp = flags;
 
        return 0;
 }
@@ -785,7 +841,7 @@ static int get_function(struct udevice *dev, int offset, bool skip_unused,
                        const char **namep)
 {
        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
-       struct dm_gpio_ops *ops = gpio_get_ops(dev);
+       const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 
        BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
        if (!device_active(dev))
@@ -822,7 +878,7 @@ int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
 
 int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
 {
-       struct dm_gpio_ops *ops = gpio_get_ops(dev);
+       const struct dm_gpio_ops *ops = gpio_get_ops(dev);
        struct gpio_dev_priv *priv;
        char *str = buf;
        int func;
@@ -862,7 +918,7 @@ int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
 #if CONFIG_IS_ENABLED(ACPIGEN)
 int gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio)
 {
-       struct dm_gpio_ops *ops;
+       const struct dm_gpio_ops *ops;
 
        memset(gpio, '\0', sizeof(*gpio));
        if (!dm_gpio_is_valid(desc)) {
@@ -949,6 +1005,71 @@ int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count)
        return vector;
 }
 
+int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
+                                   int count)
+{
+       static const char tristate[] = "01z";
+       enum {
+               PULLUP,
+               PULLDOWN,
+
+               NUM_OPTIONS,
+       };
+       int vals[NUM_OPTIONS];
+       uint mask;
+       uint vector = 0;
+       int ret, i;
+
+       /*
+        * Limit to 19 digits which should be plenty. This avoids overflow of a
+        * 32-bit int
+        */
+       assert(count < 20);
+
+       for (i = 0; i < NUM_OPTIONS; i++) {
+               uint flags = GPIOD_IS_IN;
+
+               flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN : GPIOD_PULL_UP;
+               ret = dm_gpios_clrset_flags(desc_list, count, GPIOD_MASK_PULL,
+                                           flags);
+               if (ret)
+                       return log_msg_ret("pu", ret);
+
+               /* Give the lines time to settle */
+               udelay(10);
+
+               ret = dm_gpio_get_values_as_int(desc_list, count);
+               if (ret < 0)
+                       return log_msg_ret("get1", ret);
+               vals[i] = ret;
+       }
+
+       log_debug("values: %x %x, count = %d\n", vals[0], vals[1], count);
+       for (i = count - 1, mask = 1 << i; i >= 0; i--, mask >>= 1) {
+               uint pd = vals[PULLDOWN] & mask ? 1 : 0;
+               uint pu = vals[PULLUP] & mask ? 1 : 0;
+               uint digit;
+
+               /*
+                * Get value with internal pulldown active. If this is 1 then
+                * there is a stronger external pullup, which we call 1. If not
+                * then call it 0.
+                *
+                * If the values differ then the pin is floating so we call
+                * this a 2.
+                */
+               if (pu == pd)
+                       digit = pd;
+               else
+                       digit = 2;
+               log_debug("%c ", tristate[digit]);
+               vector = 3 * vector + digit;
+       }
+       log_debug("vector=%d\n", vector);
+
+       return vector;
+}
+
 /**
  * gpio_request_tail: common work for requesting a gpio.
  *
@@ -1011,7 +1132,10 @@ static int gpio_request_tail(int ret, const char *nodename,
                debug("%s: dm_gpio_requestf failed\n", __func__);
                goto err;
        }
-       ret = dm_gpio_set_dir_flags(desc, flags);
+
+       /* Keep any direction flags provided by the devicetree */
+       ret = dm_gpio_set_dir_flags(desc,
+                                   flags | (desc->flags & GPIOD_MASK_DIR));
        if (ret) {
                debug("%s: dm_gpio_set_dir failed\n", __func__);
                goto err;
@@ -1024,6 +1148,7 @@ err:
        return ret;
 }
 
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 static int _gpio_request_by_name_nodev(ofnode node, const char *list_name,
                                       int index, struct gpio_desc *desc,
                                       int flags, bool add_index)
@@ -1110,6 +1235,7 @@ int gpio_get_list_count(struct udevice *dev, const char *list_name)
 
        return ret;
 }
+#endif /* OF_PLATDATA */
 
 int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
 {
@@ -1306,10 +1432,10 @@ static int gpio_post_bind(struct udevice *dev)
                        ops->get_function += gd->reloc_off;
                if (ops->xlate)
                        ops->xlate += gd->reloc_off;
-               if (ops->set_dir_flags)
-                       ops->set_dir_flags += gd->reloc_off;
-               if (ops->get_dir_flags)
-                       ops->get_dir_flags += gd->reloc_off;
+               if (ops->set_flags)
+                       ops->set_flags += gd->reloc_off;
+               if (ops->get_flags)
+                       ops->get_flags += gd->reloc_off;
 
                reloc_done++;
        }
index eda9548..f15ce7b 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright 2019 Google LLC
  */
 
+#define LOG_CATEGORY   UCLASS_GPIO
+
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
 #include <asm/pci.h>
 #include <asm/arch/gpio.h>
 #include <dm/acpi.h>
+#include <dm/device-internal.h>
 #include <dt-bindings/gpio/x86-gpio.h>
 
-static int intel_gpio_direction_input(struct udevice *dev, uint offset)
-{
-       struct udevice *pinctrl = dev_get_parent(dev);
-       uint config_offset;
-
-       config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
-
-       pcr_clrsetbits32(pinctrl, config_offset,
-                        PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE |
-                                 PAD_CFG0_RX_DISABLE,
-                        PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE);
-
-       return 0;
-}
-
-static int intel_gpio_direction_output(struct udevice *dev, uint offset,
-                                      int value)
-{
-       struct udevice *pinctrl = dev_get_parent(dev);
-       uint config_offset;
-
-       config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
-
-       pcr_clrsetbits32(pinctrl, config_offset,
-                        PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
-                                 PAD_CFG0_TX_DISABLE | PAD_CFG0_TX_STATE,
-                        PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE |
-                                 (value ? PAD_CFG0_TX_STATE : 0));
-
-       return 0;
-}
-
 static int intel_gpio_get_value(struct udevice *dev, uint offset)
 {
        struct udevice *pinctrl = dev_get_parent(dev);
@@ -115,7 +86,7 @@ static int intel_gpio_xlate(struct udevice *orig_dev, struct gpio_desc *desc,
 
        /*
         * GPIO numbers are global in the device tree so it doesn't matter
-        * which one is used
+        * which @orig_dev is used
         */
        gpio = args->args[0];
        ret = intel_pinctrl_get_pad(gpio, &pinctrl, &desc->offset);
@@ -127,6 +98,52 @@ static int intel_gpio_xlate(struct udevice *orig_dev, struct gpio_desc *desc,
        desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
        desc->dev = dev;
 
+       /*
+        * Handle the case where the wrong GPIO device was provided, since this
+        * will not have been probed by the GPIO uclass before calling here
+        * (see gpio_request_tail()).
+        */
+       if (orig_dev != dev) {
+               ret = device_probe(dev);
+               if (ret)
+                       return log_msg_ret("probe", ret);
+       }
+
+       return 0;
+}
+
+static int intel_gpio_set_flags(struct udevice *dev, unsigned int offset,
+                               ulong flags)
+{
+       struct udevice *pinctrl = dev_get_parent(dev);
+       u32 bic0 = 0, bic1 = 0;
+       u32 or0, or1;
+       uint config_offset;
+
+       config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
+
+       if (flags & GPIOD_IS_OUT) {
+               bic0 |= PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
+                       PAD_CFG0_TX_DISABLE;
+               or0 |= PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE;
+       } else if (flags & GPIOD_IS_IN) {
+               bic0 |= PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE |
+                       PAD_CFG0_RX_DISABLE;
+               or0 |= PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE;
+       }
+       if (flags & GPIOD_PULL_UP) {
+               bic1 |= PAD_CFG1_PULL_MASK;
+               or1 |= PAD_CFG1_PULL_UP_20K;
+       } else if (flags & GPIOD_PULL_DOWN) {
+               bic1 |= PAD_CFG1_PULL_MASK;
+               or1 |= PAD_CFG1_PULL_DN_20K;
+       }
+
+       pcr_clrsetbits32(pinctrl, PAD_CFG0_OFFSET(config_offset), bic0, or0);
+       pcr_clrsetbits32(pinctrl, PAD_CFG1_OFFSET(config_offset), bic1, or1);
+       log_debug("%s: flags=%lx, offset=%x, config_offset=%x, %x/%x %x/%x\n",
+                 dev->name, flags, offset, config_offset, bic0, or0, bic1, or1);
+
        return 0;
 }
 
@@ -177,12 +194,11 @@ static int intel_gpio_of_to_plat(struct udevice *dev)
 }
 
 static const struct dm_gpio_ops gpio_intel_ops = {
-       .direction_input        = intel_gpio_direction_input,
-       .direction_output       = intel_gpio_direction_output,
        .get_value              = intel_gpio_get_value,
        .set_value              = intel_gpio_set_value,
        .get_function           = intel_gpio_get_function,
        .xlate                  = intel_gpio_xlate,
+       .set_flags              = intel_gpio_set_flags,
 #if CONFIG_IS_ENABLED(ACPIGEN)
        .get_acpi               = intel_gpio_get_acpi,
 #endif
index dc8d506..d008fdd 100644 (file)
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/gpio/sandbox-gpio.h>
 
-
 struct gpio_state {
        const char *label;      /* label given by requester */
-       ulong dir_flags;        /* dir_flags (GPIOD_...) */
+       ulong flags;            /* flags (GPIOD_...) */
 };
 
-/* Access routines for GPIO dir flags */
-static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
+/* Access routines for GPIO info */
+static struct gpio_state *get_gpio_state(struct udevice *dev, uint offset)
 {
        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
        struct gpio_state *state = dev_get_priv(dev);
 
        if (offset >= uc_priv->gpio_count) {
-               static ulong invalid_dir_flags;
                printf("sandbox_gpio: error: invalid gpio %u\n", offset);
-               return &invalid_dir_flags;
+               return NULL;
        }
 
-       return &state[offset].dir_flags;
+       return &state[offset];
+}
+
+/* Access routines for GPIO flags */
+static ulong *get_gpio_flags(struct udevice *dev, unsigned int offset)
+{
+       struct gpio_state *state = get_gpio_state(dev, offset);
+
+       if (!state)
+               return NULL;
+
+       return &state->flags;
 
 }
 
 static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
 {
-       return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
+       return (*get_gpio_flags(dev, offset) & flag) != 0;
 }
 
 static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
                         int value)
 {
-       ulong *gpio = get_gpio_dir_flags(dev, offset);
+       struct gpio_state *state = get_gpio_state(dev, offset);
 
        if (value)
-               *gpio |= flag;
+               state->flags |= flag;
        else
-               *gpio &= ~flag;
+               state->flags &= ~flag;
 
        return 0;
 }
@@ -65,14 +74,31 @@ static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
 
 int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
 {
+       struct gpio_state *state = get_gpio_state(dev, offset);
+       bool val;
+
        if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
                debug("sandbox_gpio: get_value on output gpio %u\n", offset);
-       return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
+
+       if (state->flags & GPIOD_EXT_DRIVEN) {
+               val = state->flags & GPIOD_EXT_HIGH;
+       } else {
+               if (state->flags & GPIOD_EXT_PULL_UP)
+                       val = true;
+               else if (state->flags & GPIOD_EXT_PULL_DOWN)
+                       val = false;
+               else
+                       val = state->flags & GPIOD_PULL_UP;
+       }
+
+       return val;
 }
 
 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
-       return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
+       set_gpio_flag(dev, offset, GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
+
+       return 0;
 }
 
 int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
@@ -83,20 +109,23 @@ int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
 int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
 {
        set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
-       set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
+       set_gpio_flag(dev, offset, GPIOD_IS_IN, !output);
 
        return 0;
 }
 
-ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
+ulong sandbox_gpio_get_flags(struct udevice *dev, uint offset)
 {
-       return *get_gpio_dir_flags(dev, offset);
+       ulong flags = *get_gpio_flags(dev, offset);
+
+       return flags & ~GPIOD_SANDBOX_MASK;
 }
 
-int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-                              ulong flags)
+int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags)
 {
-       *get_gpio_dir_flags(dev, offset) = flags;
+       struct gpio_state *state = get_gpio_state(dev, offset);
+
+       state->flags = flags;
 
        return 0;
 }
@@ -117,10 +146,19 @@ static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
 static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
                                    int value)
 {
+       int ret;
+
        debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
-       return sandbox_gpio_set_direction(dev, offset, 1) |
-               sandbox_gpio_set_value(dev, offset, value);
+       ret = sandbox_gpio_set_direction(dev, offset, 1);
+       if (ret)
+               return ret;
+       ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE |
+                           GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
 /* read GPIO IN value of port 'offset' */
@@ -134,6 +172,8 @@ static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
 /* write GPIO OUT value to port 'offset' */
 static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
+       int ret;
+
        debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
        if (!sandbox_gpio_get_direction(dev, offset)) {
@@ -142,7 +182,12 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
                return -1;
        }
 
-       return sandbox_gpio_set_value(dev, offset, value);
+       ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE |
+                           GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
 static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
@@ -177,33 +222,30 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
        return 0;
 }
 
-static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-                                ulong flags)
+static int sb_gpio_set_flags(struct udevice *dev, unsigned int offset,
+                            ulong flags)
 {
-       ulong *dir_flags;
-
-       debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
-
-       dir_flags = get_gpio_dir_flags(dev, offset);
-
-       /*
-        * For testing purposes keep the output value when switching to input.
-        * This allows us to manipulate the input value via the gpio command.
-        */
-       if (flags & GPIOD_IS_IN)
-               *dir_flags = (flags & ~GPIOD_IS_OUT_ACTIVE) |
-                            (*dir_flags & GPIOD_IS_OUT_ACTIVE);
-       else
-               *dir_flags = flags;
+       debug("%s: offset:%u, flags = %lx\n", __func__, offset, flags);
+       struct gpio_state *state = get_gpio_state(dev, offset);
+
+       if (flags & GPIOD_IS_OUT) {
+               flags |= GPIOD_EXT_DRIVEN;
+               if (flags & GPIOD_IS_OUT_ACTIVE)
+                       flags |= GPIOD_EXT_HIGH;
+               else
+                       flags &= ~GPIOD_EXT_HIGH;
+       } else {
+               flags |= state->flags & GPIOD_SANDBOX_MASK;
+       }
+       state->flags = flags;
 
        return 0;
 }
 
-static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-                                ulong *flags)
+static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp)
 {
        debug("%s: offset:%u\n", __func__, offset);
-       *flags = *get_gpio_dir_flags(dev, offset);
+       *flagsp = *get_gpio_flags(dev, offset) & ~GPIOD_SANDBOX_MASK;
 
        return 0;
 }
@@ -272,8 +314,8 @@ static const struct dm_gpio_ops gpio_sandbox_ops = {
        .set_value              = sb_gpio_set_value,
        .get_function           = sb_gpio_get_function,
        .xlate                  = sb_gpio_xlate,
-       .set_dir_flags          = sb_gpio_set_dir_flags,
-       .get_dir_flags          = sb_gpio_get_dir_flags,
+       .set_flags              = sb_gpio_set_flags,
+       .get_flags              = sb_gpio_get_flags,
 #if CONFIG_IS_ENABLED(ACPIGEN)
        .get_acpi               = sb_gpio_get_acpi,
 #endif
@@ -456,7 +498,7 @@ static const char *sb_pinctrl_get_pin_name(struct udevice *dev,
        return pin_name;
 }
 
-static char *get_dir_flags_string(ulong flags)
+static char *get_flags_string(ulong flags)
 {
        if (flags & GPIOD_OPEN_DRAIN)
                return "drive-open-drain";
@@ -475,7 +517,7 @@ static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
 {
        struct udevice *gpio_dev;
        unsigned int gpio_idx;
-       ulong dir_flags;
+       ulong flags;
        int function;
 
        /* look up for the bank which owns the requested pin */
@@ -484,11 +526,11 @@ static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
                snprintf(buf, size, "Error");
        } else {
                function = sb_gpio_get_function(gpio_dev, gpio_idx);
-               dir_flags = *get_gpio_dir_flags(gpio_dev, gpio_idx);
+               flags = *get_gpio_flags(gpio_dev, gpio_idx);
 
                snprintf(buf, size, "gpio %s %s",
                         function == GPIOF_OUTPUT ? "output" : "input",
-                        get_dir_flags_string(dir_flags));
+                        get_flags_string(flags));
        }
 
        return 0;
index 7184db3..125c237 100644 (file)
@@ -191,8 +191,8 @@ static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset)
        return GPIOF_FUNC;
 }
 
-static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-                                   ulong flags)
+static int stm32_gpio_set_flags(struct udevice *dev, unsigned int offset,
+                               ulong flags)
 {
        struct stm32_gpio_priv *priv = dev_get_priv(dev);
        struct stm32_gpio_regs *regs = priv->regs;
@@ -203,12 +203,13 @@ static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
                return idx;
 
        if (flags & GPIOD_IS_OUT) {
-               int value = GPIOD_FLAGS_OUTPUT(flags);
+               bool value = flags & GPIOD_IS_OUT_ACTIVE;
 
                if (flags & GPIOD_OPEN_DRAIN)
                        stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_OD);
                else
                        stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_PP);
+
                stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT);
                writel(BSRR_BIT(idx, value), &regs->bsrr);
 
@@ -223,8 +224,8 @@ static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
        return 0;
 }
 
-static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-                                   ulong *flags)
+static int stm32_gpio_get_flags(struct udevice *dev, unsigned int offset,
+                               ulong *flagsp)
 {
        struct stm32_gpio_priv *priv = dev_get_priv(dev);
        struct stm32_gpio_regs *regs = priv->regs;
@@ -259,7 +260,7 @@ static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
        default:
                break;
        }
-       *flags = dir_flags;
+       *flagsp = dir_flags;
 
        return 0;
 }
@@ -270,8 +271,8 @@ static const struct dm_gpio_ops gpio_stm32_ops = {
        .get_value              = stm32_gpio_get_value,
        .set_value              = stm32_gpio_set_value,
        .get_function           = stm32_gpio_get_function,
-       .set_dir_flags          = stm32_gpio_set_dir_flags,
-       .get_dir_flags          = stm32_gpio_get_dir_flags,
+       .set_flags              = stm32_gpio_set_flags,
+       .get_flags              = stm32_gpio_get_flags,
 };
 
 static int gpio_stm32_probe(struct udevice *dev)
index acd27ac..8c9f1fc 100644 (file)
@@ -39,9 +39,7 @@ obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o
 obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o
 obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o
 obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o
-ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o
-endif
 obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o
 obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o
 obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o
index 085b824..7917b63 100644 (file)
@@ -7,6 +7,7 @@
 #include <dm.h>
 #include <i2c.h>
 #include <log.h>
+#include <asm/i2c.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
 
  * uclass so avoid having strange devices on the I2C bus.
  */
 
-/**
- * struct i2c_emul_uc_plat - information about the emulator for this device
- *
- * This is used by devices in UCLASS_I2C_EMUL to record information about the
- * device being emulated. It is accessible with dev_get_uclass_plat()
- *
- * @dev: Device being emulated
- */
-struct i2c_emul_uc_plat {
-       struct udevice *dev;
-};
-
 struct udevice *i2c_emul_get_device(struct udevice *emul)
 {
        struct i2c_emul_uc_plat *uc_plat = dev_get_uclass_plat(emul);
@@ -42,14 +31,27 @@ struct udevice *i2c_emul_get_device(struct udevice *emul)
        return uc_plat->dev;
 }
 
+void i2c_emul_set_idx(struct udevice *dev, int emul_idx)
+{
+       struct dm_i2c_chip *plat = dev_get_parent_plat(dev);
+
+       plat->emul_idx = emul_idx;
+}
+
 int i2c_emul_find(struct udevice *dev, struct udevice **emulp)
 {
        struct i2c_emul_uc_plat *uc_plat;
        struct udevice *emul;
        int ret;
 
-       ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev,
-                                           "sandbox,emul", &emul);
+       if (!CONFIG_IS_ENABLED(OF_PLATDATA)) {
+               ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev,
+                                                   "sandbox,emul", &emul);
+       } else {
+               struct dm_i2c_chip *plat = dev_get_parent_plat(dev);
+
+               ret = device_get_by_ofplat_idx(plat->emul_idx, &emul);
+       }
        if (ret) {
                log_err("No emulators for device '%s'\n", dev->name);
                return ret;
@@ -85,8 +87,8 @@ static const struct udevice_id i2c_emul_parent_ids[] = {
        { }
 };
 
-U_BOOT_DRIVER(i2c_emul_parent_drv) = {
-       .name           = "i2c_emul_parent_drv",
+U_BOOT_DRIVER(sandbox_i2c_emul_parent) = {
+       .name           = "sandbox_i2c_emul_parent",
        .id             = UCLASS_I2C_EMUL_PARENT,
        .of_match       = i2c_emul_parent_ids,
 };
index 5ba0a54..8bbe33d 100644 (file)
@@ -9,7 +9,7 @@
 #error This driver requires coreboot
 #endif
 
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 
 struct cbmem_console {
        u32 buffer_size;
index cb8adc4..bc01df0 100644 (file)
@@ -153,10 +153,14 @@ static int cros_ec_write_state(void *blob, int node)
 {
        struct ec_state *ec = g_state;
 
+       if (!g_state)
+               return 0;
+
        /* We are guaranteed enough space to write basic properties */
        fdt_setprop_u32(blob, node, "current-image", ec->current_image);
        fdt_setprop(blob, node, "vbnv-context", ec->vbnv_context,
                    sizeof(ec->vbnv_context));
+
        return state_setprop(node, "flash-data", ec->flash_data,
                             ec->ec_config.flash.length);
 }
index 24b2796..3aa26f6 100644 (file)
@@ -69,7 +69,7 @@ int irq_get_by_driver_info(struct udevice *dev,
 {
        int ret;
 
-       ret = device_get_by_driver_info_idx(cells->idx, &irq->dev);
+       ret = device_get_by_ofplat_idx(cells->idx, &irq->dev);
        if (ret)
                return ret;
        irq->id = cells->arg[0];
index 973d02d..51f8716 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #define LOG_CATEGORY UCLASS_MISC
-#define LOG_DEBUG
 
 #include <common.h>
 #include <axi.h>
index 827a50e..5d72982 100644 (file)
@@ -86,7 +86,7 @@ static const struct udevice_id testbus_ids[] = {
        { }
 };
 
-U_BOOT_DRIVER(testbus_drv) = {
+U_BOOT_DRIVER(denx_u_boot_test_bus) = {
        .name   = "testbus_drv",
        .of_match       = testbus_ids,
        .id     = UCLASS_TEST_BUS,
@@ -98,6 +98,7 @@ U_BOOT_DRIVER(testbus_drv) = {
        .per_child_plat_auto    = sizeof(struct dm_test_parent_plat),
        .child_pre_probe = testbus_child_pre_probe,
        .child_post_remove = testbus_child_post_remove,
+       DM_HEADER(<test.h>)
 };
 
 UCLASS_DRIVER(testbus) = {
@@ -106,6 +107,9 @@ UCLASS_DRIVER(testbus) = {
        .flags          = DM_UC_FLAG_SEQ_ALIAS,
        .child_pre_probe = testbus_child_pre_probe_uclass,
        .child_post_probe = testbus_child_post_probe_uclass,
+
+       /* This is for dtoc testing only */
+       .per_device_plat_auto   = sizeof(struct dm_test_uclass_priv),
 };
 
 static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret)
@@ -160,7 +164,9 @@ static const struct udevice_id testfdt_ids[] = {
        { }
 };
 
-U_BOOT_DRIVER(testfdt_drv) = {
+DM_DRIVER_ALIAS(denx_u_boot_fdt_test, google_another_fdt_test)
+
+U_BOOT_DRIVER(denx_u_boot_fdt_test) = {
        .name   = "testfdt_drv",
        .of_match       = testfdt_ids,
        .id     = UCLASS_TEST_FDT,
@@ -203,6 +209,7 @@ UCLASS_DRIVER(testfdt) = {
        .name           = "testfdt",
        .id             = UCLASS_TEST_FDT,
        .flags          = DM_UC_FLAG_SEQ_ALIAS,
+       .priv_auto      = sizeof(struct dm_test_uc_priv),
 };
 
 static const struct udevice_id testfdtm_ids[] = {
index f8ca52e..c34fce3 100644 (file)
@@ -311,6 +311,7 @@ config MMC_MXS
 
 config MMC_PCI
        bool "Support for MMC controllers on PCI"
+       depends on MMC_SDHCI
        help
          This selects PCI-based MMC controllers.
          If you have an MMC controller on a PCI bus, say Y here.
index 6a9403d..09a5cd6 100644 (file)
@@ -1530,8 +1530,7 @@ static int fsl_esdhc_probe(struct udevice *dev)
        if (CONFIG_IS_ENABLED(DM_GPIO) && !priv->non_removable) {
                struct udevice *gpiodev;
 
-               ret = device_get_by_driver_info_idx(dtplat->cd_gpios->idx,
-                                                   &gpiodev);
+               ret = device_get_by_ofplat_idx(dtplat->cd_gpios->idx, &gpiodev);
                if (ret)
                        return ret;
 
index fd5dd22..b9ab064 100644 (file)
@@ -53,6 +53,7 @@ static int pci_mmc_probe(struct udevice *dev)
        host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
                                              PCI_REGION_MEM);
        host->name = dev->name;
+       host->cd_gpio = priv->cd_gpio;
        host->mmc = &plat->mmc;
        host->mmc->dev = dev;
        ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
@@ -68,8 +69,11 @@ static int pci_mmc_of_to_plat(struct udevice *dev)
 {
        if (CONFIG_IS_ENABLED(DM_GPIO)) {
                struct pci_mmc_priv *priv = dev_get_priv(dev);
+               int ret;
 
-               gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
+               ret = gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
+                                          GPIOD_IS_IN);
+               log_debug("cd-gpio %s done, ret=%d\n", dev->name, ret);
        }
 
        return 0;
index 12d1321..cfce00e 100644 (file)
@@ -31,6 +31,15 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len)
        return log_ret(sf_get_ops(dev)->erase(dev, offset, len));
 }
 
+int spl_flash_get_sw_write_prot(struct udevice *dev)
+{
+       struct dm_spi_flash_ops *ops = sf_get_ops(dev);
+
+       if (!ops->get_sw_write_prot)
+               return -ENOSYS;
+       return log_ret(ops->get_sw_write_prot(dev));
+}
+
 /*
  * TODO(sjg@chromium.org): This is an old-style function. We should remove
  * it when all SPI flash drivers use dm
@@ -46,11 +55,6 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
        return dev_get_uclass_priv(dev);
 }
 
-void spi_flash_free(struct spi_flash *flash)
-{
-       device_remove(flash->spi->dev, DM_REMOVE_NORMAL);
-}
-
 int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
                           unsigned int max_hz, unsigned int spi_mode,
                           struct udevice **devp)
index 9ceff0e..786301b 100644 (file)
@@ -75,6 +75,10 @@ extern const struct flash_info spi_nor_ids[];
 #define JEDEC_MFR(info)        ((info)->id[0])
 #define JEDEC_ID(info)         (((info)->id[1]) << 8 | ((info)->id[2]))
 
+/* Get software write-protect value (BP bits) */
+int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash);
+
+
 #if CONFIG_IS_ENABLED(SPI_FLASH_MTD)
 int spi_flash_mtd_register(struct spi_flash *flash);
 void spi_flash_mtd_unregister(void);
index 6c87434..3befbe9 100644 (file)
@@ -130,6 +130,13 @@ static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
        return mtd->_erase(mtd, &instr);
 }
 
+static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
+{
+       struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+       return spi_flash_cmd_get_sw_write_prot(flash);
+}
+
 int spi_flash_std_probe(struct udevice *dev)
 {
        struct spi_slave *slave = dev_get_parent_priv(dev);
@@ -153,6 +160,7 @@ static const struct dm_spi_flash_ops spi_flash_std_ops = {
        .read = spi_flash_std_read,
        .write = spi_flash_std_write,
        .erase = spi_flash_std_erase,
+       .get_sw_write_prot = spi_flash_std_get_sw_write_prot,
 };
 
 static const struct udevice_id spi_flash_std_ids[] = {
index e0efebc..a662553 100644 (file)
@@ -2647,3 +2647,14 @@ int spi_nor_scan(struct spi_nor *nor)
 
        return 0;
 }
+
+/* U-Boot specific functions, need to extend MTD to support these */
+int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor)
+{
+       int sr = read_sr(nor);
+
+       if (sr < 0)
+               return sr;
+
+       return (sr >> 2) & 7;
+}
index 07c8c7b..1d5861d 100644 (file)
@@ -809,3 +809,9 @@ int spi_nor_scan(struct spi_nor *nor)
 
        return 0;
 }
+
+/* U-Boot specific functions, need to extend MTD to support these */
+int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor)
+{
+       return -ENOTSUPP;
+}
index baf06a2..ff59982 100644 (file)
@@ -454,14 +454,6 @@ static int zynq_gem_init(struct udevice *dev)
            priv->int_pcs) {
                nwconfig |= ZYNQ_GEM_NWCFG_SGMII_ENBL |
                            ZYNQ_GEM_NWCFG_PCS_SEL;
-#ifdef CONFIG_ARM64
-       if (priv->phydev->phy_id != PHY_FIXED_ID)
-               writel(readl(&regs->pcscntrl) | ZYNQ_GEM_PCS_CTL_ANEG_ENBL,
-                      &regs->pcscntrl);
-       else
-               writel(readl(&regs->pcscntrl) & ~ZYNQ_GEM_PCS_CTL_ANEG_ENBL,
-                      &regs->pcscntrl);
-#endif
        }
 
        switch (priv->phydev->speed) {
@@ -480,6 +472,23 @@ static int zynq_gem_init(struct udevice *dev)
                break;
        }
 
+#ifdef CONFIG_ARM64
+       if (priv->interface == PHY_INTERFACE_MODE_SGMII &&
+           priv->int_pcs) {
+               /*
+                * Disable AN for fixed link configuration, enable otherwise.
+                * Must be written after PCS_SEL is set in nwconfig,
+                * otherwise writes will not take effect.
+                */
+               if (priv->phydev->phy_id != PHY_FIXED_ID)
+                       writel(readl(&regs->pcscntrl) | ZYNQ_GEM_PCS_CTL_ANEG_ENBL,
+                              &regs->pcscntrl);
+               else
+                       writel(readl(&regs->pcscntrl) & ~ZYNQ_GEM_PCS_CTL_ANEG_ENBL,
+                              &regs->pcscntrl);
+       }
+#endif
+
        ret = clk_set_rate(&priv->tx_clk, clk_rate);
        if (IS_ERR_VALUE(ret)) {
                dev_err(dev, "failed to set tx clock rate\n");
index a14a4db..7bad4c8 100644 (file)
@@ -349,13 +349,10 @@ int vbe_setup_video_priv(struct vesa_mode_info *vesa,
        }
 
        /* Use double buffering if enabled */
-       if (IS_ENABLED(CONFIG_VIDEO_COPY)) {
-               if (!plat->base)
-                       return log_msg_ret("copy", -ENFILE);
+       if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->base)
                plat->copy_base = vesa->phys_base_ptr;
-       } else {
+       else
                plat->base = vesa->phys_base_ptr;
-       }
        log_debug("base = %lx, copy_base = %lx\n", plat->base, plat->copy_base);
        plat->size = vesa->bytes_per_scanline * vesa->y_resolution;
 
index 7ce64fd..5d4bec2 100644 (file)
@@ -201,6 +201,10 @@ static int mt7629_wf2g_led_funcs[] = { 1, };
 static int mt7629_wf5g_led_pins[] = { 18, };
 static int mt7629_wf5g_led_funcs[] = { 1, };
 
+/* LED for EPHY used as JTAG */
+static int mt7629_ephy_leds_jtag_pins[] = { 12, 13, 14, 15, 16, };
+static int mt7629_ephy_leds_jtag_funcs[] = { 7, 7, 7, 7, 7, };
+
 /* Watchdog */
 static int mt7629_watchdog_pins[] = { 11, };
 static int mt7629_watchdog_funcs[] = { 1, };
@@ -297,6 +301,7 @@ static const struct mtk_group_desc mt7629_groups[] = {
        PINCTRL_PIN_GROUP("ephy_led2", mt7629_ephy_led2),
        PINCTRL_PIN_GROUP("ephy_led3", mt7629_ephy_led3),
        PINCTRL_PIN_GROUP("ephy_led4", mt7629_ephy_led4),
+       PINCTRL_PIN_GROUP("ephy_leds_jtag", mt7629_ephy_leds_jtag),
        PINCTRL_PIN_GROUP("wf2g_led", mt7629_wf2g_led),
        PINCTRL_PIN_GROUP("wf5g_led", mt7629_wf5g_led),
        PINCTRL_PIN_GROUP("watchdog", mt7629_watchdog),
@@ -364,6 +369,7 @@ static const char *const mt7629_uart_groups[] = { "uart1_0_txd_rxd",
 static const char *const mt7629_wdt_groups[] = { "watchdog", };
 static const char *const mt7629_wifi_groups[] = { "wf0_5g", "wf0_2g", };
 static const char *const mt7629_flash_groups[] = { "snfi", "spi_nor" };
+static const char *const mt7629_jtag_groups[] = { "ephy_leds_jtag" };
 
 static const struct mtk_function_desc mt7629_functions[] = {
        {"eth", mt7629_ethernet_groups, ARRAY_SIZE(mt7629_ethernet_groups)},
@@ -376,6 +382,7 @@ static const struct mtk_function_desc mt7629_functions[] = {
        {"watchdog", mt7629_wdt_groups, ARRAY_SIZE(mt7629_wdt_groups)},
        {"wifi", mt7629_wifi_groups, ARRAY_SIZE(mt7629_wifi_groups)},
        {"flash", mt7629_flash_groups, ARRAY_SIZE(mt7629_flash_groups)},
+       {"jtag", mt7629_jtag_groups, ARRAY_SIZE(mt7629_jtag_groups)},
 };
 
 static struct mtk_pinctrl_soc mt7629_data = {
index 4dd3f73..3bd23be 100644 (file)
@@ -219,7 +219,7 @@ static const char *mtk_get_pin_name(struct udevice *dev,
 {
        struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
 
-       if (!priv->soc->grps[selector].name)
+       if (!priv->soc->pins[selector].name)
                return mtk_pinctrl_dummy_name;
 
        return priv->soc->pins[selector].name;
@@ -232,6 +232,19 @@ static int mtk_get_pins_count(struct udevice *dev)
        return priv->soc->npins;
 }
 
+static int mtk_get_pin_muxing(struct udevice *dev, unsigned int selector,
+                             char *buf, int size)
+{
+       int val, err;
+
+       err = mtk_hw_get_value(dev, selector, PINCTRL_PIN_REG_MODE, &val);
+       if (err)
+               return err;
+
+       snprintf(buf, size, "Aux Func.%d", val);
+       return 0;
+}
+
 static const char *mtk_get_group_name(struct udevice *dev,
                                      unsigned int selector)
 {
@@ -512,6 +525,7 @@ static int mtk_pinconf_group_set(struct udevice *dev,
 const struct pinctrl_ops mtk_pinctrl_ops = {
        .get_pins_count = mtk_get_pins_count,
        .get_pin_name = mtk_get_pin_name,
+       .get_pin_muxing = mtk_get_pin_muxing,
        .get_groups_count = mtk_get_groups_count,
        .get_group_name = mtk_get_group_name,
        .get_functions_count = mtk_get_functions_count,
@@ -526,6 +540,8 @@ const struct pinctrl_ops mtk_pinctrl_ops = {
        .set_state = pinctrl_generic_set_state,
 };
 
+#if CONFIG_IS_ENABLED(DM_GPIO) || \
+    (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
 static int mtk_gpio_get(struct udevice *dev, unsigned int off)
 {
        int val, err;
@@ -633,12 +649,13 @@ static int mtk_gpiochip_register(struct udevice *parent)
 
        return 0;
 }
+#endif
 
 int mtk_pinctrl_common_probe(struct udevice *dev,
                             struct mtk_pinctrl_soc *soc)
 {
        struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
-       int ret;
+       int ret = 0;
 
        priv->base = dev_read_addr_ptr(dev);
        if (!priv->base)
@@ -646,9 +663,10 @@ int mtk_pinctrl_common_probe(struct udevice *dev,
 
        priv->soc = soc;
 
+#if CONFIG_IS_ENABLED(DM_GPIO) || \
+    (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
        ret = mtk_gpiochip_register(dev);
-       if (ret)
-               return ret;
+#endif
 
-       return 0;
+       return ret;
 }
index b7ae2f6..26fb5d6 100644 (file)
@@ -25,6 +25,7 @@ DECLARE_GLOBAL_DATA_PTR;
 
 struct atmel_pio4_plat {
        struct atmel_pio4_port *reg_base;
+       unsigned int slew_rate_support;
 };
 
 static const struct pinconf_param conf_params[] = {
@@ -36,9 +37,11 @@ static const struct pinconf_param conf_params[] = {
        { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
        { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
        { "atmel,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
+       { "slew-rate", PIN_CONFIG_SLEW_RATE, 0},
 };
 
-static u32 atmel_pinctrl_get_pinconf(struct udevice *config)
+static u32 atmel_pinctrl_get_pinconf(struct udevice *config,
+                                    struct atmel_pio4_plat *plat)
 {
        const struct pinconf_param *params;
        u32 param, arg, conf = 0;
@@ -53,6 +56,10 @@ static u32 atmel_pinctrl_get_pinconf(struct udevice *config)
                param = params->param;
                arg = params->default_value;
 
+               /* Keep slew rate enabled by default. */
+               if (plat->slew_rate_support)
+                       conf |= ATMEL_PIO_SR;
+
                switch (param) {
                case PIN_CONFIG_BIAS_DISABLE:
                        conf &= (~ATMEL_PIO_PUEN_MASK);
@@ -91,6 +98,15 @@ static u32 atmel_pinctrl_get_pinconf(struct udevice *config)
                        conf |= (val << ATMEL_PIO_DRVSTR_OFFSET)
                                & ATMEL_PIO_DRVSTR_MASK;
                        break;
+               case PIN_CONFIG_SLEW_RATE:
+                       if (!plat->slew_rate_support)
+                               break;
+
+                       dev_read_u32(config, params->property, &val);
+                       /* And disable it if requested. */
+                       if (val == 0)
+                               conf &= ~ATMEL_PIO_SR;
+                       break;
                default:
                        printf("%s: Unsupported configuration parameter: %u\n",
                               __func__, param);
@@ -116,6 +132,7 @@ static inline struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
 
 static int atmel_pinctrl_set_state(struct udevice *dev, struct udevice *config)
 {
+       struct atmel_pio4_plat *plat = dev_get_plat(dev);
        struct atmel_pio4_port *bank_base;
        const void *blob = gd->fdt_blob;
        int node = dev_of_offset(config);
@@ -124,7 +141,7 @@ static int atmel_pinctrl_set_state(struct udevice *dev, struct udevice *config)
        u32 i, conf;
        int count;
 
-       conf = atmel_pinctrl_get_pinconf(config);
+       conf = atmel_pinctrl_get_pinconf(config, plat);
 
        count = fdtdec_get_int_array_count(blob, node, "pinmux",
                                           cells, ARRAY_SIZE(cells));
@@ -164,6 +181,7 @@ const struct pinctrl_ops atmel_pinctrl_ops  = {
 static int atmel_pinctrl_probe(struct udevice *dev)
 {
        struct atmel_pio4_plat *plat = dev_get_plat(dev);
+       ulong priv = dev_get_driver_data(dev);
        fdt_addr_t addr_base;
 
        dev = dev_get_parent(dev);
@@ -172,13 +190,15 @@ static int atmel_pinctrl_probe(struct udevice *dev)
                return -EINVAL;
 
        plat->reg_base = (struct atmel_pio4_port *)addr_base;
+       plat->slew_rate_support = priv;
 
        return 0;
 }
 
 static const struct udevice_id atmel_pinctrl_match[] = {
        { .compatible = "atmel,sama5d2-pinctrl" },
-       { .compatible = "microchip,sama7g5-pinctrl" },
+       { .compatible = "microchip,sama7g5-pinctrl",
+         .data = (ulong)1, },
        {}
 };
 
index 1a8d0a3..fe7a59d 100644 (file)
@@ -163,12 +163,14 @@ static int stmfx_gpio_direction_output(struct udevice *dev,
        return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 1);
 }
 
-static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-                                   ulong flags)
+static int stmfx_gpio_set_flags(struct udevice *dev, unsigned int offset,
+                               ulong flags)
 {
        int ret = -ENOTSUPP;
 
        if (flags & GPIOD_IS_OUT) {
+               bool value = flags & GPIOD_IS_OUT_ACTIVE;
+
                if (flags & GPIOD_OPEN_SOURCE)
                        return -ENOTSUPP;
                if (flags & GPIOD_OPEN_DRAIN)
@@ -177,8 +179,7 @@ static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
                        ret = stmfx_conf_set_type(dev, offset, 1);
                if (ret)
                        return ret;
-               ret = stmfx_gpio_direction_output(dev, offset,
-                                                 GPIOD_FLAGS_OUTPUT(flags));
+               ret = stmfx_gpio_direction_output(dev, offset, value);
        } else if (flags & GPIOD_IS_IN) {
                ret = stmfx_gpio_direction_input(dev, offset);
                if (ret)
@@ -199,8 +200,8 @@ static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
        return ret;
 }
 
-static int stmfx_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-                                   ulong *flags)
+static int stmfx_gpio_get_flags(struct udevice *dev, unsigned int offset,
+                               ulong *flagsp)
 {
        ulong dir_flags = 0;
        int ret;
@@ -233,7 +234,7 @@ static int stmfx_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
                                dir_flags |= GPIOD_PULL_DOWN;
                }
        }
-       *flags = dir_flags;
+       *flagsp = dir_flags;
 
        return 0;
 }
@@ -266,8 +267,8 @@ static const struct dm_gpio_ops stmfx_gpio_ops = {
        .get_function = stmfx_gpio_get_function,
        .direction_input = stmfx_gpio_direction_input,
        .direction_output = stmfx_gpio_direction_output,
-       .set_dir_flags = stmfx_gpio_set_dir_flags,
-       .get_dir_flags = stmfx_gpio_get_dir_flags,
+       .set_flags = stmfx_gpio_set_flags,
+       .get_flags = stmfx_gpio_get_flags,
 };
 
 U_BOOT_DRIVER(stmfx_gpio) = {
index d2be4c8..8fb9cba 100644 (file)
@@ -77,6 +77,16 @@ config PINCTRL_PFC_R8A774B1
           the GPIO definitions and pin control functions for each available
           multiplex function.
 
+config PINCTRL_PFC_R8A774C0
+        bool "Renesas RZ/G2 R8A774C0 pin control driver"
+        depends on PINCTRL_PFC
+        help
+          Support pin multiplexing control on Renesas RZ/G2E R8A774C0 SoCs.
+
+          The driver is controlled by a device tree node which contains both
+          the GPIO definitions and pin control functions for each available
+          multiplex function.
+
 config PINCTRL_PFC_R8A774E1
         bool "Renesas RZ/G2 R8A774E1 pin control driver"
         depends on PINCTRL_PFC
index 1d00752..0e2ac3c 100644 (file)
@@ -1,6 +1,7 @@
 obj-$(CONFIG_PINCTRL_PFC) += pfc.o
 obj-$(CONFIG_PINCTRL_PFC_R8A774A1) += pfc-r8a7796.o
 obj-$(CONFIG_PINCTRL_PFC_R8A774B1) += pfc-r8a77965.o
+obj-$(CONFIG_PINCTRL_PFC_R8A774C0) += pfc-r8a77990.o
 obj-$(CONFIG_PINCTRL_PFC_R8A774E1) += pfc-r8a7795.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7790) += pfc-r8a7790.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7791) += pfc-r8a7791.o
index b13fc0b..572b041 100644 (file)
@@ -1603,6 +1603,7 @@ static const unsigned int canfd1_data_mux[] = {
        CANFD1_TX_MARK, CANFD1_RX_MARK,
 };
 
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
 /* - DRIF0 --------------------------------------------------------------- */
 static const unsigned int drif0_ctrl_a_pins[] = {
        /* CLK, SYNC */
@@ -1795,6 +1796,7 @@ static const unsigned int drif3_data1_b_pins[] = {
 static const unsigned int drif3_data1_b_mux[] = {
        RIF3_D1_B_MARK,
 };
+#endif /* CONFIG_PINCTRL_PFC_R8A77990 */
 
 /* - DU --------------------------------------------------------------------- */
 static const unsigned int du_rgb666_pins[] = {
@@ -2818,6 +2820,57 @@ static const unsigned int pwm6_b_mux[] = {
        PWM6_B_MARK,
 };
 
+/* - QSPI0 ------------------------------------------------------------------ */
+static const unsigned int qspi0_ctrl_pins[] = {
+       /* QSPI0_SPCLK, QSPI0_SSL */
+       RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 5),
+};
+static const unsigned int qspi0_ctrl_mux[] = {
+       QSPI0_SPCLK_MARK, QSPI0_SSL_MARK,
+};
+static const unsigned int qspi0_data2_pins[] = {
+       /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1 */
+       RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2),
+};
+static const unsigned int qspi0_data2_mux[] = {
+       QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK,
+};
+static const unsigned int qspi0_data4_pins[] = {
+       /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1 */
+       RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2),
+       /* QSPI0_IO2, QSPI0_IO3 */
+       RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 4),
+};
+static const unsigned int qspi0_data4_mux[] = {
+       QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK,
+       QSPI0_IO2_MARK, QSPI0_IO3_MARK,
+};
+/* - QSPI1 ------------------------------------------------------------------ */
+static const unsigned int qspi1_ctrl_pins[] = {
+       /* QSPI1_SPCLK, QSPI1_SSL */
+       RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 11),
+};
+static const unsigned int qspi1_ctrl_mux[] = {
+       QSPI1_SPCLK_MARK, QSPI1_SSL_MARK,
+};
+static const unsigned int qspi1_data2_pins[] = {
+       /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1 */
+       RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8),
+};
+static const unsigned int qspi1_data2_mux[] = {
+       QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK,
+};
+static const unsigned int qspi1_data4_pins[] = {
+       /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1 */
+       RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8),
+       /* QSPI1_IO2, QSPI1_IO3 */
+       RCAR_GP_PIN(2, 9), RCAR_GP_PIN(2, 10),
+};
+static const unsigned int qspi1_data4_mux[] = {
+       QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK,
+       QSPI1_IO2_MARK, QSPI1_IO3_MARK,
+};
+
 /* - SCIF0 ------------------------------------------------------------------ */
 static const unsigned int scif0_data_a_pins[] = {
        /* RX, TX */
@@ -3770,8 +3823,10 @@ static const unsigned int vin5_clk_b_mux[] = {
 };
 
 static const struct {
-       struct sh_pfc_pin_group common[247];
+       struct sh_pfc_pin_group common[253];
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
        struct sh_pfc_pin_group automotive[21];
+#endif
 } pinmux_groups = {
        .common = {
                SH_PFC_PIN_GROUP(audio_clk_a),
@@ -3916,6 +3971,12 @@ static const struct {
                SH_PFC_PIN_GROUP(pwm5_b),
                SH_PFC_PIN_GROUP(pwm6_a),
                SH_PFC_PIN_GROUP(pwm6_b),
+               SH_PFC_PIN_GROUP(qspi0_ctrl),
+               SH_PFC_PIN_GROUP(qspi0_data2),
+               SH_PFC_PIN_GROUP(qspi0_data4),
+               SH_PFC_PIN_GROUP(qspi1_ctrl),
+               SH_PFC_PIN_GROUP(qspi1_data2),
+               SH_PFC_PIN_GROUP(qspi1_data4),
                SH_PFC_PIN_GROUP(scif0_data_a),
                SH_PFC_PIN_GROUP(scif0_clk_a),
                SH_PFC_PIN_GROUP(scif0_ctrl_a),
@@ -4022,6 +4083,7 @@ static const struct {
                SH_PFC_PIN_GROUP(vin5_clk_a),
                SH_PFC_PIN_GROUP(vin5_clk_b),
        },
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
        .automotive = {
                SH_PFC_PIN_GROUP(drif0_ctrl_a),
                SH_PFC_PIN_GROUP(drif0_data0_a),
@@ -4045,6 +4107,7 @@ static const struct {
                SH_PFC_PIN_GROUP(drif3_data0_b),
                SH_PFC_PIN_GROUP(drif3_data1_b),
        }
+#endif /* CONFIG_PINCTRL_PFC_R8A77990 */
 };
 
 static const char * const audio_clk_groups[] = {
@@ -4098,6 +4161,7 @@ static const char * const canfd1_groups[] = {
        "canfd1_data",
 };
 
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
 static const char * const drif0_groups[] = {
        "drif0_ctrl_a",
        "drif0_data0_a",
@@ -4130,6 +4194,7 @@ static const char * const drif3_groups[] = {
        "drif3_data0_b",
        "drif3_data1_b",
 };
+#endif /* CONFIG_PINCTRL_PFC_R8A77990 */
 
 static const char * const du_groups[] = {
        "du_rgb666",
@@ -4315,6 +4380,18 @@ static const char * const pwm6_groups[] = {
        "pwm6_b",
 };
 
+static const char * const qspi0_groups[] = {
+       "qspi0_ctrl",
+       "qspi0_data2",
+       "qspi0_data4",
+};
+
+static const char * const qspi1_groups[] = {
+       "qspi1_ctrl",
+       "qspi1_data2",
+       "qspi1_data4",
+};
+
 static const char * const scif0_groups[] = {
        "scif0_data_a",
        "scif0_clk_a",
@@ -4469,8 +4546,10 @@ static const char * const vin5_groups[] = {
 };
 
 static const struct {
-       struct sh_pfc_function common[47];
+       struct sh_pfc_function common[49];
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
        struct sh_pfc_function automotive[4];
+#endif
 } pinmux_functions = {
        .common = {
                SH_PFC_FUNCTION(audio_clk),
@@ -4504,6 +4583,8 @@ static const struct {
                SH_PFC_FUNCTION(pwm4),
                SH_PFC_FUNCTION(pwm5),
                SH_PFC_FUNCTION(pwm6),
+               SH_PFC_FUNCTION(qspi0),
+               SH_PFC_FUNCTION(qspi1),
                SH_PFC_FUNCTION(scif0),
                SH_PFC_FUNCTION(scif1),
                SH_PFC_FUNCTION(scif2),
@@ -4521,12 +4602,14 @@ static const struct {
                SH_PFC_FUNCTION(vin4),
                SH_PFC_FUNCTION(vin5),
        },
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
        .automotive = {
                SH_PFC_FUNCTION(drif0),
                SH_PFC_FUNCTION(drif1),
                SH_PFC_FUNCTION(drif2),
                SH_PFC_FUNCTION(drif3),
        }
+#endif /* CONFIG_PINCTRL_PFC_R8A77990 */
 };
 
 static const struct pinmux_cfg_reg pinmux_config_regs[] = {
index 6ff9484..07fcc3d 100644 (file)
@@ -34,6 +34,7 @@ enum sh_pfc_model {
        SH_PFC_R8A7796,
        SH_PFC_R8A774A1,
        SH_PFC_R8A774B1,
+       SH_PFC_R8A774C0,
        SH_PFC_R8A774E1,
        SH_PFC_R8A77965,
        SH_PFC_R8A77970,
@@ -927,6 +928,10 @@ static int sh_pfc_pinctrl_probe(struct udevice *dev)
        if (model == SH_PFC_R8A774B1)
                priv->pfc.info = &r8a774b1_pinmux_info;
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A774C0
+       if (model == SH_PFC_R8A774C0)
+               priv->pfc.info = &r8a774c0_pinmux_info;
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A774E1
        if (model == SH_PFC_R8A774E1)
                priv->pfc.info = &r8a774e1_pinmux_info;
@@ -1014,6 +1019,12 @@ static const struct udevice_id sh_pfc_pinctrl_ids[] = {
                .data = SH_PFC_R8A774B1,
        },
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A774C0
+       {
+               .compatible = "renesas,pfc-r8a774c0",
+               .data = SH_PFC_R8A774C0,
+       },
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A774E1
        {
                .compatible = "renesas,pfc-r8a774e1",
index 22cc860..f563916 100644 (file)
@@ -295,6 +295,7 @@ sh_pfc_pin_to_bias_reg(const struct sh_pfc *pfc, unsigned int pin,
 
 extern const struct sh_pfc_soc_info r8a774a1_pinmux_info;
 extern const struct sh_pfc_soc_info r8a774b1_pinmux_info;
+extern const struct sh_pfc_soc_info r8a774c0_pinmux_info;
 extern const struct sh_pfc_soc_info r8a774e1_pinmux_info;
 extern const struct sh_pfc_soc_info r8a7790_pinmux_info;
 extern const struct sh_pfc_soc_info r8a7791_pinmux_info;
index f25b976..ba418c2 100644 (file)
 #define debug_buffer(x, ...)
 #endif
 
-/**
- * struct sandbox_i2c_rtc_plat_data - platform data for the RTC
- *
- * @base_time:         Base system time when RTC device was bound
- * @offset:            RTC offset from current system time
- * @use_system_time:   true to use system time, false to use @base_time
- * @reg:               Register values
- */
-struct sandbox_i2c_rtc_plat_data {
-       long base_time;
-       long offset;
-       bool use_system_time;
-       u8 reg[REG_COUNT];
-};
-
-struct sandbox_i2c_rtc {
-       unsigned int offset_secs;
-};
-
 long sandbox_i2c_rtc_set_offset(struct udevice *dev, bool use_system_time,
                                int offset)
 {
@@ -223,7 +204,7 @@ static int sandbox_i2c_rtc_bind(struct udevice *dev)
 }
 
 static const struct udevice_id sandbox_i2c_rtc_ids[] = {
-       { .compatible = "sandbox,i2c-rtc" },
+       { .compatible = "sandbox,i2c-rtc-emul" },
        { }
 };
 
index d0864b1..657e5c7 100644 (file)
@@ -79,6 +79,18 @@ struct acpi_ops sandbox_rtc_acpi_ops = {
 };
 #endif
 
+static int sandbox_rtc_bind(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(PLATDATA)
+       struct sandbox_i2c_rtc_plat_data *plat = dev_get_plat(dev);
+
+       /* Set up the emul_idx for i2c_emul_find() */
+       i2c_emul_set_idx(dev, plat->dtplat.sandbox_emul->idx);
+#endif
+
+       return 0;
+}
+
 static const struct rtc_ops sandbox_rtc_ops = {
        .get = sandbox_rtc_get,
        .set = sandbox_rtc_set,
@@ -97,5 +109,6 @@ U_BOOT_DRIVER(sandbox_rtc) = {
        .id     = UCLASS_RTC,
        .of_match = sandbox_rtc_ids,
        .ops    = &sandbox_rtc_ops,
+       .bind   = sandbox_rtc_bind,
        ACPI_OPS_PTR(&sandbox_rtc_acpi_ops)
 };
index 88c8209..de09c86 100644 (file)
@@ -9,7 +9,7 @@
 #include <dm.h>
 #include <ns16550.h>
 #include <serial.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 
 static int coreboot_of_to_plat(struct udevice *dev)
 {
index 6d41602..4145d9f 100644 (file)
@@ -73,74 +73,64 @@ struct mtk_serial_regs {
 struct mtk_serial_priv {
        struct mtk_serial_regs __iomem *regs;
        u32 clock;
+       bool force_highspeed;
 };
 
 static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
 {
-       bool support_clk12m_baud115200;
-       u32 quot, samplecount, realbaud;
+       u32 quot, realbaud, samplecount = 1;
 
-       if ((baud <= 115200) && (priv->clock == 12000000))
-               support_clk12m_baud115200 = true;
-       else
-               support_clk12m_baud115200 = false;
+       /* Special case for low baud clock */
+       if (baud <= 115200 && priv->clock <= 12000000) {
+               writel(3, &priv->regs->highspeed);
+
+               quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
+               if (quot == 0)
+                       quot = 1;
+
+               samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
+
+               realbaud = priv->clock / samplecount / quot;
+               if (realbaud > BAUD_ALLOW_MAX(baud) ||
+                   realbaud < BAUD_ALLOW_MIX(baud)) {
+                       pr_info("baud %d can't be handled\n", baud);
+               }
+
+               goto set_baud;
+       }
+
+       if (priv->force_highspeed)
+               goto use_hs3;
 
        if (baud <= 115200) {
                writel(0, &priv->regs->highspeed);
                quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
-
-               if (support_clk12m_baud115200) {
-                       writel(3, &priv->regs->highspeed);
-                       quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
-                       if (quot == 0)
-                               quot = 1;
-
-                       samplecount = DIV_ROUND_CLOSEST(priv->clock,
-                                                       quot * baud);
-                       if (samplecount != 0) {
-                               realbaud = priv->clock / samplecount / quot;
-                               if ((realbaud > BAUD_ALLOW_MAX(baud)) ||
-                                   (realbaud < BAUD_ALLOW_MIX(baud))) {
-                                       pr_info("baud %d can't be handled\n",
-                                               baud);
-                               }
-                       } else {
-                               pr_info("samplecount is 0\n");
-                       }
-               }
        } else if (baud <= 576000) {
                writel(2, &priv->regs->highspeed);
 
                /* Set to next lower baudrate supported */
                if ((baud == 500000) || (baud == 576000))
                        baud = 460800;
+
                quot = DIV_ROUND_UP(priv->clock, 4 * baud);
        } else {
+use_hs3:
                writel(3, &priv->regs->highspeed);
+
                quot = DIV_ROUND_UP(priv->clock, 256 * baud);
+               samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
        }
 
+set_baud:
        /* set divisor */
        writel(UART_LCR_WLS_8 | UART_LCR_DLAB, &priv->regs->lcr);
        writel(quot & 0xff, &priv->regs->dll);
        writel((quot >> 8) & 0xff, &priv->regs->dlm);
        writel(UART_LCR_WLS_8, &priv->regs->lcr);
 
-       if (baud > 460800) {
-               u32 tmp;
-
-               tmp = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
-               writel(tmp - 1, &priv->regs->sample_count);
-               writel((tmp - 2) >> 1, &priv->regs->sample_point);
-       } else {
-               writel(0, &priv->regs->sample_count);
-               writel(0xff, &priv->regs->sample_point);
-       }
-
-       if (support_clk12m_baud115200) {
-               writel(samplecount - 1, &priv->regs->sample_count);
-               writel((samplecount - 2) >> 1, &priv->regs->sample_point);
-       }
+       /* set highspeed mode sample count & point */
+       writel(samplecount - 1, &priv->regs->sample_count);
+       writel((samplecount - 2) >> 1, &priv->regs->sample_point);
 }
 
 static int _mtk_serial_putc(struct mtk_serial_priv *priv, const char ch)
@@ -248,6 +238,8 @@ static int mtk_serial_of_to_plat(struct udevice *dev)
                return -EINVAL;
        }
 
+       priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed");
+
        return 0;
 }
 
index 5cf8225..932f737 100644 (file)
@@ -4,7 +4,6 @@
  * Written by Simon Glass <sjg@chromium.org>
  */
 #define LOG_CATEGORY UCLASS_I2S
-#define LOG_DEBUG
 
 #include <common.h>
 #include <dm.h>
index 7155d4a..ee30110 100644 (file)
@@ -11,6 +11,7 @@
 #include <log.h>
 #include <malloc.h>
 #include <spi.h>
+#include <spi-mem.h>
 #include <dm/device_compat.h>
 #include <asm/global_data.h>
 #include <dm/device-internal.h>
@@ -199,6 +200,16 @@ static int spi_post_probe(struct udevice *bus)
                        ops->set_mode += gd->reloc_off;
                if (ops->cs_info)
                        ops->cs_info += gd->reloc_off;
+               if (ops->mem_ops) {
+                       struct spi_controller_mem_ops *mem_ops =
+                               (struct spi_controller_mem_ops *)ops->mem_ops;
+                       if (mem_ops->adjust_op_size)
+                               mem_ops->adjust_op_size += gd->reloc_off;
+                       if (mem_ops->supports_op)
+                               mem_ops->supports_op += gd->reloc_off;
+                       if (mem_ops->exec_op)
+                               mem_ops->exec_op += gd->reloc_off;
+               }
                reloc_done++;
        }
 #endif
index 0274afd..b892cda 100644 (file)
@@ -314,8 +314,7 @@ static int xilinx_spi_set_speed(struct udevice *bus, uint speed)
 
        priv->freq = speed;
 
-       debug("xilinx_spi_set_speed: regs=%p, speed=%d\n", priv->regs,
-             priv->freq);
+       debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
 
        return 0;
 }
@@ -324,7 +323,7 @@ static int xilinx_spi_set_mode(struct udevice *bus, uint mode)
 {
        struct xilinx_spi_priv *priv = dev_get_priv(bus);
        struct xilinx_spi_regs *regs = priv->regs;
-       uint32_t spicr;
+       u32 spicr;
 
        spicr = readl(&regs->spicr);
        if (mode & SPI_LSB_FIRST)
@@ -339,8 +338,7 @@ static int xilinx_spi_set_mode(struct udevice *bus, uint mode)
        writel(spicr, &regs->spicr);
        priv->mode = mode;
 
-       debug("xilinx_spi_set_mode: regs=%p, mode=%d\n", priv->regs,
-             priv->mode);
+       debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
 
        return 0;
 }
index 6c9dc7a..9512f68 100644 (file)
@@ -113,7 +113,7 @@ void sysreset_walk_halt(enum sysreset_t type)
 /**
  * reset_cpu() - calls sysreset_walk(SYSRESET_WARM)
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        sysreset_walk_halt(SYSRESET_WARM);
 }
index 65622f3..d030280 100644 (file)
@@ -31,6 +31,12 @@ config OPTEE_TA_RPC_TEST
          permits to test reverse RPC calls to TEE supplicant. Should
          be used only in sandbox env.
 
+config OPTEE_TA_SCP03
+       bool "Support SCP03 TA"
+       default y
+       help
+         Enables support for controlling (enabling, provisioning) the
+         Secure Channel Protocol 03 operation in the OP-TEE SCP03 TA.
 endmenu
 
 endif
index 3a1d34d..35e8542 100644 (file)
@@ -8,6 +8,7 @@
 #include <tee.h>
 #include <tee/optee_ta_avb.h>
 #include <tee/optee_ta_rpc_test.h>
+#include <tee/optee_ta_scp03.h>
 
 #include "optee/optee_msg.h"
 #include "optee/optee_private.h"
@@ -68,6 +69,7 @@ void *optee_alloc_and_init_page_list(void *buf, ulong len,
        return NULL;
 }
 
+#if defined(CONFIG_OPTEE_TA_SCP03) || defined(CONFIG_OPTEE_TA_AVB)
 static u32 get_attr(uint n, uint num_params, struct tee_param *params)
 {
        if (n >= num_params)
@@ -79,7 +81,7 @@ static u32 get_attr(uint n, uint num_params, struct tee_param *params)
 static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
                        struct tee_param *params)
 {
-       u8 p[] = { p0, p1, p2, p3};
+       u8 p[] = { p0, p1, p2, p3 };
        uint n;
 
        for (n = 0; n < ARRAY_SIZE(p); n++)
@@ -97,6 +99,50 @@ bad_params:
 
        return TEE_ERROR_BAD_PARAMETERS;
 }
+#endif
+
+#ifdef CONFIG_OPTEE_TA_SCP03
+static u32 pta_scp03_open_session(struct udevice *dev, uint num_params,
+                                 struct tee_param *params)
+{
+       /*
+        * We don't expect additional parameters when opening a session to
+        * this TA.
+        */
+       return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
+                           TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
+                           num_params, params);
+}
+
+static u32 pta_scp03_invoke_func(struct udevice *dev, u32 func, uint num_params,
+                                struct tee_param *params)
+{
+       u32 res;
+       static bool enabled;
+
+       switch (func) {
+       case PTA_CMD_ENABLE_SCP03:
+               res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
+                                  TEE_PARAM_ATTR_TYPE_NONE,
+                                  TEE_PARAM_ATTR_TYPE_NONE,
+                                  TEE_PARAM_ATTR_TYPE_NONE,
+                                  num_params, params);
+               if (res)
+                       return res;
+
+               if (!enabled) {
+                       enabled = true;
+               } else {
+               }
+
+               if (params[0].u.value.a)
+
+               return TEE_SUCCESS;
+       default:
+               return TEE_ERROR_NOT_SUPPORTED;
+       }
+}
+#endif
 
 #ifdef CONFIG_OPTEE_TA_AVB
 static u32 ta_avb_open_session(struct udevice *dev, uint num_params,
@@ -357,6 +403,12 @@ static const struct ta_entry ta_entries[] = {
          .invoke_func = ta_rpc_test_invoke_func,
        },
 #endif
+#ifdef CONFIG_OPTEE_TA_SCP03
+       { .uuid = PTA_SCP03_UUID,
+         .open_session = pta_scp03_open_session,
+         .invoke_func = pta_scp03_invoke_func,
+       },
+#endif
 };
 
 static void sandbox_tee_get_version(struct udevice *dev,
index 2075cd4..c846bfb 100644 (file)
@@ -38,7 +38,8 @@ static int sandbox_timer_probe(struct udevice *dev)
 {
        struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 
-       if (dev_read_bool(dev, "sandbox,timebase-frequency-fallback"))
+       if (CONFIG_IS_ENABLED(CPU) &&
+           dev_read_bool(dev, "sandbox,timebase-frequency-fallback"))
                return timer_timebase_fallback(dev);
        else if (!uc_priv->clock_rate)
                uc_priv->clock_rate = SANDBOX_TIMER_RATE;
index 6f00a5d..73b4a5c 100644 (file)
@@ -83,11 +83,7 @@ static int timer_post_probe(struct udevice *dev)
        return 0;
 }
 
-/*
- * TODO: should be CONFIG_IS_ENABLED(CPU), but the SPL config has _SUPPORT on
- * the end...
- */
-#if defined(CONFIG_CPU) || defined(CONFIG_SPL_CPU_SUPPORT)
+#if CONFIG_IS_ENABLED(CPU)
 int timer_timebase_fallback(struct udevice *dev)
 {
        struct udevice *cpu;
index 8f075b9..f64d200 100644 (file)
@@ -10,7 +10,7 @@ obj-$(CONFIG_TPM_TIS_SANDBOX) += tpm_tis_sandbox.o
 obj-$(CONFIG_TPM_ST33ZP24_I2C) += tpm_tis_st33zp24_i2c.o
 obj-$(CONFIG_TPM_ST33ZP24_SPI) += tpm_tis_st33zp24_spi.o
 
-obj-$(CONFIG_TPM2_CR50_I2C) += cr50_i2c.o
+obj-$(CONFIG_$(SPL_TPL_)TPM2_CR50_I2C) += cr50_i2c.o
 obj-$(CONFIG_TPM2_TIS_SANDBOX) += tpm2_tis_sandbox.o
 obj-$(CONFIG_TPM2_TIS_SPI) += tpm2_tis_spi.o
 obj-$(CONFIG_TPM2_FTPM_TEE) += tpm2_ftpm_tee.o
index b103a6f..76432bd 100644 (file)
@@ -309,7 +309,7 @@ static int cr50_i2c_recv(struct udevice *dev, u8 *buf, size_t buf_len)
        int status;
        int ret;
 
-       log_debug("%s: len=%x\n", __func__, buf_len);
+       log_debug("%s: buf_len=%x\n", __func__, buf_len);
        if (buf_len < TPM_HEADER_SIZE)
                return -E2BIG;
 
@@ -386,7 +386,7 @@ static int cr50_i2c_send(struct udevice *dev, const u8 *buf, size_t len)
        ulong timeout;
        int ret;
 
-       log_debug("%s: len=%x\n", __func__, len);
+       log_debug("len=%x\n", len);
        timeout = timer_get_us() + TIMEOUT_LONG_US;
        do {
                ret = cr50_i2c_status(dev);
index beb0fa3..35774a6 100644 (file)
@@ -4,6 +4,8 @@
  * Written by Simon Glass <sjg@chromium.org>
  */
 
+#define LOG_CATEGORY UCLASS_TPM
+
 #include <common.h>
 #include <dm.h>
 #include <log.h>
@@ -87,15 +89,15 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size,
        ordinal = get_unaligned_be32(sendbuf + TPM_CMD_ORDINAL_BYTE);
 
        if (count == 0) {
-               debug("no data\n");
+               log_debug("no data\n");
                return -ENODATA;
        }
        if (count > send_size) {
-               debug("invalid count value %x %zx\n", count, send_size);
+               log_debug("invalid count value %x %zx\n", count, send_size);
                return -E2BIG;
        }
 
-       debug("%s: Calling send\n", __func__);
+       log_debug("%s: Calling send\n", __func__);
        ret = ops->send(dev, sendbuf, send_size);
        if (ret < 0)
                return ret;
index c74bacf..24c804a 100644 (file)
@@ -285,7 +285,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
        length = get_unaligned_be32(sent);
        sent += sizeof(length);
        if (length != send_size) {
-               printf("TPM2: Unmatching length, received: %ld, expected: %d\n",
+               printf("TPM2: Unmatching length, received: %zd, expected: %d\n",
                       send_size, length);
                rc = TPM2_RC_SIZE;
                sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
index 667157c..63ae2ba 100644 (file)
@@ -241,7 +241,7 @@ config VIDCONSOLE_AS_NAME
 
 config VIDEO_COREBOOT
        bool "Enable coreboot framebuffer driver support"
-       depends on X86 && SYS_COREBOOT
+       depends on X86
        help
          Turn on this option to enable a framebuffer driver when U-Boot is
          loaded by coreboot where the graphics device is configured by
index 0a5fb08..7237542 100644 (file)
@@ -5,9 +5,10 @@
 
 #include <common.h>
 #include <dm.h>
+#include <init.h>
 #include <vbe.h>
 #include <video.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 
 static int save_vesa_mode(struct cb_framebuffer *fb,
                          struct vesa_mode_info *vesa)
@@ -17,7 +18,7 @@ static int save_vesa_mode(struct cb_framebuffer *fb,
         * running on the serial console.
         */
        if (!fb)
-               return -ENXIO;
+               return log_msg_ret("save", -ENXIO);
 
        vesa->x_resolution = fb->x_resolution;
        vesa->y_resolution = fb->y_resolution;
@@ -44,16 +45,23 @@ static int coreboot_video_probe(struct udevice *dev)
        struct vesa_mode_info *vesa = &mode_info.vesa;
        int ret;
 
+       if (ll_boot_init())
+               return log_msg_ret("ll", -ENODEV);
+
        printf("Video: ");
 
        /* Initialize vesa_mode_info structure */
        ret = save_vesa_mode(fb, vesa);
-       if (ret)
+       if (ret) {
+               ret = log_msg_ret("save", ret);
                goto err;
+       }
 
        ret = vbe_setup_video_priv(vesa, uc_priv, plat);
-       if (ret)
+       if (ret) {
+               ret = log_msg_ret("setup", ret);
                goto err;
+       }
 
        printf("%dx%dx%d\n", uc_priv->xsize, uc_priv->ysize,
               vesa->bits_per_pixel);
@@ -61,7 +69,7 @@ static int coreboot_video_probe(struct udevice *dev)
        return 0;
 
 err:
-       printf("No video mode configured in coreboot!\n");
+       printf("No video mode configured in coreboot (err=%d)\n", ret);
        return ret;
 }
 
index f52aba4..4361a58 100644 (file)
@@ -7,6 +7,8 @@
  */
 
 #include <common.h>
+#include <display.h>
+#include <dm.h>
 #include <cpu_func.h>
 #include <efi_loader.h>
 #include <init.h>
@@ -28,7 +30,9 @@
 #include <fdt_support.h>
 #include <i2c.h>
 #include <malloc.h>
+#include <video.h>
 #include <video_fb.h>
+#include <dm/uclass-internal.h>
 #include "../videomodes.h"
 #include "../anx9804.h"
 #include "../hitachi_tx18d42vm_lcd.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* Maximum LCD size we support */
+#define LCD_MAX_WIDTH          3840
+#define LCD_MAX_HEIGHT         2160
+#define LCD_MAX_LOG2_BPP       VIDEO_BPP32
+
 enum sunxi_monitor {
        sunxi_monitor_none,
        sunxi_monitor_dvi,
@@ -58,13 +67,12 @@ enum sunxi_monitor {
 };
 #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
 
-struct sunxi_display {
-       GraphicDevice graphic_device;
+struct sunxi_display_priv {
        enum sunxi_monitor monitor;
        unsigned int depth;
        unsigned int fb_addr;
        unsigned int fb_size;
-} sunxi_display;
+};
 
 const struct ctfb_res_modes composite_video_modes[2] = {
        /*  x     y  hz  pixclk ps/kHz   le   ri  up  lo   hs vs  s  vmode */
@@ -214,7 +222,8 @@ static int sunxi_hdmi_edid_get_block(int block, u8 *buf)
        return r;
 }
 
-static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode,
+static int sunxi_hdmi_edid_get_mode(struct sunxi_display_priv *sunxi_display,
+                                   struct ctfb_res_modes *mode,
                                    bool verbose_mode)
 {
        struct edid1_info edid1;
@@ -291,14 +300,14 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode,
        }
 
        /* Check for basic audio support, if found enable hdmi output */
-       sunxi_display.monitor = sunxi_monitor_dvi;
+       sunxi_display->monitor = sunxi_monitor_dvi;
        for (i = 0; i < ext_blocks; i++) {
                if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG ||
                    cea681[i].revision < 2)
                        continue;
 
                if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
-                       sunxi_display.monitor = sunxi_monitor_hdmi;
+                       sunxi_display->monitor = sunxi_monitor_hdmi;
        }
 
        return 0;
@@ -414,9 +423,9 @@ static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
 static void sunxi_frontend_enable(void) {}
 #endif
 
-static bool sunxi_is_composite(void)
+static bool sunxi_is_composite(enum sunxi_monitor monitor)
 {
-       switch (sunxi_display.monitor) {
+       switch (monitor) {
        case sunxi_monitor_none:
        case sunxi_monitor_dvi:
        case sunxi_monitor_hdmi:
@@ -473,7 +482,8 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
 };
 
 static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
-                                   unsigned int address)
+                                   unsigned int address,
+                                   enum sunxi_monitor monitor)
 {
        struct sunxi_de_be_reg * const de_be =
                (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
@@ -502,7 +512,7 @@ static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
 #endif
                             SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
 
-       if (sunxi_is_composite()) {
+       if (sunxi_is_composite(monitor)) {
                writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
                       &de_be->output_color_ctrl);
                for (i = 0; i < 12; i++)
@@ -616,7 +626,8 @@ static void sunxi_lcdc_backlight_enable(void)
                gpio_direction_output(pin, PWM_ON);
 }
 
-static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
+static void sunxi_lcdc_tcon0_mode_set(struct sunxi_display_priv *sunxi_display,
+                                     const struct ctfb_res_modes *mode,
                                      bool for_ext_vga_dac)
 {
        struct sunxi_lcdc_reg * const lcdc =
@@ -643,17 +654,18 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
        }
 
        lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double,
-                    sunxi_is_composite());
+                    sunxi_is_composite(sunxi_display->monitor));
 
        video_ctfb_mode_to_display_timing(mode, &timing);
        lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
-                           sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
+                           sunxi_display->depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
 }
 
 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
                                      int *clk_div, int *clk_double,
-                                     bool use_portd_hvsync)
+                                     bool use_portd_hvsync,
+                                     enum sunxi_monitor monitor)
 {
        struct sunxi_lcdc_reg * const lcdc =
                (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
@@ -663,7 +675,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
 
        video_ctfb_mode_to_display_timing(mode, &timing);
        lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync,
-                           sunxi_is_composite());
+                           sunxi_is_composite(monitor));
 
        if (use_portd_hvsync) {
                sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
@@ -671,7 +683,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
        }
 
        lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double,
-                    sunxi_is_composite());
+                    sunxi_is_composite(monitor));
 }
 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
 
@@ -725,7 +737,8 @@ static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
 }
 
 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
-                               int clk_div, int clk_double)
+                               int clk_div, int clk_double,
+                               enum sunxi_monitor monitor)
 {
        struct sunxi_hdmi_reg * const hdmi =
                (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
@@ -734,7 +747,7 @@ static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
        /* Write clear interrupt status bits */
        writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
 
-       if (sunxi_display.monitor == sunxi_monitor_hdmi)
+       if (monitor == sunxi_monitor_hdmi)
                sunxi_hdmi_setup_info_frames(mode);
 
        /* Set input sync enable */
@@ -789,7 +802,7 @@ static void sunxi_hdmi_enable(void)
 
 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
 
-static void sunxi_tvencoder_mode_set(void)
+static void sunxi_tvencoder_mode_set(enum sunxi_monitor monitor)
 {
        struct sunxi_ccm_reg * const ccm =
                (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
@@ -801,7 +814,7 @@ static void sunxi_tvencoder_mode_set(void)
        /* Clock on */
        setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
 
-       switch (sunxi_display.monitor) {
+       switch (monitor) {
        case sunxi_monitor_vga:
                tvencoder_mode_set(tve, tve_mode_vga);
                break;
@@ -896,26 +909,28 @@ static void sunxi_engines_init(void)
        sunxi_drc_init();
 }
 
-static void sunxi_mode_set(const struct ctfb_res_modes *mode,
+static void sunxi_mode_set(struct sunxi_display_priv *sunxi_display,
+                          const struct ctfb_res_modes *mode,
                           unsigned int address)
 {
+       enum sunxi_monitor monitor = sunxi_display->monitor;
        int __maybe_unused clk_div, clk_double;
        struct sunxi_lcdc_reg * const lcdc =
                (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
        struct sunxi_tve_reg * __maybe_unused const tve =
                (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
 
-       switch (sunxi_display.monitor) {
+       switch (sunxi_display->monitor) {
        case sunxi_monitor_none:
                break;
        case sunxi_monitor_dvi:
        case sunxi_monitor_hdmi:
 #ifdef CONFIG_VIDEO_HDMI
-               sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
-               sunxi_hdmi_mode_set(mode, clk_div, clk_double);
+               sunxi_composer_mode_set(mode, address, monitor);
+               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
+               sunxi_hdmi_mode_set(mode, clk_div, clk_double, monitor);
                sunxi_composer_enable();
-               lcdc_enable(lcdc, sunxi_display.depth);
+               lcdc_enable(lcdc, sunxi_display->depth);
                sunxi_hdmi_enable();
 #endif
                break;
@@ -930,7 +945,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
                        axp_set_eldo(3, 1800);
                        anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
                                     ANX9804_DATA_RATE_1620M,
-                                    sunxi_display.depth);
+                                    sunxi_display->depth);
                }
                if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
                        mdelay(50); /* Wait for lcd controller power on */
@@ -942,10 +957,10 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
                        i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
                        i2c_set_bus_num(orig_i2c_bus);
                }
-               sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon0_mode_set(mode, false);
+               sunxi_composer_mode_set(mode, address, monitor);
+               sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, false);
                sunxi_composer_enable();
-               lcdc_enable(lcdc, sunxi_display.depth);
+               lcdc_enable(lcdc, sunxi_display->depth);
 #ifdef CONFIG_VIDEO_LCD_SSD2828
                sunxi_ssd2828_init(mode);
 #endif
@@ -953,17 +968,17 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
                break;
        case sunxi_monitor_vga:
 #ifdef CONFIG_VIDEO_VGA
-               sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
-               sunxi_tvencoder_mode_set();
+               sunxi_composer_mode_set(mode, address, monitor);
+               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1, monitor);
+               sunxi_tvencoder_mode_set(monitor);
                sunxi_composer_enable();
-               lcdc_enable(lcdc, sunxi_display.depth);
+               lcdc_enable(lcdc, sunxi_display->depth);
                tvencoder_enable(tve);
 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
-               sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon0_mode_set(mode, true);
+               sunxi_composer_mode_set(mode, address, monitor);
+               sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, true);
                sunxi_composer_enable();
-               lcdc_enable(lcdc, sunxi_display.depth);
+               lcdc_enable(lcdc, sunxi_display->depth);
                sunxi_vga_external_dac_enable();
 #endif
                break;
@@ -972,11 +987,11 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
        case sunxi_monitor_composite_pal_m:
        case sunxi_monitor_composite_pal_nc:
 #ifdef CONFIG_VIDEO_COMPOSITE
-               sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
-               sunxi_tvencoder_mode_set();
+               sunxi_composer_mode_set(mode, address, monitor);
+               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
+               sunxi_tvencoder_mode_set(monitor);
                sunxi_composer_enable();
-               lcdc_enable(lcdc, sunxi_display.depth);
+               lcdc_enable(lcdc, sunxi_display->depth);
                tvencoder_enable(tve);
 #endif
                break;
@@ -999,11 +1014,6 @@ static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
        }
 }
 
-ulong board_get_usable_ram_top(ulong total_size)
-{
-       return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
-}
-
 static bool sunxi_has_hdmi(void)
 {
 #ifdef CONFIG_VIDEO_HDMI
@@ -1052,9 +1062,11 @@ static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
                return sunxi_monitor_none;
 }
 
-void *video_hw_init(void)
+static int sunxi_de_probe(struct udevice *dev)
 {
-       static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
+       struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+       struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+       struct sunxi_display_priv *sunxi_display = dev_get_priv(dev);
        const struct ctfb_res_modes *mode;
        struct ctfb_res_modes custom;
        const char *options;
@@ -1067,10 +1079,8 @@ void *video_hw_init(void)
        char mon[16];
        char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
 
-       memset(&sunxi_display, 0, sizeof(struct sunxi_display));
-
        video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
-                                &sunxi_display.depth, &options);
+                                &sunxi_display->depth, &options);
 #ifdef CONFIG_VIDEO_HDMI
        hpd = video_get_option_int(options, "hpd", 1);
        hpd_delay = video_get_option_int(options, "hpd_delay", 500);
@@ -1078,35 +1088,35 @@ void *video_hw_init(void)
 #endif
        overscan_x = video_get_option_int(options, "overscan_x", -1);
        overscan_y = video_get_option_int(options, "overscan_y", -1);
-       sunxi_display.monitor = sunxi_get_default_mon(true);
+       sunxi_display->monitor = sunxi_get_default_mon(true);
        video_get_option_string(options, "monitor", mon, sizeof(mon),
-                               sunxi_get_mon_desc(sunxi_display.monitor));
+                               sunxi_get_mon_desc(sunxi_display->monitor));
        for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
                if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
-                       sunxi_display.monitor = i;
+                       sunxi_display->monitor = i;
                        break;
                }
        }
        if (i > SUNXI_MONITOR_LAST)
                printf("Unknown monitor: '%s', falling back to '%s'\n",
-                      mon, sunxi_get_mon_desc(sunxi_display.monitor));
+                      mon, sunxi_get_mon_desc(sunxi_display->monitor));
 
 #ifdef CONFIG_VIDEO_HDMI
        /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
-       if (sunxi_display.monitor == sunxi_monitor_dvi ||
-           sunxi_display.monitor == sunxi_monitor_hdmi) {
+       if (sunxi_display->monitor == sunxi_monitor_dvi ||
+           sunxi_display->monitor == sunxi_monitor_hdmi) {
                /* Always call hdp_detect, as it also enables clocks, etc. */
                hdmi_present = (sunxi_hdmi_hpd_detect(hpd_delay) == 1);
                if (hdmi_present && edid) {
                        printf("HDMI connected: ");
-                       if (sunxi_hdmi_edid_get_mode(&custom, true) == 0)
+                       if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, true) == 0)
                                mode = &custom;
                        else
                                hdmi_present = false;
                }
                /* Fall back to EDID in case HPD failed */
                if (edid && !hdmi_present) {
-                       if (sunxi_hdmi_edid_get_mode(&custom, false) == 0) {
+                       if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, false) == 0) {
                                mode = &custom;
                                hdmi_present = true;
                        }
@@ -1114,38 +1124,39 @@ void *video_hw_init(void)
                /* Shut down when display was not found */
                if ((hpd || edid) && !hdmi_present) {
                        sunxi_hdmi_shutdown();
-                       sunxi_display.monitor = sunxi_get_default_mon(false);
+                       sunxi_display->monitor = sunxi_get_default_mon(false);
                } /* else continue with hdmi/dvi without a cable connected */
        }
 #endif
 
-       switch (sunxi_display.monitor) {
+       switch (sunxi_display->monitor) {
        case sunxi_monitor_none:
-               return NULL;
+               printf("Unknown monitor\n");
+               return -EINVAL;
        case sunxi_monitor_dvi:
        case sunxi_monitor_hdmi:
                if (!sunxi_has_hdmi()) {
                        printf("HDMI/DVI not supported on this board\n");
-                       sunxi_display.monitor = sunxi_monitor_none;
-                       return NULL;
+                       sunxi_display->monitor = sunxi_monitor_none;
+                       return -EINVAL;
                }
                break;
        case sunxi_monitor_lcd:
                if (!sunxi_has_lcd()) {
                        printf("LCD not supported on this board\n");
-                       sunxi_display.monitor = sunxi_monitor_none;
-                       return NULL;
+                       sunxi_display->monitor = sunxi_monitor_none;
+                       return -EINVAL;
                }
-               sunxi_display.depth = video_get_params(&custom, lcd_mode);
+               sunxi_display->depth = video_get_params(&custom, lcd_mode);
                mode = &custom;
                break;
        case sunxi_monitor_vga:
                if (!sunxi_has_vga()) {
                        printf("VGA not supported on this board\n");
-                       sunxi_display.monitor = sunxi_monitor_none;
-                       return NULL;
+                       sunxi_display->monitor = sunxi_monitor_none;
+                       return -EINVAL;
                }
-               sunxi_display.depth = 18;
+               sunxi_display->depth = 18;
                break;
        case sunxi_monitor_composite_pal:
        case sunxi_monitor_composite_ntsc:
@@ -1153,85 +1164,99 @@ void *video_hw_init(void)
        case sunxi_monitor_composite_pal_nc:
                if (!sunxi_has_composite()) {
                        printf("Composite video not supported on this board\n");
-                       sunxi_display.monitor = sunxi_monitor_none;
-                       return NULL;
+                       sunxi_display->monitor = sunxi_monitor_none;
+                       return -EINVAL;
                }
-               if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
-                   sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
+               if (sunxi_display->monitor == sunxi_monitor_composite_pal ||
+                   sunxi_display->monitor == sunxi_monitor_composite_pal_nc)
                        mode = &composite_video_modes[0];
                else
                        mode = &composite_video_modes[1];
-               sunxi_display.depth = 24;
+               sunxi_display->depth = 24;
                break;
        }
 
        /* Yes these defaults are quite high, overscan on composite sucks... */
        if (overscan_x == -1)
-               overscan_x = sunxi_is_composite() ? 32 : 0;
+               overscan_x = sunxi_is_composite(sunxi_display->monitor) ? 32 : 0;
        if (overscan_y == -1)
-               overscan_y = sunxi_is_composite() ? 20 : 0;
+               overscan_y = sunxi_is_composite(sunxi_display->monitor) ? 20 : 0;
 
-       sunxi_display.fb_size =
-               (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
+       sunxi_display->fb_size = plat->size;
        overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
        /* We want to keep the fb_base for simplefb page aligned, where as
         * the sunxi dma engines will happily accept an unaligned address. */
        if (overscan_offset)
-               sunxi_display.fb_size += 0x1000;
-
-       if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
-               printf("Error need %dkB for fb, but only %dkB is reserved\n",
-                      sunxi_display.fb_size >> 10,
-                      CONFIG_SUNXI_MAX_FB_SIZE >> 10);
-               return NULL;
-       }
+               sunxi_display->fb_size += 0x1000;
 
        printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
               mode->xres, mode->yres,
               (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
-              sunxi_get_mon_desc(sunxi_display.monitor),
+              sunxi_get_mon_desc(sunxi_display->monitor),
               overscan_x, overscan_y);
 
-       gd->fb_base = gd->bd->bi_dram[0].start +
-                     gd->bd->bi_dram[0].size - sunxi_display.fb_size;
+       sunxi_display->fb_addr = plat->base;
        sunxi_engines_init();
 
 #ifdef CONFIG_EFI_LOADER
-       efi_add_memory_map(gd->fb_base, sunxi_display.fb_size,
+       efi_add_memory_map(sunxi_display->fb_addr, sunxi_display->fb_size,
                           EFI_RESERVED_MEMORY_TYPE);
 #endif
 
-       fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
-       sunxi_display.fb_addr = gd->fb_base;
+       fb_dma_addr = sunxi_display->fb_addr - CONFIG_SYS_SDRAM_BASE;
        if (overscan_offset) {
                fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
-               sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
-               memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
-               flush_cache(gd->fb_base, sunxi_display.fb_size);
+               sunxi_display->fb_addr += ALIGN(overscan_offset, 0x1000);
+               memset((void *)sunxi_display->fb_addr, 0, sunxi_display->fb_size);
+               flush_cache(sunxi_display->fb_addr, sunxi_display->fb_size);
        }
-       sunxi_mode_set(mode, fb_dma_addr);
+       sunxi_mode_set(sunxi_display, mode, fb_dma_addr);
 
-       /*
-        * These are the only members of this structure that are used. All the
-        * others are driver specific. The pitch is stored in plnSizeX.
-        */
-       graphic_device->frameAdrs = sunxi_display.fb_addr;
-       graphic_device->gdfIndex = GDF_32BIT_X888RGB;
-       graphic_device->gdfBytesPP = 4;
-       graphic_device->winSizeX = mode->xres - 2 * overscan_x;
-       graphic_device->winSizeY = mode->yres - 2 * overscan_y;
-       graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
-
-       return graphic_device;
+       /* The members of struct video_priv to be set by the driver. */
+       uc_priv->bpix = VIDEO_BPP32;
+       uc_priv->xsize = mode->xres;
+       uc_priv->ysize = mode->yres;
+
+       video_set_flush_dcache(dev, true);
+
+       return 0;
 }
 
+static int sunxi_de_bind(struct udevice *dev)
+{
+       struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+
+       plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * VNBYTES(LCD_MAX_LOG2_BPP);
+
+       return 0;
+}
+
+static const struct video_ops sunxi_de_ops = {
+};
+
+U_BOOT_DRIVER(sunxi_de) = {
+       .name   = "sunxi_de",
+       .id     = UCLASS_VIDEO,
+       .ops    = &sunxi_de_ops,
+       .bind   = sunxi_de_bind,
+       .probe  = sunxi_de_probe,
+       .priv_auto = sizeof(struct sunxi_display_priv),
+       .flags  = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRVINFO(sunxi_de) = {
+       .name = "sunxi_de"
+};
+
 /*
  * Simplefb support.
  */
 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
 int sunxi_simplefb_setup(void *blob)
 {
-       static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
+       struct sunxi_display_priv *sunxi_display;
+       struct video_priv *uc_priv;
+       struct udevice *de;
        int offset, ret;
        u64 start, size;
        const char *pipeline = NULL;
@@ -1242,7 +1267,19 @@ int sunxi_simplefb_setup(void *blob)
 #define PIPELINE_PREFIX
 #endif
 
-       switch (sunxi_display.monitor) {
+       ret = uclass_find_device_by_name(UCLASS_VIDEO, "sunxi_de", &de);
+       if (ret) {
+               printf("DE not present\n");
+               return 0;
+       } else if (!device_active(de)) {
+               printf("DE is present but not probed\n");
+               return 0;
+       }
+
+       uc_priv = dev_get_uclass_priv(de);
+       sunxi_display = dev_get_priv(de);
+
+       switch (sunxi_display->monitor) {
        case sunxi_monitor_none:
                return 0;
        case sunxi_monitor_dvi:
@@ -1280,16 +1317,17 @@ int sunxi_simplefb_setup(void *blob)
         * linux/arch/arm/mm/ioremap.c around line 301.
         */
        start = gd->bd->bi_dram[0].start;
-       size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
+       size = sunxi_display->fb_addr - start;
        ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
        if (ret) {
                eprintf("Cannot setup simplefb: Error reserving memory\n");
                return ret;
        }
 
-       ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
-                       graphic_device->winSizeX, graphic_device->winSizeY,
-                       graphic_device->plnSizeX, "x8r8g8b8");
+       ret = fdt_setup_simplefb_node(blob, offset, sunxi_display->fb_addr,
+                                     uc_priv->xsize, uc_priv->ysize,
+                                     VNBYTES(uc_priv->bpix) * uc_priv->xsize,
+                                     "x8r8g8b8");
        if (ret)
                eprintf("Cannot setup simplefb: Error setting properties\n");
 
index 5e0a096..3586246 100644 (file)
@@ -44,7 +44,7 @@ static void imx_watchdog_expire_now(struct watchdog_regs *wdog, bool ext_reset)
 
 #if !defined(CONFIG_IMX_WATCHDOG) || \
     (defined(CONFIG_IMX_WATCHDOG) && !CONFIG_IS_ENABLED(WDT))
-void __attribute__((weak)) reset_cpu(ulong addr)
+void __attribute__((weak)) reset_cpu(void)
 {
        struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
 
index 7533fc6..6f63b11 100644 (file)
@@ -77,7 +77,7 @@ void hw_watchdog_init(void)
        hw_watchdog_reset();
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
        struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
 
index 00ac29a..99ce75e 100644 (file)
@@ -338,6 +338,7 @@ config SPL_OF_PLATDATA
        bool "Generate platform data for use in SPL"
        depends on SPL_OF_CONTROL
        select DTOC
+       select SPL_OF_PLATDATA_DRIVER_RT if !SPL_OF_PLATDATA_INST
        help
          For very constrained SPL environments the overhead of decoding
          device tree nodes and converting their contents into platform data
@@ -355,19 +356,58 @@ config SPL_OF_PLATDATA
          compatible string, then adding platform data and U_BOOT_DRVINFO
          declarations for each node. See of-plat.txt for more information.
 
+if SPL_OF_PLATDATA
+
 config SPL_OF_PLATDATA_PARENT
        bool "Support parent information in devices"
-       depends on SPL_OF_PLATDATA
        default y
        help
          Generally it is useful to be able to access the parent of a device
          with of-platdata. To save space this can be disabled, but in that
          case dev_get_parent() will always return NULL;
 
+config SPL_OF_PLATDATA_INST
+       bool "Declare devices at build time"
+       help
+         Declare devices as udevice instances so that they do not need to be
+         bound when U-Boot starts. This can save time and code space.
+
+config SPL_OF_PLATDATA_NO_BIND
+       bool "Don't allow run-time binding of devices"
+       depends on SPL_OF_PLATDATA_INST
+       default y
+       help
+         This removes the ability to bind devices at run time, thus saving
+         some code space in U-Boot. This can be disabled if binding is needed,
+         at the code of some code size increase.
+
+config SPL_OF_PLATDATA_RT
+       bool "Use a separate struct for device runtime data"
+       depends on SPL_OF_PLATDATA_INST
+       default y
+       help
+         For systems running SPL from read-only memory it is convenient to
+         separate out the runtime information, so that the devices don't need
+         to be copied before being used. This moves the read-write parts of
+         struct udevice (at present just the flags) into a separate struct,
+         which is allocated at runtime.
+
+config SPL_OF_PLATDATA_DRIVER_RT
+       bool
+       help
+         Use a separate struct for driver runtime data.
+
+         This enables the driver_rt information, used with of-platdata when
+         of-platdata-inst is not used. It allows finding devices by their
+         driver data.
+
+endif
+
 config TPL_OF_PLATDATA
        bool "Generate platform data for use in TPL"
        depends on TPL_OF_CONTROL
        select DTOC
+       select TPL_OF_PLATDATA_DRIVER_RT if !TPL_OF_PLATDATA_INST
        help
          For very constrained SPL environments the overhead of decoding
          device tree nodes and converting their contents into platform data
@@ -385,13 +425,52 @@ config TPL_OF_PLATDATA
          compatible string, then adding platform data and U_BOOT_DRVINFO
          declarations for each node. See of-plat.txt for more information.
 
+if TPL_OF_PLATDATA
+
 config TPL_OF_PLATDATA_PARENT
        bool "Support parent information in devices"
-       depends on TPL_OF_PLATDATA
        default y
        help
          Generally it is useful to be able to access the parent of a device
          with of-platdata. To save space this can be disabled, but in that
          case dev_get_parent() will always return NULL;
 
+config TPL_OF_PLATDATA_INST
+       bool "Declare devices at build time"
+
+       help
+         Declare devices as udevice instances so that they do not need to be
+         bound when U-Boot starts. This can save time and code space.
+
+config TPL_OF_PLATDATA_NO_BIND
+       bool "Don't allow run-time binding of devices"
+       depends on TPL_OF_PLATDATA_INST
+       default y
+       help
+         This removes the ability to bind devices at run time, thus saving
+         some code space in U-Boot. This can be disabled if binding is needed,
+         at the code of some code size increase.
+
+config TPL_OF_PLATDATA_RT
+       bool "Use a separate struct for device runtime data"
+       depends on TPL_OF_PLATDATA_INST
+       default y
+       help
+         For systems running TPL from read-only memory it is convenient to
+         separate out the runtime information, so that the devices don't need
+         to be copied before being used. This moves the read-write parts of
+         struct udevice (at present just the flags) into a separate struct,
+         which is allocated at runtime.
+
+config TPL_OF_PLATDATA_DRIVER_RT
+       bool
+       help
+         Use a separate struct for driver runtime data.
+
+         This enables the driver_rt information, used with of-platdata when
+         of-platdata-inst is not used. It allows finding devices by their
+         driver data.
+
+endif
+
 endmenu
index 9007aa7..415ea28 100644 (file)
@@ -79,6 +79,57 @@ static void swap_file_header(struct cbfs_fileheader *dest,
        dest->offset = be32_to_cpu(src->offset);
 }
 
+/**
+ * fill_node() - Fill a node struct with information from the CBFS
+ *
+ * @node: Node to fill
+ * @start: Pointer to the start of the CBFS file in memory
+ * @header: Pointer to the header information (in our enddianess)
+ * @return 0 if OK, -EBADF if the header is too small
+ */
+static int fill_node(struct cbfs_cachenode *node, void *start,
+                    struct cbfs_fileheader *header)
+{
+       uint name_len;
+       uint offset;
+
+       /* Check the header is large enough */
+       if (header->offset < sizeof(struct cbfs_fileheader))
+               return -EBADF;
+
+       node->next = NULL;
+       node->type = header->type;
+       node->data = start + header->offset;
+       node->data_length = header->len;
+       name_len = header->offset - sizeof(struct cbfs_fileheader);
+       node->name = start + sizeof(struct cbfs_fileheader);
+       node->name_length = name_len;
+       node->attr_offset = header->attributes_offset;
+       node->comp_algo = CBFS_COMPRESS_NONE;
+       node->decomp_size = 0;
+
+       for (offset = node->attr_offset; offset < header->offset;) {
+               const struct cbfs_file_attribute *attr;
+               uint tag, len;
+
+               attr = start + offset;
+               tag = be32_to_cpu(attr->tag);
+               len = be32_to_cpu(attr->len);
+               if (tag == CBFS_FILE_ATTR_TAG_COMPRESSION) {
+                       struct cbfs_file_attr_compression *comp;
+
+                       comp = start + offset;
+                       node->comp_algo = be32_to_cpu(comp->compression);
+                       node->decomp_size =
+                               be32_to_cpu(comp->decompressed_size);
+               }
+
+               offset += len;
+       }
+
+       return 0;
+}
+
 /*
  * Given a starting position in memory, scan forward, bounded by a size, and
  * find the next valid CBFS file. No memory is allocated by this function. The
@@ -87,7 +138,7 @@ static void swap_file_header(struct cbfs_fileheader *dest,
  * @param start                The location in memory to start from.
  * @param size         The size of the memory region to search.
  * @param align                The alignment boundaries to check on.
- * @param new_node     A pointer to the file structure to load.
+ * @param node A pointer to the file structure to load.
  * @param used         A pointer to the count of of bytes scanned through,
  *                     including the file if one is found.
  *
@@ -95,7 +146,7 @@ static void swap_file_header(struct cbfs_fileheader *dest,
  *     is found.
  */
 static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size,
-                              int align, struct cbfs_cachenode *new_node,
+                              int align, struct cbfs_cachenode *node,
                               int *used)
 {
        struct cbfs_fileheader header;
@@ -104,8 +155,7 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size,
 
        while (size >= align) {
                const struct cbfs_fileheader *file_header = start;
-               u32 name_len;
-               u32 step;
+               int ret;
 
                /* Check if there's a file here. */
                if (memcmp(good_file_magic, &file_header->magic,
@@ -117,25 +167,13 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size,
                }
 
                swap_file_header(&header, file_header);
-               if (header.offset < sizeof(struct cbfs_fileheader)) {
+               ret = fill_node(node, start, &header);
+               if (ret) {
                        priv->result = CBFS_BAD_FILE;
-                       return -EBADF;
+                       return log_msg_ret("fill", ret);
                }
-               new_node->next = NULL;
-               new_node->type = header.type;
-               new_node->data = start + header.offset;
-               new_node->data_length = header.len;
-               name_len = header.offset - sizeof(struct cbfs_fileheader);
-               new_node->name = (char *)file_header +
-                               sizeof(struct cbfs_fileheader);
-               new_node->name_length = name_len;
-               new_node->attributes_offset = header.attributes_offset;
-
-               step = header.len;
-               if (step % align)
-                       step = step + align - step % align;
-
-               *used += step;
+
+               *used += ALIGN(header.len, align);
                return 0;
        }
 
@@ -146,7 +184,7 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size,
 static int file_cbfs_fill_cache(struct cbfs_priv *priv, int size, int align)
 {
        struct cbfs_cachenode *cache_node;
-       struct cbfs_cachenode *new_node;
+       struct cbfs_cachenode *node;
        struct cbfs_cachenode **cache_tail = &priv->file_cache;
        void *start;
 
@@ -164,21 +202,20 @@ static int file_cbfs_fill_cache(struct cbfs_priv *priv, int size, int align)
                int used;
                int ret;
 
-               new_node = (struct cbfs_cachenode *)
-                               malloc(sizeof(struct cbfs_cachenode));
-               if (!new_node)
+               node = malloc(sizeof(struct cbfs_cachenode));
+               if (!node)
                        return -ENOMEM;
-               ret = file_cbfs_next_file(priv, start, size, align, new_node,
+               ret = file_cbfs_next_file(priv, start, size, align, node,
                                          &used);
 
                if (ret < 0) {
-                       free(new_node);
+                       free(node);
                        if (ret == -ENOENT)
                                break;
                        return ret;
                }
-               *cache_tail = new_node;
-               cache_tail = &new_node->next;
+               *cache_tail = node;
+               cache_tail = &node->next;
 
                size -= used;
                start += used;
@@ -276,18 +313,26 @@ int file_cbfs_init(ulong end_of_rom)
        return cbfs_init(&cbfs_s, end_of_rom);
 }
 
-int cbfs_init_mem(ulong base, struct cbfs_priv **privp)
+int cbfs_init_mem(ulong base, ulong size, bool require_hdr,
+                 struct cbfs_priv **privp)
 {
        struct cbfs_priv priv_s, *priv = &priv_s;
        int ret;
 
        /*
-        * Use a local variable to start with until we know that the CBFS is
-        * valid.
+        * Use a local variable to start with until we know that the * CBFS is
+        * valid. Note that size is detected from the header, if present,
+        * meaning the parameter is ignored.
         */
        ret = cbfs_load_header_ptr(priv, base);
-       if (ret)
-               return ret;
+       if (ret) {
+               if (require_hdr || size == CBFS_SIZE_UNKNOWN)
+                       return ret;
+               memset(priv, '\0', sizeof(struct cbfs_priv));
+               priv->header.rom_size = size;
+               priv->header.align = CBFS_ALIGN_SIZE;
+               priv->start = (void *)base;
+       }
 
        ret = file_cbfs_fill_cache(priv, priv->header.rom_size,
                                   priv->header.align);
@@ -317,6 +362,17 @@ const struct cbfs_header *file_cbfs_get_header(void)
        }
 }
 
+const struct cbfs_cachenode *cbfs_get_first(const struct cbfs_priv *priv)
+{
+       return priv->file_cache;
+}
+
+void cbfs_get_next(const struct cbfs_cachenode **filep)
+{
+       if (*filep)
+               *filep = (*filep)->next;
+}
+
 const struct cbfs_cachenode *file_cbfs_get_first(void)
 {
        struct cbfs_priv *priv = &cbfs_s;
index b6a9991..e1a5f4b 100644 (file)
@@ -215,10 +215,20 @@ struct global_data {
         * @uclass_root_s.
         */
        struct list_head *uclass_root;
-# if CONFIG_IS_ENABLED(OF_PLATDATA)
+# if CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT)
        /** @dm_driver_rt: Dynamic info about the driver */
        struct driver_rt *dm_driver_rt;
 # endif
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT)
+       /** @dm_udevice_rt: Dynamic info about the udevice */
+       struct udevice_rt *dm_udevice_rt;
+       /**
+        * @dm_priv_base: Base address of the priv/plat region used when
+        * udevices and uclasses are in read-only memory. This is NULL if not
+        * used
+        */
+       void *dm_priv_base;
+# endif
 #endif
 #ifdef CONFIG_TIMER
        /**
@@ -410,6 +420,12 @@ struct global_data {
         * This value is used as logging level for continuation messages.
         */
        int logl_prev;
+       /**
+        * @log_cont: Previous log line did not finished wtih \n
+        *
+        * This allows for chained log messages on the same line
+        */
+       bool log_cont;
 #endif
 #if CONFIG_IS_ENABLED(BLOBLIST)
        /**
@@ -477,7 +493,7 @@ struct global_data {
 #define gd_set_of_root(_root)
 #endif
 
-#if CONFIG_IS_ENABLED(OF_PLATDATA)
+#if CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT)
 #define gd_set_dm_driver_rt(dyn)       gd->dm_driver_rt = dyn
 #define gd_dm_driver_rt()              gd->dm_driver_rt
 #else
@@ -485,6 +501,18 @@ struct global_data {
 #define gd_dm_driver_rt()              NULL
 #endif
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT)
+#define gd_set_dm_udevice_rt(dyn)      gd->dm_udevice_rt = dyn
+#define gd_dm_udevice_rt()             gd->dm_udevice_rt
+#define gd_set_dm_priv_base(dyn)       gd->dm_priv_base = dyn
+#define gd_dm_priv_base()              gd->dm_priv_base
+#else
+#define gd_set_dm_udevice_rt(dyn)
+#define gd_dm_udevice_rt()             NULL
+#define gd_set_dm_priv_base(dyn)
+#define gd_dm_priv_base()              NULL
+#endif
+
 #ifdef CONFIG_GENERATE_ACPI_TABLE
 #define gd_acpi_ctx()          gd->acpi_ctx
 #else
index 82294cb..2cb0500 100644 (file)
@@ -128,6 +128,12 @@ struct gpio_desc {
 #define GPIOD_PULL_UP          BIT(7)  /* GPIO has pull-up enabled */
 #define GPIOD_PULL_DOWN                BIT(8)  /* GPIO has pull-down enabled */
 
+/* Flags for updating the above */
+#define GPIOD_MASK_DIR         (GPIOD_IS_OUT | GPIOD_IS_IN | \
+                                       GPIOD_IS_OUT_ACTIVE)
+#define GPIOD_MASK_DSTYPE      (GPIOD_OPEN_DRAIN | GPIOD_OPEN_SOURCE)
+#define GPIOD_MASK_PULL                (GPIOD_PULL_UP | GPIOD_PULL_DOWN)
+
        uint offset;            /* GPIO offset within the device */
        /*
         * We could consider adding the GPIO label in here. Possibly we could
@@ -135,12 +141,6 @@ struct gpio_desc {
         */
 };
 
-/* helper to compute the value of the gpio output */
-#define GPIOD_FLAGS_OUTPUT_MASK (GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE)
-#define GPIOD_FLAGS_OUTPUT(flags) \
-       (((((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_IS_OUT_ACTIVE) || \
-         (((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_ACTIVE_LOW)))
-
 /**
  * dm_gpio_is_valid() - Check if a GPIO is valid
  *
@@ -260,10 +260,32 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
 struct dm_gpio_ops {
        int (*request)(struct udevice *dev, unsigned offset, const char *label);
        int (*rfree)(struct udevice *dev, unsigned int offset);
+
+       /**
+        * direction_input() - deprecated
+        *
+        * Equivalent to set_flags(...GPIOD_IS_IN)
+        */
        int (*direction_input)(struct udevice *dev, unsigned offset);
+
+       /**
+        * direction_output() - deprecated
+        *
+        * Equivalent to set_flags(...GPIOD_IS_OUT) with GPIOD_IS_OUT_ACTIVE
+        * also set if @value
+        */
        int (*direction_output)(struct udevice *dev, unsigned offset,
                                int value);
+
        int (*get_value)(struct udevice *dev, unsigned offset);
+
+       /**
+        * set_value() - Sets the GPIO value of an output
+        *
+        * If the driver provides an @set_flags() method then that is used
+        * in preference to this, with GPIOD_IS_OUT_ACTIVE set according to
+        * @value.
+        */
        int (*set_value)(struct udevice *dev, unsigned offset, int value);
        /**
         * get_function() Get the GPIO function
@@ -301,35 +323,54 @@ struct dm_gpio_ops {
                     struct ofnode_phandle_args *args);
 
        /**
-        * set_dir_flags() - Set GPIO dir flags
+        * set_flags() - Adjust GPIO flags
         *
         * This function should set up the GPIO configuration according to the
-        * information provide by the direction flags bitfield.
+        * information provided by @flags.
         *
-        * This method is optional.
+        * If any flags cannot be set (e.g. the driver or hardware does not
+        * support them or this particular GPIO does not have the requested
+        * feature), the driver should return -EINVAL.
+        *
+        * The uclass checks that flags do not obviously conflict (e.g. input
+        * and output). If the driver finds other conflicts it should return
+        * -ERECALLCONFLICT
+        *
+        * Note that GPIOD_ACTIVE_LOW should be ignored, since the uclass
+        * adjusts for it automatically. For example, for an output GPIO,
+        * GPIOD_ACTIVE_LOW causes GPIOD_IS_OUT_ACTIVE to be inverted by the
+        * uclass, so the driver always sees the value that should be set at the
+        * pin (1=high, 0=low).
+        *
+        * This method is required and should be implemented by new drivers. At
+        * some point, it will supersede direction_input() and
+        * direction_output(), which wil be removed.
         *
         * @dev:        GPIO device
         * @offset:     GPIO offset within that device
-        * @flags:      GPIO configuration to use
-        * @return 0 if OK, -ve on error
+        * @flags:      New flags value (GPIOD_...)
+        *
+        * @return 0 if OK, -EINVAL if unsupported, -ERECALLCONFLICT if flags
+        *      conflict in some *      non-obvious way and were not applied,
+        *      other -ve on error
         */
-       int (*set_dir_flags)(struct udevice *dev, unsigned int offset,
-                            ulong flags);
+       int (*set_flags)(struct udevice *dev, unsigned int offset, ulong flags);
 
        /**
-        * get_dir_flags() - Get GPIO dir flags
+        * get_flags() - Get GPIO flags
         *
-        * This function return the GPIO direction flags used.
+        * This function return the GPIO flags used. It should read this from
+        * the hardware directly.
         *
         * This method is optional.
         *
         * @dev:        GPIO device
         * @offset:     GPIO offset within that device
-        * @flags:      place to put the used direction flags by GPIO
+        * @flagsp:     place to put the current flags value
         * @return 0 if OK, -ve on error
         */
-       int (*get_dir_flags)(struct udevice *dev, unsigned int offset,
-                            ulong *flags);
+       int (*get_flags)(struct udevice *dev, unsigned int offset,
+                        ulong *flagsp);
 
 #if CONFIG_IS_ENABLED(ACPIGEN)
        /**
@@ -457,6 +498,31 @@ int gpio_get_values_as_int(const int *gpio_list);
 int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count);
 
 /**
+ * dm_gpio_get_values_as_int_base3() - Create a base-3 int from a list of GPIOs
+ *
+ * This uses pull-ups/pull-downs to figure out whether a GPIO line is externally
+ * pulled down, pulled up or floating. This allows three different strap values
+ * for each pin:
+ *    0 : external pull-down
+ *    1 : external pull-up
+ *    2 : floating
+ *
+ * With this it is possible to obtain more combinations from the same number of
+ * strapping pins, when compared to dm_gpio_get_values_as_int(). The external
+ * pull resistors should be made stronger that the internal SoC pull resistors,
+ * for this to work.
+ *
+ * With 2 pins, 6 combinations are possible, compared with 4
+ * With 3 pins, 27 are possible, compared with 8
+ *
+ * @desc_list: List of GPIOs to collect
+ * @count: Number of GPIOs
+ * @return resulting integer value, or -ve on error
+ */
+int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
+                                   int count);
+
+/**
  * gpio_claim_vector() - claim a number of GPIOs for input
  *
  * @gpio_num_array:    array of gpios to claim, terminated by -1
@@ -652,6 +718,25 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value);
 int dm_gpio_set_dir(struct gpio_desc *desc);
 
 /**
+ * dm_gpio_clrset_flags() - Update flags
+ *
+ * This updates the flags as directled. Note that desc->flags is updated by this
+ * function on success. If any changes cannot be made, best efforts are made.
+ *
+ * By use of @clr and @set any of flags can be individually updated, or left
+ * alone
+ *
+ * @desc:      GPIO description containing device, offset and flags,
+ *             previously returned by gpio_request_by_name()
+ * @clr:       Flags to clear (GPIOD_...)
+ * @set:       Flags to set (GPIOD_...)
+ * @return 0 if OK, -EINVAL if the flags had obvious conflicts,
+ * -ERECALLCONFLICT if there was a non-obvious hardware conflict when attempting
+ * to set the flags
+ */
+int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set);
+
+/**
  * dm_gpio_set_dir_flags() - Set direction using description and added flags
  *
  * This sets up the direction according to the provided flags and the GPIO
@@ -666,16 +751,31 @@ int dm_gpio_set_dir(struct gpio_desc *desc);
 int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
 
 /**
- * dm_gpio_get_dir_flags() - Get direction flags
+ * dm_gpios_clrset_flags() - Sets flags for a set of GPIOs
+ *
+ * This clears and sets flags individually for each GPIO.
+ *
+ * @desc:      List of GPIOs to update
+ * @count:     Number of GPIOs in the list
+ * @clr:       Flags to clear (GPIOD_...), e.g. GPIOD_MASK_DIR if you are
+ *             changing the direction
+ * @set:       Flags to set (GPIOD_...)
+ * @return 0 if OK, -ve on error
+ */
+int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
+                         ulong set);
+
+/**
+ * dm_gpio_get_flags() - Get flags
  *
- * read the current direction flags
+ * Read the current flags
  *
  * @desc:      GPIO description containing device, offset and flags,
  *             previously returned by gpio_request_by_name()
  * @flags:     place to put the used flags
  * @return 0 if OK, -ve on error, in which case desc->flags is not updated
  */
-int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags);
+int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flags);
 
 /**
  * gpio_get_number() - Get the global GPIO number of a GPIO
index 0577238..267f1db 100644 (file)
@@ -28,6 +28,9 @@ extern char __efi_helloworld_end[];
 extern char __efi_var_file_begin[];
 extern char __efi_var_file_end[];
 
+/* Private data used by of-platdata devices/uclasses */
+extern char __priv_data_start[], __priv_data_end[];
+
 /* Start and end of .ctors section - used for constructor calls. */
 extern char __ctors_start[], __ctors_end[];
 
index 5f296d6..ae94f1d 100644 (file)
@@ -9,6 +9,8 @@
 #include <compiler.h>
 #include <linux/compiler.h>
 
+struct cbfs_priv;
+
 enum cbfs_result {
        CBFS_SUCCESS = 0,
        CBFS_NOT_INITIALIZED,
@@ -42,6 +44,8 @@ enum cbfs_filetype {
 
 enum {
        CBFS_HEADER_MAGIC       = 0x4f524243,
+       CBFS_SIZE_UNKNOWN       = 0xffffffff,
+       CBFS_ALIGN_SIZE         = 0x40,
 };
 
 /**
@@ -68,6 +72,52 @@ struct cbfs_fileheader {
        /* offset to struct cbfs_file_attribute or 0 */
        u32 attributes_offset;
        u32 offset;
+       char filename[];
+} __packed;
+
+/**
+ * These are standard values for the known compression alogrithms that coreboot
+ * knows about for stages and payloads.  Of course, other CBFS users can use
+ * whatever values they want, as long as they understand them.
+ */
+#define CBFS_COMPRESS_NONE  0
+#define CBFS_COMPRESS_LZMA  1
+#define CBFS_COMPRESS_LZ4   2
+
+/*
+ * Depending on how the header was initialized, it may be backed with 0x00 or
+ * 0xff, so support both
+ */
+#define CBFS_FILE_ATTR_TAG_UNUSED 0
+#define CBFS_FILE_ATTR_TAG_UNUSED2 0xffffffff
+#define CBFS_FILE_ATTR_TAG_COMPRESSION 0x42435a4c
+#define CBFS_FILE_ATTR_TAG_HASH 0x68736148
+
+/*
+ * The common fields of extended cbfs file attributes. Attributes are expected
+ * to start with tag/len, then append their specific fields
+ */
+struct cbfs_file_attribute {
+       u32 tag;
+       /* len covers the whole structure, incl. tag and len */
+       u32 len;
+       u8 data[0];
+} __packed;
+
+struct cbfs_file_attr_compression {
+       u32 tag;
+       u32 len;
+       /* whole file compression format. 0 if no compression. */
+       u32 compression;
+       u32 decompressed_size;
+} __packed;
+
+struct cbfs_file_attr_hash {
+       u32 tag;
+       u32 len;
+       u32 hash_type;
+       /* hash_data is len - sizeof(struct) bytes */
+       u8  hash_data[];
 } __packed;
 
 struct cbfs_cachenode {
@@ -77,7 +127,9 @@ struct cbfs_cachenode {
        u32 type;
        u32 data_length;
        u32 name_length;
-       u32 attributes_offset;
+       u32 attr_offset;
+       u32 comp_algo;
+       u32 decomp_size;
 };
 
 /**
@@ -111,6 +163,21 @@ int file_cbfs_init(ulong end_of_rom);
 const struct cbfs_header *file_cbfs_get_header(void);
 
 /**
+ * cbfs_get_first() - Get the first file in a CBFS
+ *
+ * @return pointer to first file, or NULL if it is empty
+ */
+const struct cbfs_cachenode *cbfs_get_first(const struct cbfs_priv *priv);
+
+/**
+ * cbfs_get_next() - Get the next file in a CBFS
+ *
+ * @filep: Pointer to current file; updated to point to the next file, if any,
+ *     else NULL
+ */
+void cbfs_get_next(const struct cbfs_cachenode **filep);
+
+/**
  * file_cbfs_get_first() - Get a handle for the first file in CBFS.
  *
  * @return A handle for the first file in CBFS, NULL on error.
@@ -133,8 +200,6 @@ void file_cbfs_get_next(const struct cbfs_cachenode **file);
  */
 const struct cbfs_cachenode *file_cbfs_find(const char *name);
 
-struct cbfs_priv;
-
 /**
  * cbfs_find_file() - Find a file in a given CBFS
  *
@@ -149,11 +214,13 @@ const struct cbfs_cachenode *cbfs_find_file(struct cbfs_priv *cbfs,
  * cbfs_init_mem() - Set up a new CBFS
  *
  * @base: Base address of CBFS
+ * @size: Size of CBFS if known, else CBFS_SIZE_UNKNOWN
+ * @require_header: true to read a header at the start, false to not require one
  * @cbfsp: Returns a pointer to CBFS on success
  * @return 0 if OK, -ve on error
  */
-int cbfs_init_mem(ulong base, struct cbfs_priv **privp);
-
+int cbfs_init_mem(ulong base, ulong size, bool require_hdr,
+                 struct cbfs_priv **privp);
 
 /***************************************************************************/
 /* All of the functions below can be used without first initializing CBFS. */
index 747f8f8..137cfbc 100644 (file)
@@ -389,6 +389,14 @@ int run_command_list(const char *cmd, int len, int flag);
                return 0;                                               \
        }
 
+#define _CMD_REMOVE_REP(_name, _cmd)                                   \
+       int __remove_ ## _name(void)                                    \
+       {                                                               \
+               if (0)                                                  \
+                       _cmd(NULL, 0, 0, NULL, NULL);                   \
+               return 0;                                               \
+       }
+
 #define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep,                \
                                     _usage, _help, _comp)              \
                { #_name, _maxargs, 0 ? _cmd_rep : NULL, NULL, _usage,  \
@@ -405,7 +413,7 @@ int run_command_list(const char *cmd, int len, int flag);
 
 #define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage,      \
                               _help, _comp)                            \
-       _CMD_REMOVE(sub_ ## _name, _cmd_rep)
+       _CMD_REMOVE_REP(sub_ ## _name, _cmd_rep)
 
 #endif /* CONFIG_CMDLINE */
 
index 6e8e8ec..00760b8 100644 (file)
 
 #define CONFIG_BOOTCOMMAND     \
        "tpm init; tpm startup TPM2_SU_CLEAR; " \
-       "read mmc 2:2 100000 0 80; setexpr loader *001004f0; " \
+       "read mmc 0:2 100000 0 80; setexpr loader *001004f0; " \
        "setexpr size *00100518; setexpr blocks $size / 200; " \
-       "read mmc 2:2 100000 80 $blocks; setexpr setup $loader - 1000; " \
+       "read mmc 0:2 100000 80 $blocks; setexpr setup $loader - 1000; " \
        "setexpr cmdline_ptr $loader - 2000; " \
        "setexpr.s cmdline *$cmdline_ptr; " \
        "setexpr cmdline gsub %U \\\\${uuid}; " \
-       "if part uuid mmc 2:2 uuid; then " \
+       "if part uuid mmc 0:2 uuid; then " \
        "zboot start 100000 0 0 0 $setup cmdline; " \
        "zboot load; zboot setup; zboot dump; zboot go;" \
        "fi"
diff --git a/include/configs/hihope-rzg2.h b/include/configs/hihope-rzg2.h
new file mode 100644 (file)
index 0000000..68a5117
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * include/configs/hihope-rzg2.h
+ *     This file is HOPERUN HiHope RZ/G2 board configuration.
+ *
+ * Copyright (C) 2020 Renesas Electronics Corporation
+ */
+
+#ifndef __HIHOPE_RZG2_H
+#define __HIHOPE_RZG2_H
+
+#include "rcar-gen3-common.h"
+
+/* Ethernet RAVB */
+#define CONFIG_BITBANGMII_MULTI
+
+/* Generic Timer Definitions (use in assembler source) */
+#define COUNTER_FREQUENCY      0xFE502A        /* 16.66MHz from CPclk */
+
+#endif /* __HIHOPE_RZG2_H */
diff --git a/include/configs/mt8183.h b/include/configs/mt8183.h
new file mode 100644 (file)
index 0000000..8e7afbb
--- /dev/null
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Configuration for MT8183 based boards
+ *
+ * Copyright (C) 2021 BayLibre, SAS
+ * Author: Fabien Parent <fparent@baylibre.com
+ */
+
+#ifndef __MT8183_H
+#define __MT8183_H
+
+#include <linux/sizes.h>
+
+#define CONFIG_SYS_LOAD_ADDR           CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_MALLOC_LEN          SZ_4M
+
+#define CONFIG_CPU_ARMV8
+#define COUNTER_FREQUENCY              13000000
+
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE    -4
+#define CONFIG_SYS_NS16550_MEM32
+#define CONFIG_SYS_NS16550_COM1                0x11005200
+#define CONFIG_SYS_NS16550_CLK         26000000
+
+#define CONFIG_SYS_INIT_SP_ADDR                (CONFIG_SYS_TEXT_BASE + SZ_2M - \
+                                                GENERATED_GBL_DATA_SIZE)
+
+#define CONFIG_SYS_BOOTM_LEN           SZ_64M
+
+/* Environment settings */
+#include <config_distro_bootcmd.h>
+
+#define BOOT_TARGET_DEVICES(func) \
+       func(MMC, mmc, 0)
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+       "scriptaddr=0x40000000\0" \
+       BOOTENV
+
+#endif
similarity index 55%
rename from include/configs/pumpkin.h
rename to include/configs/mt8516.h
index 9c52cae..a1c5d81 100644 (file)
@@ -6,8 +6,8 @@
  * Author: Fabien Parent <fparent@baylibre.com
  */
 
-#ifndef __PUMPKIN_H
-#define __PUMPKIN_H
+#ifndef __MT8516_H
+#define __MT8516_H
 
 #include <linux/sizes.h>
 
 /* Environment settings */
 #include <config_distro_bootcmd.h>
 
-#define MMCBOOT \
-       "mmcdev=0\0" \
-       "kernel_partition=2\0" \
-       "rootfs_partition=3\0" \
-       "mmc_discover_partition=" \
-               "part start mmc ${mmcdev} ${kernel_partition} kernel_part_addr;" \
-               "part size mmc ${mmcdev} ${kernel_partition} kernel_part_size;\0" \
-       "mmcboot=" \
-               "mmc dev ${mmcdev};" \
-               "run mmc_discover_partition;" \
-               "mmc read ${kerneladdr} ${kernel_part_addr} ${kernel_part_size};" \
-               "setenv bootargs ${bootargs} root=/dev/mmcblk${mmcdev}p${rootfs_partition} rootwait; " \
-               "bootm ${kerneladdr}; \0"
+#define BOOT_TARGET_DEVICES(func) \
+       func(MMC, mmc, 0)
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
-       "kerneladdr=0x4A000000\0" \
-       MMCBOOT \
-       "bootcmd=run mmcboot;\0"
+       "scriptaddr=0x40000000\0" \
+       BOOTENV
 
 #endif
diff --git a/include/configs/silinux-ek874.h b/include/configs/silinux-ek874.h
new file mode 100644 (file)
index 0000000..25c0cd2
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * include/configs/silinux-ek874.h
+ *     This file is Silicon Linux EK874 board configuration.
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ */
+
+#ifndef __SILINUX_EK874_H
+#define __SILINUX_EK874_H
+
+#include "rcar-gen3-common.h"
+
+/* Ethernet RAVB */
+#define CONFIG_BITBANGMII_MULTI
+
+/* Generic Timer Definitions (use in assembler source) */
+#define COUNTER_FREQUENCY      0xFE502A        /* 16.66MHz from CPclk */
+
+#endif /* __SILINUX_EK874_H */
index 7b602dd..33a4d7b 100644 (file)
@@ -223,23 +223,6 @@ extern int soft_i2c_gpio_scl;
 #define CONFIG_VIDEO_LCD_I2C_BUS       -1 /* NA, but necessary to compile */
 #endif
 
-#ifdef CONFIG_VIDEO_SUNXI
-/*
- * The amount of RAM to keep free at the top of RAM when relocating u-boot,
- * to use as framebuffer. This must be a multiple of 4096.
- */
-#define CONFIG_SUNXI_MAX_FB_SIZE (16 << 20)
-
-#define CONFIG_VIDEO_LOGO
-#define CONFIG_VIDEO_STD_TIMINGS
-#define CONFIG_I2C_EDID
-#define VIDEO_LINE_LEN (pGD->plnSizeX)
-
-/* allow both serial and cfb console. */
-/* stop x86 thinking in cfbconsole from trying to init a pc keyboard */
-
-#endif /* CONFIG_VIDEO_SUNXI */
-
 /* Ethernet support */
 
 #ifdef CONFIG_USB_EHCI_HCD
@@ -401,11 +384,7 @@ extern int soft_i2c_gpio_scl;
        "stdin=serial\0"
 #endif
 
-#ifdef CONFIG_VIDEO
-#define CONSOLE_STDOUT_SETTINGS \
-       "stdout=serial,vga\0" \
-       "stderr=serial,vga\0"
-#elif CONFIG_DM_VIDEO
+#ifdef CONFIG_DM_VIDEO
 #define CONSOLE_STDOUT_SETTINGS \
        "stdout=serial,vidconsole\0" \
        "stderr=serial,vidconsole\0"
index 8aa825d..c3a66f0 100644 (file)
@@ -84,6 +84,6 @@ enum {
  */
 int cleanup_before_linux_select(int flags);
 
-void reset_cpu(ulong addr);
-;
+void reset_cpu(void);
+
 #endif
index 39406c3..e6b71cb 100644 (file)
 #ifndef _DM_DEVICE_INTERNAL_H
 #define _DM_DEVICE_INTERNAL_H
 
+#include <linker_lists.h>
 #include <dm/ofnode.h>
 
 struct device_node;
 struct udevice;
 
+/*
+ * These two macros DM_DEVICE_INST and DM_DEVICE_REF are only allowed in code
+ * generated by dtoc, because the ordering is important and if other instances
+ * creep in then they may mess up the ordering expected by dtoc.
+ *
+ * It is OK to use them with 'extern' though, since that does not actually
+ * add a new record to the linker_list.
+ */
+
+/**
+ * DM_DEVICE_INST() - Declare a bound device ready for run-time use
+ *
+ * This adds an actual struct udevice to a list which is found by driver model
+ * on start-up.
+ *
+ * For example:
+ *
+ * extern U_BOOT_DRIVER(sandbox_fixed_clock);
+ * extern DM_UCLASS_INST(clk);
+ *
+ * DM_DEVICE_INST(clk_fixed) = {
+ *     .driver         = DM_DRIVER_REF(sandbox_fixed_clock),
+ *     .name           = "sandbox_fixed_clock",
+ *     .plat_          = &_sandbox_fixed_clock_plat_clk_fixed,
+ *     .uclass         = DM_UCLASS_REF(clk),
+ *     ...
+ *     .seq_           = 0,
+ * };
+ *
+ * @_name: Name of the udevice. This must be a valid C identifier, used by the
+ *     linker_list.
+ */
+#define DM_DEVICE_INST(_name)                                          \
+       ll_entry_declare(struct udevice, _name, udevice)
+
+/**
+ * DM_DEVICE_REF() - Get a reference to a device
+ *
+ * This is useful in data structures and code for referencing a udevice at
+ * build time. Before this is used, an extern DM_DEVICE_INST() must have been
+ * declared.
+ *
+ * For example:
+ *
+ * extern DM_DEVICE_INST(clk_fixed);
+ *
+ * struct udevice *devs[] = {
+ *     DM_DEVICE_REF(clk_fixed),
+ * };
+ *
+ * @_name: Name of the udevice. This must be a valid C identifier, used by the
+ *     linker_list
+ * @returns struct udevice * for the device
+ */
+#define DM_DEVICE_REF(_name)                                           \
+       ll_entry_ref(struct udevice, _name, udevice)
+
+/**
+ * DM_DEVICE_GET() - Get a pointer to a given device
+ *
+ * This is similar to DM_DEVICE_REF() except that it does not need the extern
+ * declaration before it. However it cannot be used in a data structures, only
+ * in code within a function.
+ *
+ * For example:
+ *
+ * void some_function() {
+ *     struct udevice *dev = DM_DEVICE_GET(clk_fixed);
+ * ...
+ * }
+ */
+#define DM_DEVICE_GET(__name)                                          \
+       ll_entry_get(struct udevice, __name, udevice)
+
 /**
  * device_bind() - Create a device and bind it to a driver
  *
@@ -209,6 +284,9 @@ static inline int device_chld_remove(struct udevice *dev, struct driver *drv,
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev                Device to check
  * @priv       New private-data pointer
  */
@@ -223,6 +301,9 @@ void dev_set_priv(struct udevice *dev, void *priv);
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev:       Device to update
  * @parent_priv: New parent-private data
  */
@@ -237,6 +318,9 @@ void dev_set_parent_priv(struct udevice *dev, void *parent_priv);
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev:       Device to update
  * @uclass_priv: New uclass private data
  */
@@ -251,6 +335,9 @@ void dev_set_uclass_priv(struct udevice *dev, void *uclass_priv);
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev                Device to check
  * @plat       New platform-data pointer
  */
@@ -265,6 +352,9 @@ void dev_set_plat(struct udevice *dev, void *priv);
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev:       Device to update
  * @parent_plat: New parent platform data
  */
@@ -279,6 +369,9 @@ void dev_set_parent_plat(struct udevice *dev, void *parent_plat);
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev:       Device to update
  * @uclass_plat: New uclass platform data
  */
index bb9faa0..0a9718a 100644 (file)
@@ -177,7 +177,9 @@ struct udevice {
        struct list_head uclass_node;
        struct list_head child_head;
        struct list_head sibling_node;
+#if !CONFIG_IS_ENABLED(OF_PLATDATA_RT)
        u32 flags_;
+#endif
        int seq_;
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
        ofnode node_;
@@ -190,12 +192,32 @@ struct udevice {
 #endif
 };
 
+/**
+ * udevice_rt - runtime information set up by U-Boot
+ *
+ * This is only used with OF_PLATDATA_RT
+ *
+ * There is one of these for every udevice in the linker list, indexed by
+ * the udevice_info idx value.
+ *
+ * @flags_: Flags for this device DM_FLAG_... (do not access outside driver
+ *     model)
+ */
+struct udevice_rt {
+       u32 flags_;
+};
+
 /* Maximum sequence number supported */
 #define DM_MAX_SEQ     999
 
 /* Returns the operations for a device */
 #define device_get_ops(dev)    (dev->driver->ops)
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT)
+u32 dev_get_flags(const struct udevice *dev);
+void dev_or_flags(const struct udevice *dev, u32 or);
+void dev_bic_flags(const struct udevice *dev, u32 bic);
+#else
 static inline u32 dev_get_flags(const struct udevice *dev)
 {
        return dev->flags_;
@@ -210,6 +232,7 @@ static inline void dev_bic_flags(struct udevice *dev, u32 bic)
 {
        dev->flags_ &= ~bic;
 }
+#endif /* OF_PLATDATA_RT */
 
 /**
  * dev_ofnode() - get the DT node reference associated with a udevice
@@ -363,6 +386,28 @@ struct driver {
        ll_entry_get(struct driver, __name, driver)
 
 /**
+ * DM_DRIVER_REF() - Get a reference to a driver
+ *
+ * This is useful in data structures and code for referencing a driver at
+ * build time. Before this is used, an extern U_BOOT_DRIVER() must have been
+ * declared.
+ *
+ * For example:
+ *
+ * extern U_BOOT_DRIVER(sandbox_fixed_clock);
+ *
+ * struct driver *drvs[] = {
+ *     DM_DRIVER_REF(sandbox_fixed_clock),
+ * };
+ *
+ * @_name: Name of the driver. This must be a valid C identifier, used by the
+ *     linker_list
+ * @returns struct driver * for the driver
+ */
+#define DM_DRIVER_REF(_name)                                   \
+       ll_entry_ref(struct driver, _name, driver)
+
+/**
  * Declare a macro to state a alias for a driver name. This macro will
  * produce no code but its information will be parsed by tools like
  * dtoc
@@ -370,6 +415,40 @@ struct driver {
 #define DM_DRIVER_ALIAS(__name, __alias)
 
 /**
+ * Declare a macro to indicate which phase of U-Boot this driver is fore.
+ *
+ *
+ * This macro produces no code but its information will be parsed by dtoc. The
+ * macro can be only be used once in a driver. Put it within the U_BOOT_DRIVER()
+ * declaration, e.g.:
+ *
+ * U_BOOT_DRIVER(cpu) = {
+ *     .name = ...
+ *     ...
+ *     DM_PHASE(tpl)
+ * };
+ */
+#define DM_PHASE(_phase)
+
+/**
+ * Declare a macro to declare a header needed for a driver. Often the correct
+ * header can be found automatically, but only for struct declarations. For
+ * enums and #defines used in the driver declaration and declared in a different
+ * header from the structs, this macro must be used.
+ *
+ * This macro produces no code but its information will be parsed by dtoc. The
+ * macro can be used multiple times with different headers, for the same driver.
+ * Put it within the U_BOOT_DRIVER() declaration, e.g.:
+ *
+ * U_BOOT_DRIVER(cpu) = {
+ *     .name = ...
+ *     ...
+ *     DM_HEADER(<asm/cpu.h>)
+ * };
+ */
+#define DM_HEADER(_hdr)
+
+/**
  * dev_get_plat() - Get the platform data for a device
  *
  * This checks that dev is not NULL, but no other checks for now
@@ -611,33 +690,24 @@ int device_find_global_by_ofnode(ofnode node, struct udevice **devp);
 int device_get_global_by_ofnode(ofnode node, struct udevice **devp);
 
 /**
- * device_get_by_driver_info() - Get a device based on driver_info
- *
- * Locates a device by its struct driver_info, by using its reference which
- * is updated during the bind process.
+ * device_get_by_ofplat_idx() - Get a device based on of-platdata index
  *
- * The device is probed to activate it ready for use.
- *
- * @info: Struct driver_info
- * @devp: Returns pointer to device if found, otherwise this is set to NULL
- * @return 0 if OK, -ve on error
- */
-int device_get_by_driver_info(const struct driver_info *info,
-                             struct udevice **devp);
-
-/**
- * device_get_by_driver_info_idx() - Get a device based on driver_info index
+ * Locates a device by either its struct driver_info index, or its
+ * struct udevice index. The latter is used with OF_PLATDATA_INST, since we have
+ * a list of build-time instantiated struct udevice records, The former is used
+ * with !OF_PLATDATA_INST since in that case we have a list of
+ * struct driver_info records.
  *
- * Locates a device by its struct driver_info, by using its index number which
- * is written into the idx field of struct phandle_1_arg, etc.
+ * The index number is written into the idx field of struct phandle_1_arg, etc.
+ * It is the position of this driver_info/udevice in its linker list.
  *
  * The device is probed to activate it ready for use.
  *
- * @idx: Index number of the driver_info structure (0=first)
+ * @idx: Index number of the driver_info/udevice structure (0=first)
  * @devp: Returns pointer to device if found, otherwise this is set to NULL
  * @return 0 if OK, -ve on error
  */
-int device_get_by_driver_info_idx(uint idx, struct udevice **devp);
+int device_get_by_ofplat_idx(uint idx, struct udevice **devp);
 
 /**
  * device_find_first_child() - Find the first child of a device
index ca15df2..fc4f974 100644 (file)
 
 enum fmap_compress_t {
        FMAP_COMPRESS_NONE,
+       FMAP_COMPRESS_LZMA,
        FMAP_COMPRESS_LZ4,
+
+       FMAP_COMPRESS_COUNT,
+       FMAP_COMPRESS_UNKNOWN,
 };
 
 enum fmap_hash_t {
@@ -30,6 +34,10 @@ struct fmap_entry {
        enum fmap_hash_t hash_algo;             /* Hash algorithm */
        const uint8_t *hash;                    /* Hash value */
        int hash_size;                          /* Hash size */
+       /* Node pointer if CBFS, else NULL */
+       const struct cbfs_cachenode *cbfs_node;
+       /* Hash node pointer if CBFS, else NULL */
+       const struct cbfs_cachenode *cbfs_hash_node;
 };
 
 /**
index 3821a56..4efb1df 100644 (file)
@@ -71,19 +71,4 @@ struct driver_rt {
 #define U_BOOT_DRVINFOS(__name)                                                \
        ll_entry_declare_list(struct driver_info, __name, driver_info)
 
-/**
- * Get a pointer to a given device info given its name
- *
- * With the declaration U_BOOT_DRVINFO(name), DM_DRVINFO_GET(name) will return a
- * pointer to the struct driver_info created by that declaration.
- *
- * if OF_PLATDATA is enabled, from this it is possible to use the @dev member of
- * struct driver_info to find the device pointer itself.
- *
- * @__name: Driver name (C identifier, not a string. E.g. gpio7_at_ff7e0000)
- * @return struct driver_info * to the driver that created the device
- */
-#define DM_DRVINFO_GET(__name)                                         \
-       ll_entry_get(struct driver_info, __name, driver_info)
-
 #endif
index 89afbee..42510b1 100644 (file)
@@ -11,6 +11,9 @@
 
 struct udevice;
 
+/* Head of the uclass list if CONFIG_OF_PLATDATA_INST is enabled */
+extern struct list_head uclass_head;
+
 /**
  * dm_root() - Return pointer to the top of the driver tree
  *
index c5a9610..a9562b2 100644 (file)
@@ -73,6 +73,11 @@ struct dm_test_priv {
        int uclass_postp;
 };
 
+/* struct dm_test_uc_priv - private data for the testdrv uclass */
+struct dm_test_uc_priv {
+       int dummy;
+};
+
 /**
  * struct dm_test_perdev_class_priv - private per-device data for test uclass
  */
@@ -127,25 +132,9 @@ extern int dm_testdrv_op_count[DM_TEST_OP_COUNT];
 
 extern struct unit_test_state global_dm_test_state;
 
-/*
- * struct dm_test_state - Entire state of dm test system
- *
- * This is often abreviated to dms.
- *
- * @root: Root device
- * @testdev: Test device
- * @force_fail_alloc: Force all memory allocs to fail
- * @skip_post_probe: Skip uclass post-probe processing
- */
-struct dm_test_state {
-       struct udevice *root;
-       struct udevice *testdev;
-       int force_fail_alloc;
-       int skip_post_probe;
-};
-
 /* Declare a new driver model test */
-#define DM_TEST(_name, _flags) UNIT_TEST(_name, _flags, dm_test)
+#define DM_TEST(_name, _flags) \
+       UNIT_TEST(_name, UT_TESTF_DM | UT_TESTF_CONSOLE_REC | (_flags), dm_test)
 
 /*
  * struct sandbox_sdl_plat - Platform data for the SDL video driver
index c5a464b..57c664c 100644 (file)
 
 #include <dm/ofnode.h>
 
+/*
+ * These next two macros DM_UCLASS_INST() and DM_UCLASS_REF() are only allowed
+ * in code generated by dtoc, because the ordering is important and if other
+ * instances creep in then they may mess up the ordering expected by dtoc.
+ *
+ * It is OK to use them with 'extern' though, since that does not actually
+ * add a new record to the linker_list.
+ */
+
+/**
+ * DM_UCLASS_INST() - Declare a uclass ready for run-time use
+ *
+ * This adds an actual struct uclass to a list which is found by driver model
+ * on start-up.
+ *
+ * For example:
+ *
+ * DM_UCLASS_INST(clk) = {
+ *     .uc_drv         = DM_UCLASS_DRIVER_REF(clk),
+ * ...
+ * };
+ *
+ * @_name: Name of the uclass. This must be a valid C identifier, used by the
+ *     linker_list.
+ */
+#define DM_UCLASS_INST(_name)                                          \
+       ll_entry_declare(struct uclass, _name, uclass)
+
+/**
+ * DM_UCLASS_REF() - Get a reference to a uclass
+ *
+ * This is useful for referencing a uclass at build time. Before this is used,
+ * an extern DM_UCLASS_INST() must have been declared.
+ *
+ * For example:
+ *
+ * extern DM_UCLASS_INST(clk);
+ *
+ * struct uclass *ucs[] = {
+ *     DM_UCLASS_REF(clk),
+ * }
+ *
+ * @_name: Name of the uclass. This must be a valid C identifier, used by the
+ *     linker_list
+ * @returns struct uclass * for the device
+ */
+#define DM_UCLASS_REF(_name)                                           \
+       ll_entry_ref(struct uclass, _name, uclass)
+
 /**
  * uclass_set_priv() - Set the private data for a uclass
  *
@@ -20,6 +69,9 @@
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @uc         Uclass to update
  * @priv       New private-data pointer
  */
index d956837..6752d8e 100644 (file)
@@ -114,6 +114,37 @@ struct uclass_driver {
 #define UCLASS_DRIVER(__name)                                          \
        ll_entry_declare(struct uclass_driver, __name, uclass_driver)
 
+/*
+ * These two macros DM_UCLASS_DRIVER_REF and DM_UCLASS_DRIVER_REF are only
+ * allowed in code generated by dtoc, because the ordering is important and if
+ * other instances creep in then they may mess up the ordering expected by dtoc.
+ *
+ * It is OK to use them with 'extern' though, since that does not actually
+ * add a new record to the linker_list.
+ */
+
+/**
+ * DM_UCLASS_DRIVER_REF() - Get a reference to a uclass driver
+ *
+ * This is useful in data structures and code for referencing a uclass_driver at
+ * build time. Before this is used, an extern UCLASS_DRIVER() must have been
+ * declared.
+ *
+ * For example:
+ *
+ * extern UCLASS_DRIVER(clk);
+ *
+ * struct uclass_driver *drvs[] = {
+ *     DM_UCLASS_DRIVER_REF(clk),
+ * };
+ *
+ * @_name: Name of the uclass_driver. This must be a valid C identifier, used by
+ *     the linker_list.
+ * @returns struct uclass_driver * for the uclass driver
+ */
+#define DM_UCLASS_DRIVER_REF(_name)                                    \
+       ll_entry_ref(struct uclass_driver, _name, uclass_driver)
+
 /**
  * uclass_get_priv() - Get the private data for a uclass
  *
index 01a0449..138893c 100644 (file)
@@ -49,3 +49,12 @@ void dm_dump_driver_compat(void);
 void dm_dump_static_driver_info(void);
 
 #endif
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA_INST) && CONFIG_IS_ENABLED(READ_ONLY)
+void *dm_priv_to_rw(void *priv);
+#else
+static inline void *dm_priv_to_rw(void *priv)
+{
+       return priv;
+}
+#endif
diff --git a/include/dt-bindings/display/tda998x.h b/include/dt-bindings/display/tda998x.h
new file mode 100644 (file)
index 0000000..746831f
--- /dev/null
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _DT_BINDINGS_TDA998X_H
+#define _DT_BINDINGS_TDA998X_H
+
+#define TDA998x_SPDIF  1
+#define TDA998x_I2S    2
+
+#endif /*_DT_BINDINGS_TDA998X_H */
diff --git a/include/dt-bindings/dma/xlnx-zynqmp-dpdma.h b/include/dt-bindings/dma/xlnx-zynqmp-dpdma.h
new file mode 100644 (file)
index 0000000..3719cda
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#ifndef __DT_BINDINGS_DMA_XLNX_ZYNQMP_DPDMA_H__
+#define __DT_BINDINGS_DMA_XLNX_ZYNQMP_DPDMA_H__
+
+#define ZYNQMP_DPDMA_VIDEO0            0
+#define ZYNQMP_DPDMA_VIDEO1            1
+#define ZYNQMP_DPDMA_VIDEO2            2
+#define ZYNQMP_DPDMA_GRAPHICS          3
+#define ZYNQMP_DPDMA_AUDIO0            4
+#define ZYNQMP_DPDMA_AUDIO1            5
+
+#endif /* __DT_BINDINGS_DMA_XLNX_ZYNQMP_DPDMA_H__ */
index f0e1c9c..f9ccaf5 100644 (file)
@@ -24,7 +24,9 @@ struct phandle_2_arg {
        uint idx;
        int arg[2];
 };
+
 #include <generated/dt-structs-gen.h>
+#include <generated/dt-decl.h>
 #endif
 
 #endif
index 4ccde1d..18a1adf 100644 (file)
@@ -1732,6 +1732,23 @@ struct efi_load_file_protocol {
                                         void *buffer);
 };
 
+struct efi_system_resource_entry {
+       efi_guid_t fw_class;
+       u32 fw_type;
+       u32 fw_version;
+       u32 lowest_supported_fw_version;
+       u32 capsule_flags;
+       u32 last_attempt_version;
+       u32 last_attempt_status;
+} __packed;
+
+struct efi_system_resource_table {
+       u32 fw_resource_count;
+       u32 fw_resource_count_max;
+       u64 fw_resource_version;
+       struct efi_system_resource_entry entries[];
+} __packed;
+
 /* Boot manager load options */
 #define LOAD_OPTION_ACTIVE             0x00000001
 #define LOAD_OPTION_FORCE_RECONNECT    0x00000002
@@ -1750,6 +1767,10 @@ struct efi_load_file_protocol {
 #define ESRT_FW_TYPE_DEVICEFIRMWARE    0x00000002
 #define ESRT_FW_TYPE_UEFIDRIVER                0x00000003
 
+#define EFI_SYSTEM_RESOURCE_TABLE_GUID\
+       EFI_GUID(0xb122a263, 0x3661, 0x4f68,\
+               0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80)
+
 /* Last Attempt Status Values */
 #define LAST_ATTEMPT_STATUS_SUCCESS                    0x00000000
 #define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL         0x00000001
index 68daa1a..de1a496 100644 (file)
@@ -214,6 +214,8 @@ extern const efi_guid_t efi_guid_rng_protocol;
 extern const efi_guid_t efi_guid_capsule_report;
 /* GUID of firmware management protocol */
 extern const efi_guid_t efi_guid_firmware_management_protocol;
+/* GUID for the ESRT */
+extern const efi_guid_t efi_esrt_guid;
 
 extern unsigned int __efi_runtime_start, __efi_runtime_stop;
 extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
@@ -437,6 +439,7 @@ efi_status_t efi_net_register(void);
 /* Called by bootefi to make the watchdog available */
 efi_status_t efi_watchdog_register(void);
 efi_status_t efi_initrd_register(void);
+void efi_initrd_deregister(void);
 /* Called by bootefi to make SMBIOS tables available */
 /**
  * efi_acpi_register() - write out ACPI tables
@@ -558,6 +561,15 @@ struct efi_simple_file_system_protocol *efi_simple_file_system(
 /* open file from device-path: */
 struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp);
 
+/* Registers a callback function for a notification event. */
+efi_status_t EFIAPI efi_register_protocol_notify(const efi_guid_t *protocol,
+                                                struct efi_event *event,
+                                                void **registration);
+efi_status_t efi_file_size(struct efi_file_handle *fh, efi_uintn_t *size);
+
+/* get a device path from a Boot#### option */
+struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid);
+
 /**
  * efi_size_in_pages() - convert size in bytes to size in pages
  *
@@ -723,6 +735,8 @@ efi_status_t EFIAPI efi_query_variable_info(
                        u64 *remaining_variable_storage_size,
                        u64 *maximum_variable_size);
 
+void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size);
+
 /*
  * See section 3.1.3 in the v2.7 UEFI spec for more details on
  * the layout of EFI_LOAD_OPTION.  In short it is:
@@ -744,6 +758,10 @@ struct efi_load_option {
        const u8 *optional_data;
 };
 
+struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
+                                      efi_uintn_t *size, efi_guid_t guid);
+struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
+                                     const struct efi_device_path *dp2);
 efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
                                         efi_uintn_t *size);
 unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data);
@@ -890,4 +908,22 @@ static inline efi_status_t efi_launch_capsules(void)
 
 #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
 
+/**
+ * Install the ESRT system table.
+ *
+ * @return     status code
+ */
+efi_status_t efi_esrt_register(void);
+
+/**
+ * efi_esrt_populate() - Populates the ESRT entries from the FMP instances
+ * present in the system.
+ * If an ESRT already exists, the old ESRT is replaced in the system table.
+ * The memory of the old ESRT is deallocated.
+ *
+ * Return:
+ * - EFI_SUCCESS if the ESRT is correctly created
+ * - error code otherwise.
+ */
+efi_status_t efi_esrt_populate(void);
 #endif /* _EFI_LOADER_H */
index 1515fda..07b6199 100644 (file)
@@ -66,11 +66,10 @@ enum efi_test_phase {
         */
        EFI_SETUP_BEFORE_BOOTTIME_EXIT,
        /**
-        * @EFI_SETUP_AFTER_BOOTTIME_EXIT: - setup after ExitBootServices
-        *
-        * Setup, execute, and teardown are executed after ExitBootServices().
+        * @EFI_SETTING_VIRTUAL_ADDRESS_MAP - calls SetVirtualAddressMap()
+        * Execute calls SetVirtualAddressMap().
         */
-       EFI_SETUP_AFTER_BOOTTIME_EXIT,
+       EFI_SETTING_VIRTUAL_ADDRESS_MAP,
 };
 
 extern struct efi_simple_text_output_protocol *con_out;
index 7ae0c42..c0fe94c 100644 (file)
@@ -93,6 +93,8 @@ struct udevice;
  *                        datasheet explains it's usage of this addressing
  *                        mode.
  * @emul: Emulator for this chip address (only used for emulation)
+ * @emul_idx: Emulator index, used for of-platdata and set by each i2c chip's
+ *     bind() method. This allows i2c_emul_find() to work with of-platdata.
  */
 struct dm_i2c_chip {
        uint chip_addr;
@@ -102,6 +104,7 @@ struct dm_i2c_chip {
 #ifdef CONFIG_SANDBOX
        struct udevice *emul;
        bool test_mode;
+       int emul_idx;
 #endif
 };
 
@@ -555,6 +558,18 @@ void i2c_dump_msgs(struct i2c_msg *msg, int nmsgs);
 int i2c_emul_find(struct udevice *dev, struct udevice **emulp);
 
 /**
+ * i2c_emul_set_idx() - Set the emulator index for an i2c sandbox device
+ *
+ * With of-platdata we cannot find the emulator using the device tree, so rely
+ * on the bind() method of each i2c driver calling this function to tell us
+ * the of-platdata idx of the emulator
+ *
+ * @dev: i2c device to set the emulator for
+ * @emul_idx: of-platdata index for that emulator
+ */
+void i2c_emul_set_idx(struct udevice *dev, int emul_idx);
+
+/**
  * i2c_emul_get_device() - Find the device being emulated
  *
  * Given an emulator this returns the associated device
index b4b284d..aeb0d37 100644 (file)
@@ -886,6 +886,11 @@ static inline int image_check_type(const image_header_t *hdr, uint8_t type)
 }
 static inline int image_check_arch(const image_header_t *hdr, uint8_t arch)
 {
+#ifndef USE_HOSTCC
+       /* Let's assume that sandbox can load any architecture */
+       if (IS_ENABLED(CONFIG_SANDBOX))
+               return true;
+#endif
        return (image_get_arch(hdr) == arch) ||
                (image_get_arch(hdr) == IH_ARCH_ARM && arch == IH_ARCH_ARM64);
 }
index fd98ecd..81a280a 100644 (file)
        })
 
 /**
+ * ll_entry_ref() - Get a reference to a linker-generated array entry
+ *
+ * Once an extern ll_entry_declare() has been used to declare the reference,
+ * this macro allows the entry to be accessed.
+ *
+ * This is like ll_entry_get(), but without the extra code, so it is suitable
+ * for putting into data structures.
+ */
+#define ll_entry_ref(_type, _name, _list)                              \
+       ((_type *)&_u_boot_list_2_##_list##_2_##_name)
+
+/**
  * ll_start() - Point to first entry of first linker-generated array
  * @_type:     Data type of the entry
  *
index cc9c430..6fda14f 100644 (file)
@@ -192,6 +192,8 @@ struct clk_fixed_factor {
        unsigned int    div;
 };
 
+extern const struct clk_ops clk_fixed_rate_ops;
+
 #define to_clk_fixed_factor(_clk) container_of(_clk, struct clk_fixed_factor,\
                                               clk)
 
@@ -202,6 +204,9 @@ struct clk_fixed_rate {
 
 #define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_plat(dev))
 
+void clk_fixed_rate_ofdata_to_plat_(struct udevice *dev,
+                                   struct clk_fixed_rate *plat);
+
 struct clk_composite {
        struct clk      clk;
        struct clk_ops  ops;
index 2d27f9f..6ef891d 100644 (file)
@@ -316,12 +316,40 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
                    __ret); \
        __ret; \
        })
+
+/*
+ * Similar to the above, but any non-zero value is consider an error, not just
+ * values less than 0.
+ */
+#define log_retz(_ret) ({ \
+       int __ret = (_ret); \
+       if (__ret) \
+               log(LOG_CATEGORY, LOGL_ERR, "returning err=%d\n", __ret); \
+       __ret; \
+       })
+#define log_msg_retz(_msg, _ret) ({ \
+       int __ret = (_ret); \
+       if (__ret) \
+               log(LOG_CATEGORY, LOGL_ERR, "%s: returning err=%d\n", _msg, \
+                   __ret); \
+       __ret; \
+       })
 #else
 /* Non-logging versions of the above which just return the error code */
 #define log_ret(_ret) (_ret)
 #define log_msg_ret(_msg, _ret) ((void)(_msg), _ret)
+#define log_retz(_ret) (_ret)
+#define log_msg_retz(_msg, _ret) ((void)(_msg), _ret)
 #endif
 
+/** * enum log_rec_flags - Flags for a log record */
+enum log_rec_flags {
+       /** @LOGRECF_FORCE_DEBUG: Force output of debug record */
+       LOGRECF_FORCE_DEBUG     = BIT(0),
+       /** @LOGRECF_CONT: Continuation of previous log record */
+       LOGRECF_CONT            = BIT(1),
+};
+
 /**
  * struct log_rec - a single log record
  *
@@ -337,18 +365,18 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
  *
  * @cat: Category, representing a uclass or part of U-Boot
  * @level: Severity level, less severe is higher
- * @force_debug: Force output of debug
- * @file: Name of file where the log record was generated (not allocated)
  * @line: Line number where the log record was generated
+ * @flags: Flags for log record (enum log_rec_flags)
+ * @file: Name of file where the log record was generated (not allocated)
  * @func: Function where the log record was generated (not allocated)
  * @msg: Log message (allocated)
  */
 struct log_rec {
        enum log_category_t cat;
        enum log_level_t level;
-       bool force_debug;
+       u16 line;
+       u8 flags;
        const char *file;
-       int line;
        const char *func;
        const char *msg;
 };
index e15e528..024b18b 100644 (file)
@@ -880,6 +880,8 @@ extern Void_t*     sbrk();
 
 #else
 
+void malloc_simple_info(void);
+
 #if CONFIG_IS_ENABLED(SYS_MALLOC_SIMPLE)
 #define malloc malloc_simple
 #define realloc realloc_simple
@@ -887,7 +889,6 @@ extern Void_t*     sbrk();
 static inline void free(void *ptr) {}
 void *calloc(size_t nmemb, size_t size);
 void *realloc_simple(void *ptr, size_t size);
-void malloc_simple_info(void);
 #else
 
 # ifdef USE_DL_PREFIX
index 65bcb23..77d8bd8 100644 (file)
@@ -114,7 +114,7 @@ void os_fd_restore(void);
  * os_malloc() - aquires some memory from the underlying os.
  *
  * @length:    Number of bytes to be allocated
- * Return:     Pointer to length bytes or NULL on error
+ * Return:     Pointer to length bytes or NULL if @length is 0 or on error
  */
 void *os_malloc(size_t length);
 
@@ -123,11 +123,22 @@ void *os_malloc(size_t length);
  *
  * This returns the memory to the OS.
  *
- * @ptr:       Pointer to memory block to free
+ * @ptr:       Pointer to memory block to free. If this is NULL then this
+ *             function does nothing
  */
 void os_free(void *ptr);
 
 /**
+ * os_realloc() - reallocate memory
+ *
+ * This follows the semantics of realloc(), so can perform an os_malloc() or
+ * os_free() depending on @ptr and @length.
+ *
+ * Return:     Pointer to reallocated memory or NULL if @length is 0
+ */
+void *os_realloc(void *ptr, size_t length);
+
+/**
  * os_usleep() - access to the usleep function of the os
  *
  * @usec:      time to sleep in micro seconds
@@ -313,9 +324,10 @@ int os_jump_to_image(const void *dest, int size);
  *
  * @fname:     place to put full path to U-Boot
  * @maxlen:    maximum size of @fname
+ * @use_img:   select the 'u-boot.img' file instead of the 'u-boot' ELF file
  * Return:     0 if OK, -NOSPC if the filename is too large, -ENOENT if not found
  */
-int os_find_u_boot(char *fname, int maxlen);
+int os_find_u_boot(char *fname, int maxlen, bool use_img);
 
 /**
  * os_spl_to_uboot() - Run U-Boot proper
index c1f0afb..4006e94 100644 (file)
@@ -14,6 +14,13 @@ struct host_block_dev {
        int fd;
 };
 
-int host_dev_bind(int dev, char *filename);
+/**
+ * host_dev_bind() - Bind or unbind a device
+ *
+ * @dev: Device number (0=first slot)
+ * @filename: Host filename to use, or NULL to unbind
+ * @removable: true if the block device should mark itself as removable
+ */
+int host_dev_bind(int dev, char *filename, bool removable);
 
 #endif
diff --git a/include/scp03.h b/include/scp03.h
new file mode 100644 (file)
index 0000000..729667c
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+
+#ifndef _SCP03_H
+#define _SCP03_H
+
+/*
+ * Requests to OPTEE to enable or provision the Secure Channel Protocol on its
+ * Secure Element
+ *
+ *  If key provisioning is requested, OPTEE shall generate new SCP03 keys and
+ *  write them to the Secure Element.
+ *
+ *  Both functions return < 0 on error else 0.
+ */
+int tee_enable_scp03(void);
+int tee_provision_scp03(void);
+#endif /* _SCP03_H */
index ecc4fd1..ffeefb4 100644 (file)
 #define SMBIOS_MAJOR_VER       3
 #define SMBIOS_MINOR_VER       0
 
+enum {
+       SMBIOS_STR_MAX  = 64,   /* Maximum length allowed for a string */
+};
+
 /* SMBIOS structure types */
 enum {
        SMBIOS_BIOS_INFORMATION = 0,
@@ -269,4 +273,20 @@ const char *smbios_string(const struct smbios_header *header, int index);
  */
 int smbios_update_version(const char *version);
 
+/**
+ * smbios_update_version_full() - Update the version string
+ *
+ * This can be called after the SMBIOS tables are written (e.g. after the U-Boot
+ * main loop has started) to update the BIOS version string (SMBIOS table 0).
+ * It scans for the correct place to put the version, so does not need U-Boot
+ * to have actually written the tables itself (e.g. if a previous bootloader
+ * did it).
+ *
+ * @smbios_tab: Start of SMBIOS tables
+ * @version: New version string to use
+ * @return 0 if OK, -ENOENT if no version string was previously written,
+ *     -ENOSPC if the new string is too large to fit
+ */
+int smbios_update_version_full(void *smbios_tab, const char *version);
+
 #endif /* _SMBIOS_H_ */
index 85cae32..3d747c9 100644 (file)
@@ -35,6 +35,19 @@ struct dm_spi_flash_ops {
        int (*write)(struct udevice *dev, u32 offset, size_t len,
                     const void *buf);
        int (*erase)(struct udevice *dev, u32 offset, size_t len);
+       /**
+        * get_sw_write_prot() - Check state of software write-protect feature
+        *
+        * SPI flash chips can lock a region of the flash defined by a
+        * 'protected area'. This function checks if this protected area is
+        * defined.
+        *
+        * @dev:        SPI flash device
+        * @return 0 if no region is write-protected, 1 if a region is
+        *      write-protected, -ENOSYS if the driver does not implement this,
+        *      other -ve value on error
+        */
+       int (*get_sw_write_prot)(struct udevice *dev);
 };
 
 /* Access the serial operations for a device */
@@ -77,6 +90,20 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len,
 int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len);
 
 /**
+ * spl_flash_get_sw_write_prot() - Check state of software write-protect feature
+ *
+ * SPI flash chips can lock a region of the flash defined by a
+ * 'protected area'. This function checks if this protected area is
+ * defined.
+ *
+ * @dev:       SPI flash device
+ * @return 0 if no region is write-protected, 1 if a region is
+ *     write-protected, -ENOSYS if the driver does not implement this,
+ *     other -ve value on error
+ */
+int spl_flash_get_sw_write_prot(struct udevice *dev);
+
+/**
  * spi_flash_std_probe() - Probe a SPI flash device
  *
  * This is the standard internal method for probing a SPI flash device to
@@ -97,7 +124,9 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
                                  unsigned int max_hz, unsigned int spi_mode);
 
 /* Compatibility function - this is the old U-Boot API */
-void spi_flash_free(struct spi_flash *flash);
+static inline void spi_flash_free(struct spi_flash *flash)
+{
+}
 
 static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
                                 size_t len, void *buf)
index 0d13458..4f6e0e5 100644 (file)
@@ -222,6 +222,15 @@ struct spl_load_info {
        void *priv;
        int bl_len;
        const char *filename;
+       /**
+        * read() - Read from device
+        *
+        * @load: Information about the load state
+        * @sector: Sector number to read from (each @load->bl_len bytes)
+        * @count: Number of sectors to read
+        * @buf: Buffer to read into
+        * @return number of sectors read, 0 on error
+        */
        ulong (*read)(struct spl_load_info *load, ulong sector, ulong count,
                      void *buf);
 };
index 270ac1b..68fad25 100644 (file)
@@ -37,9 +37,13 @@ struct udevice;
 enum sysinfo_id {
        SYSINFO_ID_NONE,
 
+       /* For SMBIOS tables */
        SYSINFO_ID_SMBIOS_SYSTEM_VERSION,
        SYSINFO_ID_SMBIOS_BASEBOARD_VERSION,
 
+       /* For show_board_info() */
+       SYSINFO_ID_BOARD_MODEL,
+
        /* First value available for downstream/board used */
        SYSINFO_ID_USER = 0x1000,
 };
index 8bb094d..701e4f5 100644 (file)
@@ -116,6 +116,6 @@ void sysreset_walk_halt(enum sysreset_t type);
 /**
  * reset_cpu() - calls sysreset_walk(SYSRESET_WARM)
  */
-void reset_cpu(ulong addr);
+void reset_cpu(void);
 
 #endif
diff --git a/include/tee/optee_ta_scp03.h b/include/tee/optee_ta_scp03.h
new file mode 100644 (file)
index 0000000..13f9956
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+#ifndef __TA_SCP03_H
+#define __TA_SCP03_H
+
+#define PTA_SCP03_UUID { 0xbe0e5821, 0xe718, 0x4f77, \
+                       { 0xab, 0x3e, 0x8e, 0x6c, 0x73, 0xa9, 0xc7, 0x35 } }
+
+/*
+ * Enable Secure Channel Protocol functionality (SCP03) on the Secure Element.
+ *   Setting the operation value to something different than NULL will trigger
+ *   the SCP03 provisioning request.
+ *
+ *   in        params[0].a = operation
+ */
+#define PTA_CMD_ENABLE_SCP03   0
+
+#endif /*__TA_SCP03_H*/
index 3fdaa2b..0b124ed 100644 (file)
  *
  * @fail_count: Number of tests that failed
  * @start: Store the starting mallinfo when doing leak test
- * @priv: A pointer to some other info some suites want to track
+ * @of_live: true to use livetree if available, false to use flattree
  * @of_root: Record of the livetree root node (used for setting up tests)
+ * @root: Root device
+ * @testdev: Test device
+ * @force_fail_alloc: Force all memory allocs to fail
+ * @skip_post_probe: Skip uclass post-probe processing
  * @expect_str: Temporary string used to hold expected string value
  * @actual_str: Temporary string used to hold actual string value
  */
 struct unit_test_state {
        int fail_count;
        struct mallinfo start;
-       void *priv;
        struct device_node *of_root;
+       bool of_live;
+       struct udevice *root;
+       struct udevice *testdev;
+       int force_fail_alloc;
+       int skip_post_probe;
        char expect_str[256];
        char actual_str[256];
 };
@@ -36,6 +44,8 @@ enum {
        UT_TESTF_FLAT_TREE      = BIT(3),       /* test needs flat DT */
        UT_TESTF_LIVE_TREE      = BIT(4),       /* needs live device tree */
        UT_TESTF_CONSOLE_REC    = BIT(5),       /* needs console recording */
+       /* do extra driver model init and uninit */
+       UT_TESTF_DM             = BIT(6),
 };
 
 /**
@@ -76,13 +86,24 @@ struct unit_test {
  * @_suite:    name of the test suite concatenated with "_test"
  */
 #define UNIT_TEST(_name, _flags, _suite)                               \
-       ll_entry_declare(struct unit_test, _name, _suite) = {           \
+       ll_entry_declare(struct unit_test, _name, ut_ ## _suite) = {    \
                .file = __FILE__,                                       \
                .name = #_name,                                         \
                .flags = _flags,                                        \
                .func = _name,                                          \
        }
 
+/* Get the start of a list of unit tests for a particular suite */
+#define UNIT_TEST_SUITE_START(_suite) \
+       ll_entry_start(struct unit_test, ut_ ## _suite)
+#define UNIT_TEST_SUITE_COUNT(_suite) \
+       ll_entry_count(struct unit_test, ut_ ## _suite)
+
+/* Use ! and ~ so that all tests will be sorted between these two values */
+#define UNIT_TEST_ALL_START()  ll_entry_start(struct unit_test, ut_!)
+#define UNIT_TEST_ALL_END()    ll_entry_start(struct unit_test, ut_~)
+#define UNIT_TEST_ALL_COUNT()  (UNIT_TEST_ALL_END() - UNIT_TEST_ALL_START())
+
 /* Sizes for devres tests */
 enum {
        TEST_DEVRES_SIZE        = 100,
@@ -103,15 +124,4 @@ enum {
  */
 struct udevice *testbus_get_clear_removed(void);
 
-/**
- * dm_test_main() - Run driver model tests
- *
- * Run all the available driver model tests, or a selection
- *
- * @test_name: Name of single test to run (e.g. "dm_test_fdt_pre_reloc" or just
- *     "fdt_pre_reloc"), or NULL to run all
- * @return 0 if all tests passed, 1 if not
- */
-int dm_test_main(const char *test_name);
-
 #endif /* __TEST_TEST_H */
index 17400c7..fbbba28 100644 (file)
@@ -356,4 +356,49 @@ void ut_silence_console(struct unit_test_state *uts);
  */
 void ut_unsilence_console(struct unit_test_state *uts);
 
+/**
+ * ut_set_skip_delays() - Sets whether delays should be skipped
+ *
+ * Normally functions like mdelay() cause U-Boot to wait for a while. This
+ * allows all such delays to be skipped on sandbox, to speed up tests
+ *
+ * @uts: Test state (in case in future we want to keep state here)
+ * @skip_delays: true to skip delays, false to process them normally
+ */
+void ut_set_skip_delays(struct unit_test_state *uts, bool skip_delays);
+
+/**
+ * test_get_state() - Get the active test state
+ *
+ * @return the currently active test state, or NULL if none
+ */
+struct unit_test_state *test_get_state(void);
+
+/**
+ * test_set_state() - Set the active test state
+ *
+ * @uts: Test state to use as currently active test state, or NULL if none
+ */
+void test_set_state(struct unit_test_state *uts);
+
+/**
+ * ut_run_tests() - Run a set of tests
+ *
+ * This runs the test, handling any preparation and clean-up needed. It prints
+ * the name of each test before running it.
+ *
+ * @category: Category of these tests. This is a string printed at the start to
+ *     announce the the number of tests
+ * @prefix: String prefix for the tests. Any tests that have this prefix will be
+ *     printed without the prefix, so that it is easier to see the unique part
+ *     of the test name. If NULL, no prefix processing is done
+ * @tests: List of tests to run
+ * @count: Number of tests to run
+ * @select_name: Name of a single test to run (from the list provided). If NULL
+ *     then all tests are run
+ * @return 0 if all tests passed, -1 if any failed
+ */
+int ut_run_list(const char *name, const char *prefix, struct unit_test *tests,
+               int count, const char *select_name);
+
 #endif
index c1309a2..998b4fb 100644 (file)
@@ -55,6 +55,8 @@ enum tpm_version {
  * @buf:               Buffer used during the exchanges with the chip
  * @pcr_count:         Number of PCR per bank
  * @pcr_select_min:    Minimum size in bytes of the pcrSelect array
+ * @plat_hier_disabled:        Platform hierarchy has been disabled (TPM is locked
+ *                     down until next reboot)
  */
 struct tpm_chip_priv {
        enum tpm_version version;
@@ -66,6 +68,7 @@ struct tpm_chip_priv {
        /* TPM v2 specific data */
        uint pcr_count;
        uint pcr_select_min;
+       bool plat_hier_disabled;
 };
 
 /**
index 8f6cc28..fcfe1f0 100644 (file)
@@ -289,7 +289,7 @@ struct __packed tpm_nv_data_public {
  * @param mode         TPM startup mode
  * @return return code of the operation
  */
-u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode);
+u32 tpm1_startup(struct udevice *dev, enum tpm_startup_type mode);
 
 /**
  * Issue a TPM_SelfTestFull command.
@@ -297,7 +297,7 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode);
  * @param dev          TPM device
  * @return return code of the operation
  */
-u32 tpm_self_test_full(struct udevice *dev);
+u32 tpm1_self_test_full(struct udevice *dev);
 
 /**
  * Issue a TPM_ContinueSelfTest command.
@@ -305,7 +305,7 @@ u32 tpm_self_test_full(struct udevice *dev);
  * @param dev          TPM device
  * @return return code of the operation
  */
-u32 tpm_continue_self_test(struct udevice *dev);
+u32 tpm1_continue_self_test(struct udevice *dev);
 
 /**
  * Issue a TPM_NV_DefineSpace command.  The implementation is limited
@@ -318,7 +318,7 @@ u32 tpm_continue_self_test(struct udevice *dev);
  * @param size         size of the area
  * @return return code of the operation
  */
-u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size);
+u32 tpm1_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size);
 
 /**
  * Issue a TPM_NV_ReadValue command.  This implementation is limited
@@ -331,7 +331,7 @@ u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size);
  * @param count                size of output buffer
  * @return return code of the operation
  */
-u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
+u32 tpm1_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
 
 /**
  * Issue a TPM_NV_WriteValue command.  This implementation is limited
@@ -344,8 +344,8 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
  * @param length       length of data bytes of input buffer
  * @return return code of the operation
  */
-u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
-                      u32 length);
+u32 tpm1_nv_write_value(struct udevice *dev, u32 index, const void *data,
+                       u32 length);
 
 /**
  * Issue a TPM_Extend command.
@@ -358,8 +358,8 @@ u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
  *                     command
  * @return return code of the operation
  */
-u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
-              void *out_digest);
+u32 tpm1_extend(struct udevice *dev, u32 index, const void *in_digest,
+               void *out_digest);
 
 /**
  * Issue a TPM_PCRRead command.
@@ -370,7 +370,7 @@ u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
  * @param count                size of output buffer
  * @return return code of the operation
  */
-u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count);
+u32 tpm1_pcr_read(struct udevice *dev, u32 index, void *data, size_t count);
 
 /**
  * Issue a TSC_PhysicalPresence command.  TPM physical presence flag
@@ -380,7 +380,7 @@ u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count);
  * @param presence     TPM physical presence flag
  * @return return code of the operation
  */
-u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence);
+u32 tpm1_tsc_physical_presence(struct udevice *dev, u16 presence);
 
 /**
  * Issue a TPM_ReadPubek command.
@@ -390,7 +390,7 @@ u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence);
  * @param count                size of output buffer
  * @return return code of the operation
  */
-u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count);
+u32 tpm1_read_pubek(struct udevice *dev, void *data, size_t count);
 
 /**
  * Issue a TPM_ForceClear command.
@@ -398,7 +398,7 @@ u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count);
  * @param dev          TPM device
  * @return return code of the operation
  */
-u32 tpm_force_clear(struct udevice *dev);
+u32 tpm1_force_clear(struct udevice *dev);
 
 /**
  * Issue a TPM_PhysicalEnable command.
@@ -406,7 +406,7 @@ u32 tpm_force_clear(struct udevice *dev);
  * @param dev          TPM device
  * @return return code of the operation
  */
-u32 tpm_physical_enable(struct udevice *dev);
+u32 tpm1_physical_enable(struct udevice *dev);
 
 /**
  * Issue a TPM_PhysicalDisable command.
@@ -414,7 +414,7 @@ u32 tpm_physical_enable(struct udevice *dev);
  * @param dev          TPM device
  * @return return code of the operation
  */
-u32 tpm_physical_disable(struct udevice *dev);
+u32 tpm1_physical_disable(struct udevice *dev);
 
 /**
  * Issue a TPM_PhysicalSetDeactivated command.
@@ -423,7 +423,7 @@ u32 tpm_physical_disable(struct udevice *dev);
  * @param state                boolean state of the deactivated flag
  * @return return code of the operation
  */
-u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state);
+u32 tpm1_physical_set_deactivated(struct udevice *dev, u8 state);
 
 /**
  * Issue a TPM_GetCapability command.  This implementation is limited
@@ -437,8 +437,8 @@ u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state);
  * @param count                size of output buffer
  * @return return code of the operation
  */
-u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
-                      void *cap, size_t count);
+u32 tpm1_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+                       void *cap, size_t count);
 
 /**
  * Issue a TPM_FlushSpecific command for a AUTH resource.
@@ -447,7 +447,7 @@ u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
  * @param auth_handle  handle of the auth session
  * @return return code of the operation
  */
-u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle);
+u32 tpm1_terminate_auth_session(struct udevice *dev, u32 auth_handle);
 
 /**
  * Issue a TPM_OIAP command to setup an object independent authorization
@@ -460,7 +460,7 @@ u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle);
  * @param auth_handle  pointer to the (new) auth handle or NULL.
  * @return return code of the operation
  */
-u32 tpm_oiap(struct udevice *dev, u32 *auth_handle);
+u32 tpm1_oiap(struct udevice *dev, u32 *auth_handle);
 
 /**
  * Ends an active OIAP session.
@@ -468,7 +468,7 @@ u32 tpm_oiap(struct udevice *dev, u32 *auth_handle);
  * @param dev          TPM device
  * @return return code of the operation
  */
-u32 tpm_end_oiap(struct udevice *dev);
+u32 tpm1_end_oiap(struct udevice *dev);
 
 /**
  * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating
@@ -482,9 +482,9 @@ u32 tpm_end_oiap(struct udevice *dev);
  * @param key_handle   pointer to the key handle
  * @return return code of the operation
  */
-u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
-                      size_t key_length, const void *parent_key_usage_auth,
-                      u32 *key_handle);
+u32 tpm1_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
+                       size_t key_length, const void *parent_key_usage_auth,
+                       u32 *key_handle);
 
 /**
  * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for
@@ -500,9 +500,9 @@ u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
  *                     of the stored TPM_PUBKEY structure (iff pubkey != NULL).
  * @return return code of the operation
  */
-u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
-                        const void *usage_auth, void *pubkey,
-                        size_t *pubkey_len);
+u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
+                         const void *usage_auth, void *pubkey,
+                         size_t *pubkey_len);
 
 /**
  * Get the TPM permanent flags value
@@ -511,8 +511,8 @@ u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
  * @param pflags       Place to put permanent flags
  * @return return code of the operation
  */
-u32 tpm_get_permanent_flags(struct udevice *dev,
-                           struct tpm_permanent_flags *pflags);
+u32 tpm1_get_permanent_flags(struct udevice *dev,
+                            struct tpm_permanent_flags *pflags);
 
 /**
  * Get the TPM permissions
@@ -521,7 +521,7 @@ u32 tpm_get_permanent_flags(struct udevice *dev,
  * @param perm         Returns permissions value
  * @return return code of the operation
  */
-u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm);
+u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm);
 
 /**
  * Flush a resource with a given handle and type from the TPM
@@ -531,7 +531,7 @@ u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm);
  * @param resource_type                type of the resource
  * @return return code of the operation
  */
-u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type);
+u32 tpm1_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type);
 
 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
 /**
@@ -543,8 +543,8 @@ u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type);
  * @param[out] handle  The handle of the key (Non-null iff found)
  * @return 0 if key was found in TPM; != 0 if not.
  */
-u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
-                     const u8 pubkey_digest[20], u32 *handle);
+u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20],
+                      const u8 pubkey_digest[20], u32 *handle);
 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
 
 /**
@@ -557,7 +557,7 @@ u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
  * @param count                size of output buffer
  * @return return code of the operation
  */
-u32 tpm_get_random(struct udevice *dev, void *data, u32 count);
+u32 tpm1_get_random(struct udevice *dev, void *data, u32 count);
 
 /**
  * tpm_finalise_physical_presence() - Finalise physical presence
@@ -565,15 +565,15 @@ u32 tpm_get_random(struct udevice *dev, void *data, u32 count);
  * @param dev          TPM device
  * @return return code of the operation (0 = success)
  */
-u32 tpm_finalise_physical_presence(struct udevice *dev);
+u32 tpm1_finalise_physical_presence(struct udevice *dev);
 
 /**
- * tpm_nv_set_locked() - lock the non-volatile space
+ * tpm_nv_enable_locking() - lock the non-volatile space
  *
  * @param dev          TPM device
  * @return return code of the operation (0 = success)
  */
-u32 tpm_nv_set_locked(struct udevice *dev);
+u32 tpm1_nv_set_locked(struct udevice *dev);
 
 /**
  * tpm_set_global_lock() - set the global lock
@@ -589,6 +589,6 @@ u32 tpm_set_global_lock(struct udevice *dev);
  * @param dev          TPM device
  * @return return code of the operation (0 = success)
  */
-u32 tpm_resume(struct udevice *dev);
+u32 tpm1_resume(struct udevice *dev);
 
 #endif /* __TPM_V1_H */
index 56eaa65..df67a19 100644 (file)
@@ -237,10 +237,14 @@ enum tpm2_handles {
 enum tpm2_command_codes {
        TPM2_CC_STARTUP         = 0x0144,
        TPM2_CC_SELF_TEST       = 0x0143,
+       TPM2_CC_HIER_CONTROL    = 0x0121,
        TPM2_CC_CLEAR           = 0x0126,
        TPM2_CC_CLEARCONTROL    = 0x0127,
        TPM2_CC_HIERCHANGEAUTH  = 0x0129,
+       TPM2_CC_NV_DEFINE_SPACE = 0x012a,
        TPM2_CC_PCR_SETAUTHPOL  = 0x012C,
+       TPM2_CC_NV_WRITE        = 0x0137,
+       TPM2_CC_NV_WRITELOCK    = 0x0138,
        TPM2_CC_DAM_RESET       = 0x0139,
        TPM2_CC_DAM_PARAMETERS  = 0x013A,
        TPM2_CC_NV_READ         = 0x014E,
@@ -271,6 +275,7 @@ enum tpm2_return_codes {
        TPM2_RC_COMMAND_CODE    = TPM2_RC_VER1 + 0x0043,
        TPM2_RC_AUTHSIZE        = TPM2_RC_VER1 + 0x0044,
        TPM2_RC_AUTH_CONTEXT    = TPM2_RC_VER1 + 0x0045,
+       TPM2_RC_NV_DEFINED      = TPM2_RC_VER1 + 0x004c,
        TPM2_RC_NEEDS_TEST      = TPM2_RC_VER1 + 0x0053,
        TPM2_RC_WARN            = 0x0900,
        TPM2_RC_TESTING         = TPM2_RC_WARN + 0x000A,
@@ -355,6 +360,20 @@ enum {
        TPM_MAX_BUF_SIZE        = 1260,
 };
 
+enum {
+       /* Secure storage for firmware settings */
+       TPM_HT_PCR = 0,
+       TPM_HT_NV_INDEX,
+       TPM_HT_HMAC_SESSION,
+       TPM_HT_POLICY_SESSION,
+
+       HR_SHIFT                = 24,
+       HR_PCR                  = TPM_HT_PCR << HR_SHIFT,
+       HR_HMAC_SESSION         = TPM_HT_HMAC_SESSION << HR_SHIFT,
+       HR_POLICY_SESSION       = TPM_HT_POLICY_SESSION << HR_SHIFT,
+       HR_NV_INDEX             = TPM_HT_NV_INDEX << HR_SHIFT,
+};
+
 /**
  * Issue a TPM2_Startup command.
  *
@@ -389,6 +408,23 @@ u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
               const ssize_t pw_sz);
 
 /**
+ * Issue a TPM_NV_DefineSpace command
+ *
+ * This allows a space to be defined with given attributes and policy
+ *
+ * @dev                        TPM device
+ * @space_index                index of the area
+ * @space_size         size of area in bytes
+ * @nv_attributes      TPM_NV_ATTRIBUTES of the area
+ * @nv_policy          policy to use
+ * @nv_policy_size     size of the policy
+ * @return return code of the operation
+ */
+u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
+                        size_t space_size, u32 nv_attributes,
+                        const u8 *nv_policy, size_t nv_policy_size);
+
+/**
  * Issue a TPM2_PCR_Extend command.
  *
  * @dev                TPM device
@@ -403,6 +439,29 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
                    const u8 *digest, u32 digest_len);
 
 /**
+ * Read data from the secure storage
+ *
+ * @dev                TPM device
+ * @index      Index of data to read
+ * @data       Place to put data
+ * @count      Number of bytes of data
+ * @return code of the operation
+ */
+u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
+
+/**
+ * Write data to the secure storage
+ *
+ * @dev                TPM device
+ * @index      Index of data to write
+ * @data       Data to write
+ * @count      Number of bytes of data
+ * @return code of the operation
+ */
+u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
+                       u32 count);
+
+/**
  * Issue a TPM2_PCR_Read command.
  *
  * @dev                TPM device
@@ -516,4 +575,26 @@ u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
  */
 u32 tpm2_get_random(struct udevice *dev, void *data, u32 count);
 
+/**
+ * Lock data in the TPM
+ *
+ * Once locked the data cannot be written until after a reboot
+ *
+ * @dev                TPM device
+ * @index      Index of data to lock
+ * @return code of the operation
+ */
+u32 tpm2_write_lock(struct udevice *dev, u32 index);
+
+/**
+ * Disable access to any platform data
+ *
+ * This can be called to close off access to the firmware data in the data,
+ * before calling the kernel.
+ *
+ * @dev                TPM device
+ * @return code of the operation
+ */
+u32 tpm2_disable_platform_hierarchy(struct udevice *dev);
+
 #endif /* __TPM_V2_H */
diff --git a/include/tpm_api.h b/include/tpm_api.h
new file mode 100644 (file)
index 0000000..f13d98c
--- /dev/null
@@ -0,0 +1,322 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#ifndef __TPM_API_H
+#define __TPM_API_H
+
+#include <tpm-common.h>
+#include <tpm-v1.h>
+#include <tpm-v2.h>
+
+/**
+ * Issue a TPM_Startup command.
+ *
+ * @param dev          TPM device
+ * @param mode         TPM startup mode
+ * @return return code of the operation
+ */
+u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode);
+
+/**
+ * Issue a TPM_SelfTestFull command.
+ *
+ * @param dev          TPM device
+ * @return return code of the operation
+ */
+u32 tpm_self_test_full(struct udevice *dev);
+
+/**
+ * Issue a TPM_ContinueSelfTest command.
+ *
+ * @param dev          TPM device
+ * @return return code of the operation
+ */
+u32 tpm_continue_self_test(struct udevice *dev);
+
+/**
+ * Issue a TPM_NV_DefineSpace command.  The implementation is limited
+ * to specify TPM_NV_ATTRIBUTES and size of the area.  The area index
+ * could be one of the special value listed in enum tpm_nv_index.
+ *
+ * @param dev          TPM device
+ * @param index                index of the area
+ * @param perm         TPM_NV_ATTRIBUTES of the area
+ * @param size         size of the area
+ * @return return code of the operation
+ */
+u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size);
+
+/**
+ * Issue a TPM_NV_ReadValue command.  This implementation is limited
+ * to read the area from offset 0.  The area index could be one of
+ * the special value listed in enum tpm_nv_index.
+ *
+ * @param dev          TPM device
+ * @param index                index of the area
+ * @param data         output buffer of the area contents
+ * @param count                size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
+
+/**
+ * Issue a TPM_NV_WriteValue command.  This implementation is limited
+ * to write the area from offset 0.  The area index could be one of
+ * the special value listed in enum tpm_nv_index.
+ *
+ * @param dev          TPM device
+ * @param index                index of the area
+ * @param data         input buffer to be wrote to the area
+ * @param length       length of data bytes of input buffer
+ * @return return code of the operation
+ */
+u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
+                      u32 length);
+
+/**
+ * Issue a TPM_Extend command.
+ *
+ * @param dev          TPM device
+ * @param index                index of the PCR
+ * @param in_digest    160-bit value representing the event to be
+ *                     recorded
+ * @param out_digest   160-bit PCR value after execution of the
+ *                     command
+ * @return return code of the operation
+ */
+u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
+                  void *out_digest);
+
+/**
+ * Issue a TPM_PCRRead command.
+ *
+ * @param dev          TPM device
+ * @param index                index of the PCR
+ * @param data         output buffer for contents of the named PCR
+ * @param count                size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count);
+
+/**
+ * Issue a TSC_PhysicalPresence command.  TPM physical presence flag
+ * is bit-wise OR'ed of flags listed in enum tpm_physical_presence.
+ *
+ * @param dev          TPM device
+ * @param presence     TPM physical presence flag
+ * @return return code of the operation
+ */
+u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence);
+
+/**
+ * Issue a TPM_ReadPubek command.
+ *
+ * @param dev          TPM device
+ * @param data         output buffer for the public endorsement key
+ * @param count                size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count);
+
+/**
+ * Issue a TPM_ForceClear command.
+ *
+ * @param dev          TPM device
+ * @return return code of the operation
+ */
+u32 tpm_force_clear(struct udevice *dev);
+
+/**
+ * Issue a TPM_PhysicalEnable command.
+ *
+ * @param dev          TPM device
+ * @return return code of the operation
+ */
+u32 tpm_physical_enable(struct udevice *dev);
+
+/**
+ * Issue a TPM_PhysicalDisable command.
+ *
+ * @param dev          TPM device
+ * @return return code of the operation
+ */
+u32 tpm_physical_disable(struct udevice *dev);
+
+/**
+ * Issue a TPM_PhysicalSetDeactivated command.
+ *
+ * @param dev          TPM device
+ * @param state                boolean state of the deactivated flag
+ * @return return code of the operation
+ */
+u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state);
+
+/**
+ * Issue a TPM_GetCapability command.  This implementation is limited
+ * to query sub_cap index that is 4-byte wide.
+ *
+ * @param dev          TPM device
+ * @param cap_area     partition of capabilities
+ * @param sub_cap      further definition of capability, which is
+ *                     limited to be 4-byte wide
+ * @param cap          output buffer for capability information
+ * @param count                size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+                      void *cap, size_t count);
+
+/**
+ * Issue a TPM_FlushSpecific command for a AUTH resource.
+ *
+ * @param dev          TPM device
+ * @param auth_handle  handle of the auth session
+ * @return return code of the operation
+ */
+u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle);
+
+/**
+ * Issue a TPM_OIAP command to setup an object independent authorization
+ * session.
+ * Information about the session is stored internally.
+ * If there was already an OIAP session active it is terminated and a new
+ * session is set up.
+ *
+ * @param dev          TPM device
+ * @param auth_handle  pointer to the (new) auth handle or NULL.
+ * @return return code of the operation
+ */
+u32 tpm_oiap(struct udevice *dev, u32 *auth_handle);
+
+/**
+ * Ends an active OIAP session.
+ *
+ * @param dev          TPM device
+ * @return return code of the operation
+ */
+u32 tpm_end_oiap(struct udevice *dev);
+
+/**
+ * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating
+ * the usage of the parent key.
+ *
+ * @param dev          TPM device
+ * @param parent_handle        handle of the parent key.
+ * @param key          pointer to the key structure (TPM_KEY or TPM_KEY12).
+ * @param key_length   size of the key structure
+ * @param parent_key_usage_auth        usage auth for the parent key
+ * @param key_handle   pointer to the key handle
+ * @return return code of the operation
+ */
+u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
+                      size_t key_length, const void *parent_key_usage_auth,
+                      u32 *key_handle);
+
+/**
+ * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for
+ * authenticating the usage of the key.
+ *
+ * @param dev          TPM device
+ * @param key_handle   handle of the key
+ * @param usage_auth   usage auth for the key
+ * @param pubkey       pointer to the pub key buffer; may be NULL if the pubkey
+ *                     should not be stored.
+ * @param pubkey_len   pointer to the pub key buffer len. On entry: the size of
+ *                     the provided pubkey buffer. On successful exit: the size
+ *                     of the stored TPM_PUBKEY structure (iff pubkey != NULL).
+ * @return return code of the operation
+ */
+u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
+                        const void *usage_auth, void *pubkey,
+                        size_t *pubkey_len);
+
+/**
+ * Get the TPM permissions
+ *
+ * @param dev          TPM device
+ * @param perm         Returns permissions value
+ * @return return code of the operation
+ */
+u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm);
+
+/**
+ * Flush a resource with a given handle and type from the TPM
+ *
+ * @param dev          TPM device
+ * @param key_handle           handle of the resource
+ * @param resource_type                type of the resource
+ * @return return code of the operation
+ */
+u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type);
+
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+/**
+ * Search for a key by usage AuthData and the hash of the parent's pub key.
+ *
+ * @param dev          TPM device
+ * @param auth         Usage auth of the key to search for
+ * @param pubkey_digest        SHA1 hash of the pub key structure of the key
+ * @param[out] handle  The handle of the key (Non-null iff found)
+ * @return 0 if key was found in TPM; != 0 if not.
+ */
+u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
+                     const u8 pubkey_digest[20], u32 *handle);
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
+/**
+ * Read random bytes from the TPM RNG. The implementation deals with the fact
+ * that the TPM may legally return fewer bytes than requested by retrying
+ * until @p count bytes have been received.
+ *
+ * @param dev          TPM device
+ * @param data         output buffer for the random bytes
+ * @param count                size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_get_random(struct udevice *dev, void *data, u32 count);
+
+/**
+ * tpm_finalise_physical_presence() - Finalise physical presence
+ *
+ * @param dev          TPM device
+ * @return return code of the operation (0 = success)
+ */
+u32 tpm_finalise_physical_presence(struct udevice *dev);
+
+/**
+ * tpm_nv_enable_locking() - lock the non-volatile space
+ *
+ * @param dev          TPM device
+ * @return return code of the operation (0 = success)
+ */
+u32 tpm_nv_enable_locking(struct udevice *dev);
+
+/**
+ * tpm_set_global_lock() - set the global lock
+ *
+ * @param dev          TPM device
+ * @return return code of the operation (0 = success)
+ */
+u32 tpm_set_global_lock(struct udevice *dev);
+
+/**
+ * tpm_write_lock() - lock the non-volatile space
+ *
+ * @param dev          TPM device
+ * @param index                Index of space to lock
+ * @return return code of the operation (0 = success)
+ */
+u32 tpm_write_lock(struct udevice *dev, u32 index);
+
+/**
+ * tpm_resume() - start up the TPM from resume (after suspend)
+ *
+ * @param dev          TPM device
+ * @return return code of the operation (0 = success)
+ */
+u32 tpm_resume(struct udevice *dev);
+
+#endif /* __TPM_API_H */
index 7288340..80ff244 100644 (file)
@@ -642,7 +642,7 @@ menu "System tables"
 
 config BLOBLIST_TABLES
        bool "Put tables in a bloblist"
-       depends on X86
+       depends on X86 && BLOBLIST
        help
          Normally tables are placed at address 0xf0000 and can be up to 64KB
          long. With this option, tables are instead placed in the bloblist
index edc1c3d..c42d4e1 100644 (file)
@@ -53,6 +53,7 @@ endif
 obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm-common.o
 ifeq ($(CONFIG_$(SPL_TPL_)TPM),y)
 obj-y += crc8.o
+obj-$(CONFIG_TPM) += tpm_api.o
 obj-$(CONFIG_TPM_V1) += tpm-v1.o
 obj-$(CONFIG_TPM_V2) += tpm-v2.o
 endif
index 6040ec8..530df6a 100644 (file)
@@ -128,8 +128,8 @@ int binman_select_subnode(const char *name)
        if (!ofnode_valid(node))
                return log_msg_ret("node", -ENOENT);
        binman->image = node;
-       log_debug("binman: Selected image subnode '%s'\n",
-                 ofnode_get_name(binman->image));
+       log_info("binman: Selected image subnode '%s'\n",
+                ofnode_get_name(binman->image));
 
        return 0;
 }
index 634d3b1..e44f004 100644 (file)
@@ -315,18 +315,13 @@ config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE
 
 config EFI_LOAD_FILE2_INITRD
        bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk"
-       default n
-       help
-         Expose a EFI_FILE_LOAD2_PROTOCOL that the Linux UEFI stub can
-         use to load the initial ramdisk. Once this is enabled using
-         initrd=<ramdisk> will stop working.
-
-config EFI_INITRD_FILESPEC
-       string "initramfs path"
-       default "host 0:1 initrd"
-       depends on EFI_LOAD_FILE2_INITRD
+       default y
        help
-         Full path of the initramfs file, e.g. mmc 0:2 initramfs.cpio.gz.
+         Linux v5.7 and later can make use of this option. If the boot option
+         selected by the UEFI boot manager specifies an existing file to be used
+         as initial RAM disk, a Linux specific Load File2 protocol will be
+         installed and Linux 5.7+ will ignore any initrd=<ramdisk> command line
+         argument.
 
 config EFI_SECURE_BOOT
        bool "Enable EFI secure boot support"
@@ -347,4 +342,11 @@ config EFI_SECURE_BOOT
          it is signed with a trusted key. To do that, you need to install,
          at least, PK, KEK and db.
 
+config EFI_ESRT
+       bool "Enable the UEFI ESRT generation"
+       depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
+       default y
+       help
+         Enabling this option creates the ESRT UEFI system table.
+
 endif
index 10b42e8..8bd343e 100644 (file)
@@ -23,6 +23,7 @@ endif
 obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
 obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o
 obj-y += efi_boottime.o
+obj-y += efi_helper.o
 obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
 obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o
 obj-y += efi_console.o
@@ -52,6 +53,7 @@ obj-y += efi_variable.o
 obj-$(CONFIG_EFI_VARIABLES_PRESEED) += efi_var_seed.o
 endif
 obj-y += efi_watchdog.o
+obj-$(CONFIG_EFI_ESRT) += efi_esrt.o
 obj-$(CONFIG_LCD) += efi_gop.o
 obj-$(CONFIG_DM_VIDEO) += efi_gop.o
 obj-$(CONFIG_PARTITIONS) += efi_disk.o
index 25f5ceb..46c8011 100644 (file)
@@ -118,11 +118,13 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
                ret = efi_set_variable_int(L"BootCurrent",
                                           &efi_global_variable_guid,
                                           attributes, sizeof(n), &n, false);
-               if (ret != EFI_SUCCESS) {
-                       if (EFI_CALL(efi_unload_image(*handle))
-                           != EFI_SUCCESS)
-                               log_err("Unloading image failed\n");
-                       goto error;
+               if (ret != EFI_SUCCESS)
+                       goto unload;
+               /* try to register load file2 for initrd's */
+               if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) {
+                       ret = efi_initrd_register();
+                       if (ret != EFI_SUCCESS)
+                               goto unload;
                }
 
                log_info("Booting: %ls\n", lo.label);
@@ -147,6 +149,13 @@ error:
        free(load_option);
 
        return ret;
+
+unload:
+       if (EFI_CALL(efi_unload_image(*handle)) != EFI_SUCCESS)
+               log_err("Unloading image failed\n");
+       free(load_option);
+
+       return ret;
 }
 
 /**
index 41b8949..4777b35 100644 (file)
@@ -1406,10 +1406,9 @@ out:
  *
  * Return: status code
  */
-static efi_status_t EFIAPI efi_register_protocol_notify(
-                                               const efi_guid_t *protocol,
-                                               struct efi_event *event,
-                                               void **registration)
+efi_status_t EFIAPI efi_register_protocol_notify(const efi_guid_t *protocol,
+                                                struct efi_event *event,
+                                                void **registration)
 {
        struct efi_register_notify_event *item;
        efi_status_t ret = EFI_SUCCESS;
@@ -1877,7 +1876,6 @@ static
 efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
                                      void **buffer, efi_uintn_t *size)
 {
-       struct efi_file_info *info = NULL;
        struct efi_file_handle *f;
        efi_status_t ret;
        u64 addr;
@@ -1888,18 +1886,7 @@ efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
        if (!f)
                return EFI_NOT_FOUND;
 
-       /* Get file size */
-       bs = 0;
-       EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
-                                 &bs, info));
-       if (ret != EFI_BUFFER_TOO_SMALL) {
-               ret =  EFI_DEVICE_ERROR;
-               goto error;
-       }
-
-       info = malloc(bs);
-       EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, &bs,
-                                 info));
+       ret = efi_file_size(f, &bs);
        if (ret != EFI_SUCCESS)
                goto error;
 
@@ -1909,7 +1896,6 @@ efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
         * allocate a buffer as EFI_BOOT_SERVICES_DATA. The caller has to
         * update the reservation according to the image type.
         */
-       bs = info->file_size;
        ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
                                 EFI_BOOT_SERVICES_DATA,
                                 efi_size_in_pages(bs), &addr);
@@ -1926,7 +1912,6 @@ efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
        *size = bs;
 error:
        EFI_CALL(f->close(f));
-       free(info);
        return ret;
 }
 
index 7ba1ced..9df9c35 100644 (file)
@@ -482,6 +482,14 @@ efi_status_t EFIAPI efi_update_capsule(
                        goto out;
        }
 out:
+
+       if (IS_ENABLED(CONFIG_EFI_ESRT)) {
+               /* Rebuild the ESRT to reflect any updated FW images. */
+               ret = efi_esrt_populate();
+               if (ret != EFI_SUCCESS)
+                       log_warning("EFI Capsule: failed to update ESRT\n");
+       }
+
        return EFI_EXIT(ret);
 }
 
index 398dbc6..4b20859 100644 (file)
@@ -282,11 +282,31 @@ struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
        return ndp;
 }
 
-struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
-                                     const struct efi_device_path *dp2)
+/**
+ * efi_dp_append_or_concatenate() - Append or concatenate two device paths.
+ *                                 Concatenated device path will be separated
+ *                                 by a sub-type 0xff end node
+ *
+ * @dp1:       First device path
+ * @dp2:       Second device path
+ * @concat:    If true the two device paths will be concatenated and separated
+ *             by an end of entrire device path sub-type 0xff end node.
+ *             If true the second device path will be appended to the first and
+ *             terminated by an end node
+ *
+ * Return:
+ * concatenated device path or NULL. Caller must free the returned value
+ */
+static struct
+efi_device_path *efi_dp_append_or_concatenate(const struct efi_device_path *dp1,
+                                             const struct efi_device_path *dp2,
+                                             bool concat)
 {
        struct efi_device_path *ret;
+       size_t end_size = sizeof(END);
 
+       if (concat)
+               end_size = 2 * sizeof(END);
        if (!dp1 && !dp2) {
                /* return an end node */
                ret = efi_dp_dup(&END);
@@ -298,18 +318,58 @@ struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
                /* both dp1 and dp2 are non-null */
                unsigned sz1 = efi_dp_size(dp1);
                unsigned sz2 = efi_dp_size(dp2);
-               void *p = dp_alloc(sz1 + sz2 + sizeof(END));
+               void *p = dp_alloc(sz1 + sz2 + end_size);
                if (!p)
                        return NULL;
+               ret = p;
                memcpy(p, dp1, sz1);
+               p += sz1;
+
+               if (concat) {
+                       memcpy(p, &END, sizeof(END));
+                       p += sizeof(END);
+               }
+
                /* the end node of the second device path has to be retained */
-               memcpy(p + sz1, dp2, sz2 + sizeof(END));
-               ret = p;
+               memcpy(p, dp2, sz2);
+               p += sz2;
+               memcpy(p, &END, sizeof(END));
        }
 
        return ret;
 }
 
+/**
+ * efi_dp_append() - Append a device to an existing device path.
+ *
+ * @dp1:       First device path
+ * @dp2:       Second device path
+ *
+ * Return:
+ * concatenated device path or NULL. Caller must free the returned value
+ */
+struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
+                                     const struct efi_device_path *dp2)
+{
+       return efi_dp_append_or_concatenate(dp1, dp2, false);
+}
+
+/**
+ * efi_dp_concat() - Concatenate 2 device paths. The final device path will
+ *                   contain two device paths separated by and end node (0xff).
+ *
+ * @dp1:       First device path
+ * @dp2:       Second device path
+ *
+ * Return:
+ * concatenated device path or NULL. Caller must free the returned value
+ */
+struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
+                                     const struct efi_device_path *dp2)
+{
+       return efi_dp_append_or_concatenate(dp1, dp2, true);
+}
+
 struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
                                           const struct efi_device_path *node)
 {
@@ -1183,3 +1243,43 @@ ssize_t efi_dp_check_length(const struct efi_device_path *dp,
                dp = (const struct efi_device_path *)((const u8 *)dp + len);
        }
 }
+
+/**
+ * efi_dp_from_lo() - Get the instance of a VenMedia node in a
+ *                    multi-instance device path that matches
+ *                    a specific GUID. This kind of device paths
+ *                    is found in Boot#### options describing an
+ *                    initrd location
+ *
+ * @lo:                EFI_LOAD_OPTION containing a valid device path
+ * @size:      size of the discovered device path
+ * @guid:      guid to search for
+ *
+ * Return:
+ * device path including the VenMedia node or NULL.
+ * Caller must free the returned value.
+ */
+struct
+efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
+                               efi_uintn_t *size, efi_guid_t guid)
+{
+       struct efi_device_path *fp = lo->file_path;
+       struct efi_device_path_vendor *vendor;
+       int lo_len = lo->file_path_length;
+
+       for (; lo_len >=  sizeof(struct efi_device_path);
+            lo_len -= fp->length, fp = (void *)fp + fp->length) {
+               if (lo_len < 0 || efi_dp_check_length(fp, lo_len) < 0)
+                       break;
+               if (fp->type != DEVICE_PATH_TYPE_MEDIA_DEVICE ||
+                   fp->sub_type != DEVICE_PATH_SUB_TYPE_VENDOR_PATH)
+                       continue;
+
+               vendor = (struct efi_device_path_vendor *)fp;
+               if (!guidcmp(&vendor->guid, &guid))
+                       return efi_dp_dup(fp);
+       }
+       log_debug("VenMedia(%pUl) not found in %ls\n", &guid, lo->label);
+
+       return NULL;
+}
diff --git a/lib/efi_loader/efi_esrt.c b/lib/efi_loader/efi_esrt.c
new file mode 100644 (file)
index 0000000..947bdb5
--- /dev/null
@@ -0,0 +1,510 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  EFI application ESRT tables support
+ *
+ *  Copyright (C) 2021 Arm Ltd.
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <log.h>
+#include <efi_api.h>
+#include <malloc.h>
+
+const efi_guid_t efi_esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
+
+static struct efi_system_resource_table *esrt;
+
+#define EFI_ESRT_VERSION 1
+
+/**
+ * efi_esrt_image_info_to_entry() - copy the information present in a fw image
+ * descriptor to a ESRT entry.
+ * The function ensures the ESRT entry matches the image_type_id in @img_info.
+ * In case of a mismatch we leave the entry unchanged.
+ *
+ * @img_info:     the source image info descriptor
+ * @entry:        pointer to the ESRT entry to be filled
+ * @desc_version: the version of the elements in img_info
+ * @image_type:   the image type value to be set in the ESRT entry
+ * @flags:        the capsule flags value to be set in the ESRT entry
+ *
+ * Return:
+ * - EFI_SUCCESS if the entry is correctly updated
+ * - EFI_INVALID_PARAMETER if entry does not match image_type_id in @img_info.
+ */
+static efi_status_t
+efi_esrt_image_info_to_entry(struct efi_firmware_image_descriptor *img_info,
+                            struct efi_system_resource_entry *entry,
+                            u32 desc_version, u32 image_type, u32 flags)
+{
+       if (guidcmp(&entry->fw_class, &img_info->image_type_id)) {
+               EFI_PRINT("ESRT entry %pUL mismatches img_type_id %pUL\n",
+                         &entry->fw_class, &img_info->image_type_id);
+               return EFI_INVALID_PARAMETER;
+       }
+
+       entry->fw_version = img_info->version;
+
+       entry->fw_type = image_type;
+       entry->capsule_flags = flags;
+
+       /*
+        * The field lowest_supported_image_version is only present
+        * on image info structure of version 2 or greater.
+        * See the EFI_FIRMWARE_IMAGE_DESCRIPTOR definition in UEFI.
+        */
+       if (desc_version >= 2)
+               entry->lowest_supported_fw_version =
+                       img_info->lowest_supported_image_version;
+       else
+               entry->lowest_supported_fw_version = 0;
+
+       /*
+        * The fields last_attempt_version and last_attempt_status
+        * are only present on image info structure of version 3 or
+        * greater.
+        * See the EFI_FIRMWARE_IMAGE_DESCRIPTOR definition in UEFI.
+        */
+       if (desc_version >= 3) {
+               entry->last_attempt_version =
+                       img_info->last_attempt_version;
+
+               entry->last_attempt_status =
+                       img_info->last_attempt_status;
+       } else {
+               entry->last_attempt_version = 0;
+               entry->last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
+       }
+
+       return EFI_SUCCESS;
+}
+
+/**
+ * efi_esrt_entries_to_size() - Obtain the bytes used by an ESRT
+ * datastructure with @num_entries.
+ *
+ * @num_entries: the number of entries in the ESRT.
+ *
+ * Return: the number of bytes an ESRT with @num_entries occupies in memory.
+ */
+static
+inline u32 efi_esrt_entries_to_size(u32 num_entries)
+{
+       u32 esrt_size = sizeof(struct efi_system_resource_table) +
+               num_entries * sizeof(struct efi_system_resource_entry);
+
+       return esrt_size;
+}
+
+/**
+ * efi_esrt_allocate_install() - Allocates @num_entries for the ESRT and
+ * performs basic ESRT initialization.
+ *
+ * @num_entries: the number of entries that the ESRT will hold.
+ *
+ * Return:
+ * - pointer to the ESRT if successful.
+ * - NULL otherwise.
+ */
+static
+efi_status_t efi_esrt_allocate_install(u32 num_entries)
+{
+       efi_status_t ret;
+       struct efi_system_resource_table *new_esrt;
+       u32 size = efi_esrt_entries_to_size(num_entries);
+       efi_guid_t esrt_guid = efi_esrt_guid;
+
+       /* Reserve num_pages for ESRT */
+       ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, size,
+                               (void **)&new_esrt);
+
+       if (ret != EFI_SUCCESS) {
+               EFI_PRINT("ESRT cannot allocate memory for %d entries (%d bytes)\n",
+                         num_entries, efi_esrt_entries_to_size(num_entries));
+
+               return ret;
+       }
+
+       new_esrt->fw_resource_count_max = num_entries;
+       new_esrt->fw_resource_count = 0;
+       new_esrt->fw_resource_version = EFI_ESRT_VERSION;
+
+       /* Install the ESRT in the system configuration table. */
+       ret = efi_install_configuration_table(&esrt_guid, (void *)new_esrt);
+       if (ret != EFI_SUCCESS) {
+               EFI_PRINT("ESRT failed to install the ESRT in the system table\n");
+               return ret;
+       }
+
+       /* If there was a previous ESRT, deallocate its memory now. */
+       if (esrt)
+               ret = EFI_CALL(efi_free_pool(esrt));
+
+       esrt = new_esrt;
+
+       return EFI_SUCCESS;
+}
+
+/**
+ * esrt_find_entry() - Obtain the ESRT entry for the image with GUID
+ * @img_fw_class.
+ *
+ * If the img_fw_class is not yet present in the ESRT, this function
+ * reserves the tail element of the current ESRT as the entry for that fw_class.
+ * The number of elements in the ESRT is updated in that case.
+ *
+ * @img_fw_class: the GUID of the FW image which ESRT entry we want to obtain.
+ *
+ * Return:
+ *  - A pointer to the ESRT entry for the image with GUID img_fw_class,
+ *  - NULL if:
+ *   - there is no more space in the ESRT,
+ *   - ESRT is not initialized,
+ */
+static
+struct efi_system_resource_entry *esrt_find_entry(efi_guid_t *img_fw_class)
+{
+       u32 filled_entries;
+       u32 max_entries;
+       struct efi_system_resource_entry *entry;
+
+       if (!esrt) {
+               EFI_PRINT("ESRT access before initialized\n");
+               return NULL;
+       }
+
+       filled_entries = esrt->fw_resource_count;
+       entry = esrt->entries;
+
+       /* Check if the image with img_fw_class is already in the ESRT. */
+       for (u32 idx = 0; idx < filled_entries; idx++) {
+               if (!guidcmp(&entry[idx].fw_class, img_fw_class)) {
+                       EFI_PRINT("ESRT found entry for image %pUl at index %d\n",
+                                 img_fw_class, idx);
+                       return &entry[idx];
+               }
+       }
+
+       max_entries = esrt->fw_resource_count_max;
+       /*
+        * Since the image with img_fw_class is not present in the ESRT, check
+        * if ESRT is full before appending the new entry to it.
+        */
+       if (filled_entries == max_entries) {
+               EFI_PRINT("ESRT full, this should not happen\n");
+               return NULL;
+       }
+
+       /*
+        * This is a new entry for a fw image, increment the element
+        * number in the table and set the fw_class field.
+        */
+       esrt->fw_resource_count++;
+       entry[filled_entries].fw_class = *img_fw_class;
+       EFI_PRINT("ESRT allocated new entry for image %pUl at index %d\n",
+                 img_fw_class, filled_entries);
+
+       return &entry[filled_entries];
+}
+
+/**
+ * efi_esrt_add_from_fmp() - Populates a sequence of ESRT entries from the FW
+ * images in the FMP.
+ *
+ * @fmp: the FMP instance from which FW images are added to the ESRT
+ *
+ * Return:
+ * - EFI_SUCCESS if all the FW images in the FMP are added to the ESRT
+ * - Error status otherwise
+ */
+static
+efi_status_t efi_esrt_add_from_fmp(struct efi_firmware_management_protocol *fmp)
+{
+       struct efi_system_resource_entry *entry = NULL;
+       size_t info_size = 0;
+       struct efi_firmware_image_descriptor *img_info = NULL;
+       u32 desc_version;
+       u8 desc_count;
+       size_t desc_size;
+       u32 package_version;
+       u16 *package_version_name;
+       efi_status_t ret = EFI_SUCCESS;
+
+       /*
+        * TODO: set the field image_type depending on the FW image type
+        * defined in a platform basis.
+        */
+       u32 image_type = ESRT_FW_TYPE_UNKNOWN;
+
+       /* TODO: set the capsule flags as a function of the FW image type. */
+       u32 flags = 0;
+
+       ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, img_info,
+                                          &desc_version, &desc_count,
+                                          &desc_size, NULL, NULL));
+
+       if (ret != EFI_BUFFER_TOO_SMALL) {
+               /*
+                * An input of info_size=0 should always lead
+                * fmp->get_image_info to return BUFFER_TO_SMALL.
+                */
+               EFI_PRINT("Erroneous FMP implementation\n");
+               return EFI_INVALID_PARAMETER;
+       }
+
+       ret = EFI_CALL(efi_allocate_pool(EFI_BOOT_SERVICES_DATA, info_size,
+                                        (void **)&img_info));
+       if (ret != EFI_SUCCESS) {
+               EFI_PRINT("ESRT failed to allocate memory for image info.\n");
+               return ret;
+       }
+
+       ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, img_info,
+                                          &desc_version, &desc_count,
+                                          &desc_size, &package_version,
+                                          &package_version_name));
+       if (ret != EFI_SUCCESS) {
+               EFI_PRINT("ESRT failed to obtain the FMP image info\n");
+               goto out;
+       }
+
+       /*
+        * Iterate over all the FW images in the FMP.
+        */
+       for (u32 desc_idx = 0; desc_idx < desc_count; desc_idx++) {
+               struct efi_firmware_image_descriptor *cur_img_info =
+                       (struct efi_firmware_image_descriptor *)
+                       ((uintptr_t)img_info + desc_idx * desc_size);
+
+               /*
+                * Obtain the ESRT entry for the FW image with fw_class
+                * equal to cur_img_info->image_type_id.
+                */
+               entry = esrt_find_entry(&cur_img_info->image_type_id);
+
+               if (entry) {
+                       ret = efi_esrt_image_info_to_entry(cur_img_info, entry,
+                                                          desc_version,
+                                                          image_type, flags);
+                       if (ret != EFI_SUCCESS)
+                               EFI_PRINT("ESRT entry mismatches image_type\n");
+
+               } else {
+                       EFI_PRINT("ESRT failed to add entry for %pUl\n",
+                                 &cur_img_info->image_type_id);
+                       continue;
+               }
+       }
+
+out:
+       EFI_CALL(efi_free_pool(img_info));
+       return EFI_SUCCESS;
+}
+
+/**
+ * efi_esrt_populate() - Populates the ESRT entries from the FMP instances
+ * present in the system.
+ * If an ESRT already exists, the old ESRT is replaced in the system table.
+ * The memory of the old ESRT is deallocated.
+ *
+ * Return:
+ * - EFI_SUCCESS if the ESRT is correctly created
+ * - error code otherwise.
+ */
+efi_status_t efi_esrt_populate(void)
+{
+       efi_handle_t *base_handle = NULL;
+       efi_handle_t *it_handle;
+       size_t no_handles = 0;
+       struct efi_firmware_management_protocol *fmp;
+       efi_status_t ret;
+       u32 num_entries = 0;
+       struct efi_handler *handler;
+
+       /*
+        * Obtain the number of registered FMP handles.
+        */
+       ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL,
+                                               &efi_guid_firmware_management_protocol,
+                                               NULL, &no_handles,
+                                               (efi_handle_t **)&base_handle));
+
+       if (ret != EFI_SUCCESS) {
+               EFI_PRINT("ESRT There are no FMP instances\n");
+
+               ret = efi_esrt_allocate_install(0);
+               if (ret != EFI_SUCCESS) {
+                       EFI_PRINT("ESRT failed to create table with 0 entries\n");
+                       return ret;
+               }
+               return EFI_SUCCESS;
+       }
+
+       EFI_PRINT("ESRT populate esrt from (%ld) available FMP handles\n",
+                 no_handles);
+
+       /*
+        * Iterate over all FMPs to determine an upper bound on the number of
+        * ESRT entries.
+        */
+       it_handle = base_handle;
+       for (u32 idx = 0; idx < no_handles; idx++, it_handle++) {
+               struct efi_firmware_image_descriptor *img_info = NULL;
+               size_t info_size = 0;
+               u32 desc_version = 0;
+               u8 desc_count = 0;
+               size_t desc_size = 0;
+               u32 package_version;
+               u16 *package_version_name;
+
+               ret = efi_search_protocol(*it_handle,
+                                         &efi_guid_firmware_management_protocol,
+                                         &handler);
+
+               if (ret != EFI_SUCCESS) {
+                       EFI_PRINT("ESRT Unable to find FMP handle (%d)\n",
+                                 idx);
+                       goto out;
+               }
+               fmp = handler->protocol_interface;
+
+               ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, NULL,
+                                                  &desc_version, &desc_count,
+                                                  &desc_size, &package_version,
+                                                  &package_version_name));
+
+               if (ret != EFI_BUFFER_TOO_SMALL) {
+                       /*
+                        * An input of info_size=0 should always lead
+                        * fmp->get_image_info to return BUFFER_TO_SMALL.
+                        */
+                       EFI_PRINT("ESRT erroneous FMP implementation\n");
+                       ret = EFI_INVALID_PARAMETER;
+                       goto out;
+               }
+
+               ret = EFI_CALL(efi_allocate_pool(EFI_BOOT_SERVICES_DATA, info_size,
+                                                (void **)&img_info));
+               if (ret != EFI_SUCCESS) {
+                       EFI_PRINT("ESRT failed to allocate memory for image info\n");
+                       goto out;
+               }
+
+               /*
+                * Calls to a FMP get_image_info method do not return the
+                * desc_count value if the return status differs from EFI_SUCCESS.
+                * We need to repeat the call to get_image_info with a properly
+                * sized buffer in order to obtain the real number of images
+                * handled by the FMP.
+                */
+               ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, img_info,
+                                                  &desc_version, &desc_count,
+                                                  &desc_size, &package_version,
+                                                  &package_version_name));
+
+               if (ret != EFI_SUCCESS) {
+                       EFI_PRINT("ESRT failed to obtain image info from FMP\n");
+                       EFI_CALL(efi_free_pool(img_info));
+                       goto out;
+               }
+
+               num_entries += desc_count;
+
+               EFI_CALL(efi_free_pool(img_info));
+       }
+
+       EFI_PRINT("ESRT create table with %d entries\n", num_entries);
+       /*
+        * Allocate an ESRT with the sufficient number of entries to accommodate
+        * all the FMPs in the system.
+        */
+       ret = efi_esrt_allocate_install(num_entries);
+       if (ret != EFI_SUCCESS) {
+               EFI_PRINT("ESRT failed to initialize table\n");
+               goto out;
+       }
+
+       /*
+        * Populate the ESRT entries with all existing FMP.
+        */
+       it_handle = base_handle;
+       for (u32 idx = 0; idx < no_handles; idx++, it_handle++) {
+               ret = EFI_CALL(efi_search_protocol(*it_handle,
+                                                  &efi_guid_firmware_management_protocol,
+                                                  &handler));
+
+               if (ret != EFI_SUCCESS) {
+                       EFI_PRINT("ESRT unable to find FMP handle (%d)\n",
+                                 idx);
+                       break;
+               }
+               fmp = handler->protocol_interface;
+
+               ret = efi_esrt_add_from_fmp(fmp);
+               if (ret != EFI_SUCCESS)
+                       EFI_PRINT("ESRT failed to add FMP to the table\n");
+       }
+
+out:
+
+       EFI_CALL(efi_free_pool(base_handle));
+
+       return ret;
+}
+
+/**
+ * efi_esrt_new_fmp_notify() - Callback for the EVT_NOTIFY_SIGNAL event raised
+ * when a new FMP protocol instance is registered in the system.
+ */
+static void EFIAPI efi_esrt_new_fmp_notify(struct efi_event *event,
+                                          void *context)
+{
+       efi_status_t ret;
+
+       EFI_ENTRY();
+
+       ret = efi_esrt_populate();
+       if (ret != EFI_SUCCESS)
+               EFI_PRINT("ESRT failed to populate ESRT entry\n");
+
+       EFI_EXIT(ret);
+}
+
+/**
+ * efi_esrt_register() - Install the ESRT system table.
+ *
+ * Return: status code
+ */
+efi_status_t efi_esrt_register(void)
+{
+       struct efi_event *ev = NULL;
+       void *registration;
+       efi_status_t ret;
+
+       EFI_PRINT("ESRT creation start\n");
+
+       ret = efi_esrt_populate();
+       if (ret != EFI_SUCCESS) {
+               EFI_PRINT("ESRT failed to initiate the table\n");
+               return ret;
+       }
+
+       ret = EFI_CALL(efi_create_event(EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+                                       efi_esrt_new_fmp_notify, NULL, NULL, &ev));
+       if (ret != EFI_SUCCESS) {
+               EFI_PRINT("ESRT failed to create event\n");
+               return ret;
+       }
+
+       ret = EFI_CALL(efi_register_protocol_notify(&efi_guid_firmware_management_protocol,
+                                                   ev, &registration));
+       if (ret != EFI_SUCCESS) {
+               EFI_PRINT("ESRT failed to register FMP callback\n");
+               return ret;
+       }
+
+       EFI_PRINT("ESRT table created\n");
+
+       return ret;
+}
index 8ece8e7..204105e 100644 (file)
@@ -409,6 +409,45 @@ static efi_status_t efi_get_file_size(struct file_handle *fh,
        return EFI_SUCCESS;
 }
 
+/**
+ * efi_file_size() - Get the size of a file using an EFI file handle
+ *
+ * @fh:                EFI file handle
+ * @size:      buffer to fill in the discovered size
+ *
+ * Return:     size of the file
+ */
+efi_status_t efi_file_size(struct efi_file_handle *fh, efi_uintn_t *size)
+{
+       struct efi_file_info *info = NULL;
+       efi_uintn_t bs = 0;
+       efi_status_t ret;
+
+       *size = 0;
+       ret = EFI_CALL(fh->getinfo(fh, (efi_guid_t *)&efi_file_info_guid, &bs,
+                                  info));
+       if (ret != EFI_BUFFER_TOO_SMALL) {
+               ret = EFI_DEVICE_ERROR;
+               goto out;
+       }
+
+       info = malloc(bs);
+       if (!info) {
+               ret = EFI_OUT_OF_RESOURCES;
+               goto out;
+       }
+       ret = EFI_CALL(fh->getinfo(fh, (efi_guid_t *)&efi_file_info_guid, &bs,
+                                  info));
+       if (ret != EFI_SUCCESS)
+               goto out;
+
+       *size = info->file_size;
+
+out:
+       free(info);
+       return ret;
+}
+
 static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size,
                void *buffer)
 {
diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c
new file mode 100644 (file)
index 0000000..d03a736
--- /dev/null
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020, Linaro Limited
+ */
+
+#define LOG_CATEGORY LOGC_EFI
+#include <common.h>
+#include <env.h>
+#include <malloc.h>
+#include <dm.h>
+#include <fs.h>
+#include <efi_load_initrd.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
+
+/**
+ * efi_create_current_boot_var() - Return Boot#### name were #### is replaced by
+ *                                the value of BootCurrent
+ *
+ * @var_name:          variable name
+ * @var_name_size:     size of var_name
+ *
+ * Return:     Status code
+ */
+static efi_status_t efi_create_current_boot_var(u16 var_name[],
+                                               size_t var_name_size)
+{
+       efi_uintn_t boot_current_size;
+       efi_status_t ret;
+       u16 boot_current;
+       u16 *pos;
+
+       boot_current_size = sizeof(boot_current);
+       ret = efi_get_variable_int(L"BootCurrent",
+                                  &efi_global_variable_guid, NULL,
+                                  &boot_current_size, &boot_current, NULL);
+       if (ret != EFI_SUCCESS)
+               goto out;
+
+       pos = efi_create_indexed_name(var_name, var_name_size, "Boot",
+                                     boot_current);
+       if (!pos) {
+               ret = EFI_OUT_OF_RESOURCES;
+               goto out;
+       }
+
+out:
+       return ret;
+}
+
+/**
+ * efi_get_dp_from_boot() - Retrieve and return a device path from an EFI
+ *                         Boot### variable.
+ *                         A boot option may contain an array of device paths.
+ *                         We use a VenMedia() with a specific GUID to identify
+ *                         the usage of the array members. This function is
+ *                         used to extract a specific device path
+ *
+ * @guid:      vendor GUID of the VenMedia() device path node identifying the
+ *             device path
+ *
+ * Return:     device path or NULL. Caller must free the returned value
+ */
+struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid)
+{
+       struct efi_device_path *file_path = NULL;
+       struct efi_device_path *tmp = NULL;
+       struct efi_load_option lo;
+       void *var_value = NULL;
+       efi_uintn_t size;
+       efi_status_t ret;
+       u16 var_name[16];
+
+       ret = efi_create_current_boot_var(var_name, sizeof(var_name));
+       if (ret != EFI_SUCCESS)
+               return NULL;
+
+       var_value = efi_get_var(var_name, &efi_global_variable_guid, &size);
+       if (!var_value)
+               return NULL;
+
+       ret = efi_deserialize_load_option(&lo, var_value, &size);
+       if (ret != EFI_SUCCESS)
+               goto out;
+
+       tmp = efi_dp_from_lo(&lo, &size, guid);
+       if (!tmp)
+               goto out;
+
+       /* efi_dp_dup will just return NULL if efi_dp_next is NULL */
+       file_path = efi_dp_dup(efi_dp_next(tmp));
+
+out:
+       efi_free_pool(tmp);
+       free(var_value);
+
+       return file_path;
+}
index b9ee883..e2a8063 100644 (file)
@@ -3,9 +3,11 @@
  * Copyright (c) 2020, Linaro Limited
  */
 
+#define LOG_CATEGORY LOGC_EFI
 #include <common.h>
 #include <efi_loader.h>
 #include <efi_load_initrd.h>
+#include <efi_variable.h>
 #include <fs.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -23,57 +25,56 @@ static const struct efi_load_file_protocol efi_lf2_protocol = {
  * Device path defined by Linux to identify the handle providing the
  * EFI_LOAD_FILE2_PROTOCOL used for loading the initial ramdisk.
  */
-static const struct efi_initrd_dp dp = {
+static const struct efi_initrd_dp dp_lf2_handle = {
        .vendor = {
                {
                   DEVICE_PATH_TYPE_MEDIA_DEVICE,
                   DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
-                  sizeof(dp.vendor),
+                  sizeof(dp_lf2_handle.vendor),
                },
                EFI_INITRD_MEDIA_GUID,
        },
        .end = {
                DEVICE_PATH_TYPE_END,
                DEVICE_PATH_SUB_TYPE_END,
-               sizeof(dp.end),
+               sizeof(dp_lf2_handle.end),
        }
 };
 
+static efi_handle_t efi_initrd_handle;
+
 /**
- * get_file_size() - retrieve the size of initramfs, set efi status on error
+ * get_initrd_fp() - Get initrd device path from a FilePathList device path
  *
- * @dev:                       device to read from, e.g. "mmc"
- * @part:                      device partition, e.g. "0:1"
- * @file:                      name of file
- * @status:                    EFI exit code in case of failure
+ * @initrd_fp: the final initrd filepath
  *
- * Return:                     size of file
+ * Return:     status code. Caller must free initrd_fp
  */
-static loff_t get_file_size(const char *dev, const char *part, const char *file,
-                           efi_status_t *status)
+static efi_status_t get_initrd_fp(struct efi_device_path **initrd_fp)
 {
-       loff_t sz = 0;
-       int ret;
-
-       ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
-       if (ret) {
-               *status = EFI_NO_MEDIA;
-               goto out;
-       }
+       const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
+       struct efi_device_path *dp = NULL;
 
-       ret = fs_size(file, &sz);
-       if (ret) {
-               sz = 0;
-               *status = EFI_NOT_FOUND;
-               goto out;
-       }
+       /*
+        * if bootmgr is setup with and initrd, the device path will be
+        * in the FilePathList[] of our load options in Boot####.
+        * The first device path of the multi instance device path will
+        * start with a VenMedia and the initrds will follow.
+        *
+        * If the device path is not found return EFI_INVALID_PARAMETER.
+        * We can then use this specific return value and not install the
+        * protocol, while allowing the boot to continue
+        */
+       dp = efi_get_dp_from_boot(lf2_initrd_guid);
+       if (!dp)
+               return EFI_INVALID_PARAMETER;
 
-out:
-       return sz;
+       *initrd_fp = dp;
+       return EFI_SUCCESS;
 }
 
 /**
- * efi_load_file2initrd() - load initial RAM disk
+ * efi_load_file2_initrd() - load initial RAM disk
  *
  * This function implements the LoadFile service of the EFI_LOAD_FILE2_PROTOCOL
  * in order to load an initial RAM disk requested by the Linux kernel stub.
@@ -93,102 +94,125 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this,
                      struct efi_device_path *file_path, bool boot_policy,
                      efi_uintn_t *buffer_size, void *buffer)
 {
-       char *filespec;
-       efi_status_t status = EFI_NOT_FOUND;
-       loff_t file_sz = 0, read_sz = 0;
-       char *dev, *part, *file;
-       char *pos;
-       int ret;
+       struct efi_device_path *initrd_fp = NULL;
+       efi_status_t ret = EFI_NOT_FOUND;
+       struct efi_file_handle *f = NULL;
+       efi_uintn_t bs;
 
        EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy,
                  buffer_size, buffer);
 
-       filespec = strdup(CONFIG_EFI_INITRD_FILESPEC);
-       if (!filespec)
-               goto out;
-       pos = filespec;
-
        if (!this || this != &efi_lf2_protocol ||
            !buffer_size) {
-               status = EFI_INVALID_PARAMETER;
+               ret = EFI_INVALID_PARAMETER;
                goto out;
        }
 
-       if (file_path->type != dp.end.type ||
-           file_path->sub_type != dp.end.sub_type) {
-               status = EFI_INVALID_PARAMETER;
+       if (file_path->type != dp_lf2_handle.end.type ||
+           file_path->sub_type != dp_lf2_handle.end.sub_type) {
+               ret = EFI_INVALID_PARAMETER;
                goto out;
        }
 
        if (boot_policy) {
-               status = EFI_UNSUPPORTED;
+               ret = EFI_UNSUPPORTED;
                goto out;
        }
 
-       /*
-        * expect a string with three space separated parts:
-        *
-        * * a block device type, e.g. "mmc"
-        * * a device and partition identifier, e.g. "0:1"
-        * * a file path on the block device, e.g. "/boot/initrd.cpio.gz"
-        */
-       dev = strsep(&pos, " ");
-       if (!dev)
+       ret = get_initrd_fp(&initrd_fp);
+       if (ret != EFI_SUCCESS)
                goto out;
-       part = strsep(&pos, " ");
-       if (!part)
-               goto out;
-       file = strsep(&pos, " ");
-       if (!file)
+
+       /* Open file */
+       f = efi_file_from_path(initrd_fp);
+       if (!f) {
+               log_err("Can't find initrd specified in Boot####\n");
+               ret = EFI_NOT_FOUND;
                goto out;
+       }
 
-       file_sz = get_file_size(dev, part, file, &status);
-       if (!file_sz)
+       /* Get file size */
+       ret = efi_file_size(f, &bs);
+       if (ret != EFI_SUCCESS)
                goto out;
 
-       if (!buffer || *buffer_size < file_sz) {
-               status = EFI_BUFFER_TOO_SMALL;
-               *buffer_size = file_sz;
+       if (!buffer || *buffer_size < bs) {
+               ret = EFI_BUFFER_TOO_SMALL;
+               *buffer_size = bs;
        } else {
-               ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
-               if (ret) {
-                       status = EFI_NO_MEDIA;
-                       goto out;
-               }
-
-               ret = fs_read(file, map_to_sysmem(buffer), 0, *buffer_size,
-                             &read_sz);
-               if (ret || read_sz != file_sz)
-                       goto out;
-               *buffer_size = read_sz;
-
-               status = EFI_SUCCESS;
+               ret = EFI_CALL(f->read(f, &bs, (void *)(uintptr_t)buffer));
+               *buffer_size = bs;
+       }
+
+out:
+       efi_free_pool(initrd_fp);
+       if (f)
+               EFI_CALL(f->close(f));
+       return EFI_EXIT(ret);
+}
+
+/**
+ * check_initrd() - Determine if the file defined as an initrd in Boot####
+ *                 load_options device path is present
+ *
+ * Return:     status code
+ */
+static efi_status_t check_initrd(void)
+{
+       struct efi_device_path *initrd_fp = NULL;
+       struct efi_file_handle *f;
+       efi_status_t ret;
+
+       ret = get_initrd_fp(&initrd_fp);
+       if (ret != EFI_SUCCESS)
+               goto out;
+
+       /*
+        * If the file is not found, but the file path is set, return an error
+        * and trigger the bootmgr fallback
+        */
+       f = efi_file_from_path(initrd_fp);
+       if (!f) {
+               log_err("Can't find initrd specified in Boot####\n");
+               ret = EFI_NOT_FOUND;
+               goto out;
        }
 
+       EFI_CALL(f->close(f));
+
 out:
-       free(filespec);
-       return EFI_EXIT(status);
+       efi_free_pool(initrd_fp);
+       return ret;
 }
 
 /**
  * efi_initrd_register() - create handle for loading initial RAM disk
  *
  * This function creates a new handle and installs a Linux specific vendor
- * device path and an EFI_LOAD_FILE_2_PROTOCOL. Linux uses the device path
+ * device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path
  * to identify the handle and then calls the LoadFile service of the
- * EFI_LOAD_FILE_2_PROTOCOL to read the initial RAM disk.
+ * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk.
  *
  * Return:     status code
  */
 efi_status_t efi_initrd_register(void)
 {
-       efi_handle_t efi_initrd_handle = NULL;
        efi_status_t ret;
 
+       /*
+        * Allow the user to continue if Boot#### file path is not set for
+        * an initrd
+        */
+       ret = check_initrd();
+       if (ret == EFI_INVALID_PARAMETER)
+               return EFI_SUCCESS;
+       if (ret != EFI_SUCCESS)
+               return ret;
+
        ret = EFI_CALL(efi_install_multiple_protocol_interfaces
                       (&efi_initrd_handle,
                        /* initramfs */
-                       &efi_guid_device_path, &dp,
+                       &efi_guid_device_path, &dp_lf2_handle,
                        /* LOAD_FILE2 */
                        &efi_guid_load_file2_protocol,
                        (void *)&efi_lf2_protocol,
@@ -196,3 +220,17 @@ efi_status_t efi_initrd_register(void)
 
        return ret;
 }
+
+/**
+ * efi_initrd_deregister() - delete the handle for loading initial RAM disk
+ *
+ * This will delete the handle containing the Linux specific vendor device
+ * path and EFI_LOAD_FILE2_PROTOCOL for loading an initrd
+ *
+ * Return:     status code
+ */
+void efi_initrd_deregister(void)
+{
+       efi_delete_handle(efi_initrd_handle);
+       efi_initrd_handle = NULL;
+}
index b1c5125..3c5cf9a 100644 (file)
@@ -227,6 +227,12 @@ efi_status_t efi_init_obj_list(void)
        if (ret != EFI_SUCCESS)
                goto out;
 
+       if (IS_ENABLED(CONFIG_EFI_ESRT)) {
+               ret = efi_esrt_register();
+               if (ret != EFI_SUCCESS)
+                       goto out;
+       }
+
        if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) {
                ret = efi_tcg2_register();
                if (ret != EFI_SUCCESS)
index 797d6eb..0904684 100644 (file)
@@ -13,6 +13,7 @@
 #include <efi_loader.h>
 #include <efi_tcg2.h>
 #include <log.h>
+#include <version.h>
 #include <tpm-v2.h>
 #include <u-boot/sha1.h>
 #include <u-boot/sha256.h>
@@ -958,6 +959,23 @@ out:
 }
 
 /**
+ * tcg2_uninit - remove the final event table and free efi memory on failures
+ */
+void tcg2_uninit(void)
+{
+       efi_status_t ret;
+
+       ret = efi_install_configuration_table(&efi_guid_final_events, NULL);
+       if (ret != EFI_SUCCESS)
+               log_err("Failed to delete final events config table\n");
+
+       efi_free_pool(event_log.buffer);
+       event_log.buffer = NULL;
+       efi_free_pool(event_log.final_buffer);
+       event_log.final_buffer = NULL;
+}
+
+/**
  * create_final_event() - Create the final event and install the config
  *                     defined by the TCG EFI spec
  */
@@ -983,10 +1001,6 @@ static efi_status_t create_final_event(void)
        event_log.final_pos = sizeof(*final_event);
        ret = efi_install_configuration_table(&efi_guid_final_events,
                                              final_event);
-       if (ret != EFI_SUCCESS)
-               goto out;
-
-       return EFI_SUCCESS;
 out:
        return ret;
 }
@@ -1041,6 +1055,40 @@ static efi_status_t efi_init_event_log(void)
        event_log.last_event_size = event_log.pos;
 
        ret = create_final_event();
+       if (ret != EFI_SUCCESS)
+               goto out;
+
+       return EFI_SUCCESS;
+out:
+       tcg2_uninit();
+       return ret;
+}
+
+/**
+ * efi_append_scrtm_version - Append an S-CRTM EV_S_CRTM_VERSION event on the
+ *                           eventlog and extend the PCRs
+ *
+ * @dev:       TPM device
+ *
+ * @Return:    status code
+ */
+static efi_status_t efi_append_scrtm_version(struct udevice *dev)
+{
+       struct tpml_digest_values digest_list;
+       u8 ver[] = U_BOOT_VERSION_STRING;
+       const int pcr_index = 0;
+       efi_status_t ret;
+
+       ret = tcg2_create_digest(ver, sizeof(ver), &digest_list);
+       if (ret != EFI_SUCCESS)
+               goto out;
+
+       ret = tcg2_pcr_extend(dev, pcr_index, &digest_list);
+       if (ret != EFI_SUCCESS)
+               goto out;
+
+       ret = tcg2_agile_log_append(pcr_index, EV_S_CRTM_VERSION, &digest_list,
+                                   sizeof(ver), ver);
 
 out:
        return ret;
@@ -1055,23 +1103,34 @@ out:
  */
 efi_status_t efi_tcg2_register(void)
 {
-       efi_status_t ret;
+       efi_status_t ret = EFI_SUCCESS;
        struct udevice *dev;
 
        ret = platform_get_tpm2_device(&dev);
        if (ret != EFI_SUCCESS) {
                log_warning("Unable to find TPMv2 device\n");
-               return EFI_SUCCESS;
+               ret = EFI_SUCCESS;
+               goto out;
        }
 
        ret = efi_init_event_log();
        if (ret != EFI_SUCCESS)
-               return ret;
+               goto fail;
+
+       ret = efi_append_scrtm_version(dev);
+       if (ret != EFI_SUCCESS)
+               goto out;
 
        ret = efi_add_protocol(efi_root, &efi_guid_tcg2_protocol,
                               (void *)&efi_tcg2_protocol);
-       if (ret != EFI_SUCCESS)
+       if (ret != EFI_SUCCESS) {
                log_err("Cannot install EFI_TCG2_PROTOCOL\n");
+               goto fail;
+       }
 
+out:
+       return ret;
+fail:
+       tcg2_uninit();
        return ret;
 }
index 1c74592..b11ed91 100644 (file)
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
+#include <stdlib.h>
 
 enum efi_secure_mode {
        EFI_MODE_SETUP,
@@ -343,3 +344,35 @@ enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid)
        }
        return EFI_AUTH_VAR_NONE;
 }
+
+/**
+ * efi_get_var() - read value of an EFI variable
+ *
+ * @name:      variable name
+ * @start:     vendor GUID
+ * @size:      size of allocated buffer
+ *
+ * Return:     buffer with variable data or NULL
+ */
+void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size)
+{
+       efi_status_t ret;
+       void *buf = NULL;
+
+       *size = 0;
+       ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
+       if (ret == EFI_BUFFER_TOO_SMALL) {
+               buf = malloc(*size);
+               if (!buf)
+                       return NULL;
+               ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
+       }
+
+       if (ret != EFI_SUCCESS) {
+               free(buf);
+               *size = 0;
+               return NULL;
+       }
+
+       return buf;
+}
index 50de581..aa71d09 100644 (file)
@@ -71,6 +71,8 @@ ifeq ($(CONFIG_BLK)$(CONFIG_DOS_PARTITION),yy)
 obj-y += efi_selftest_block_device.o
 endif
 
+obj-$(CONFIG_EFI_ESRT) += efi_selftest_esrt.o
+
 targets += \
 efi_miniapp_file_image_exception.h \
 efi_miniapp_file_image_exit.h \
index b8eed04..39ee2ed 100644 (file)
@@ -160,7 +160,7 @@ static bool need_reset(const u16 *testname)
                if (testname && efi_st_strcmp_16_8(testname, test->name))
                        continue;
                if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT ||
-                   test->phase == EFI_SETUP_AFTER_BOOTTIME_EXIT)
+                   test->phase == EFI_SETTING_VIRTUAL_ADDRESS_MAP)
                        return true;
        }
        return false;
@@ -327,15 +327,16 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
        /* Execute mixed tests */
        efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT,
                        EFI_ST_SETUP, &failures);
+       efi_st_do_tests(testname, EFI_SETTING_VIRTUAL_ADDRESS_MAP,
+                       EFI_ST_SETUP, &failures);
 
        efi_st_exit_boot_services();
 
        efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT,
                        EFI_ST_EXECUTE | EFI_ST_TEARDOWN, &failures);
-
-       /* Execute runtime tests */
-       efi_st_do_tests(testname, EFI_SETUP_AFTER_BOOTTIME_EXIT,
-                       EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
+       /* Execute test setting the virtual address map */
+       efi_st_do_tests(testname, EFI_SETTING_VIRTUAL_ADDRESS_MAP,
+                       EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
                        &failures);
 
        /* Give feedback */
diff --git a/lib/efi_selftest/efi_selftest_esrt.c b/lib/efi_selftest/efi_selftest_esrt.c
new file mode 100644 (file)
index 0000000..99251f2
--- /dev/null
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  Test ESRT tables support
+ *
+ *  Copyright (C) 2021 Arm Ltd.
+ */
+#include <common.h>
+#include <efi_loader.h>
+#include <efi_selftest.h>
+
+// This value must not exceed 255.
+// An FMP cannot contain more than 255 FW images.
+#define TEST_ESRT_NUM_ENTRIES 255
+
+static
+struct efi_firmware_image_descriptor static_img_info[TEST_ESRT_NUM_ENTRIES];
+
+static const struct efi_system_table *local_systable;
+
+static efi_handle_t fmp_handle;
+
+static const efi_guid_t efi_fmp_guid =
+               EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID;
+
+static void efi_test_esrt_init_info(void)
+{
+       for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++) {
+               static_img_info[idx].image_index = idx;
+
+               // Note: the 16 byte value present in
+               // static_img_info[idx].image_type_id is not strictly a GUID.
+               // The value is used for the sake of code testing.
+               static_img_info[idx].image_type_id.b[0] = idx;
+
+               static_img_info[idx].image_id = 0;
+               static_img_info[idx].image_id_name = NULL;
+               static_img_info[idx].version = 0;
+               static_img_info[idx].version_name = NULL;
+               static_img_info[idx].size = 0;
+               static_img_info[idx].lowest_supported_image_version = 1;
+               static_img_info[idx].last_attempt_version = 2;
+               static_img_info[idx].last_attempt_status = 3;
+               static_img_info[idx].hardware_instance = 1;
+       }
+}
+
+static efi_status_t
+EFIAPI efi_test_fmp_get_image_info(struct efi_firmware_management_protocol *this,
+                                  efi_uintn_t *image_info_size,
+                                  struct efi_firmware_image_descriptor *image_info,
+                                  u32 *descriptor_version,
+                                  u8 *descriptor_count,
+                                  efi_uintn_t *descriptor_size,
+                                  u32 *package_version,
+                                  u16 **package_version_name)
+{
+       efi_status_t ret = EFI_SUCCESS;
+
+       if (!image_info_size)
+               return EFI_INVALID_PARAMETER;
+
+       if (descriptor_version)
+               *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+       if (descriptor_count)
+               *descriptor_count = TEST_ESRT_NUM_ENTRIES;
+       if (descriptor_size)
+               *descriptor_size = sizeof(*image_info);
+       if (package_version)
+               *package_version = 0xffffffff;
+       if (package_version_name)
+               *package_version_name = NULL;
+
+       if (*image_info_size < sizeof(*image_info)) {
+               *image_info_size = *descriptor_size * *descriptor_count;
+               return EFI_BUFFER_TOO_SMALL;
+       }
+
+       for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++)
+               image_info[idx] = static_img_info[idx];
+
+       return ret;
+}
+
+static struct efi_firmware_management_protocol efi_test_fmp = {
+       .get_image_info = efi_test_fmp_get_image_info,
+       .get_image = NULL,
+       .set_image = NULL,
+       .check_image = NULL,
+       .get_package_info = NULL,
+       .set_package_info = NULL,
+};
+
+static void *lib_test_get_esrt(void)
+{
+       for (int idx = 0; idx < local_systable->nr_tables; idx++)
+               if (!guidcmp(&efi_esrt_guid, &local_systable->tables[idx].guid))
+                       return local_systable->tables[idx].table;
+
+       return NULL;
+}
+
+/**
+ * lib_test_check_uuid_entry: Find an ESRT entry for which the fw_calss field matches
+ * the image_type_id in the @img_info.
+ * Ensure that all of the field in the ESRT entry have the same value as the corresponding
+ * fields in the @img_info.
+ *
+ * @esrt: pointer to the ESRT
+ * @img_info: an image_info_descriptor output by the FMP get_image_info
+ *
+ * @return: true if matching ESRT entry is found and if all the ESRT entry fields match the
+ * corresponding @img_info fields.
+ */
+static bool lib_test_check_uuid_entry(struct efi_system_resource_table *esrt,
+                                     struct efi_firmware_image_descriptor
+                                     *img_info)
+{
+       const u32 filled_entries = esrt->fw_resource_count;
+       struct efi_system_resource_entry *entry = esrt->entries;
+
+       for (u32 idx = 0; idx < filled_entries; idx++) {
+               if (!guidcmp(&entry[idx].fw_class, &img_info->image_type_id)) {
+                       if (entry[idx].fw_version != img_info->version) {
+                               efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+                                            &img_info->image_type_id);
+                               return false;
+                       }
+
+                       if (entry[idx].lowest_supported_fw_version !=
+                               img_info->lowest_supported_image_version) {
+                               efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+                                            &img_info->image_type_id);
+                               return false;
+                       }
+
+                       if (entry[idx].last_attempt_version !=
+                               img_info->last_attempt_version) {
+                               efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+                                            &img_info->image_type_id);
+                               return false;
+                       }
+
+                       if (entry[idx].last_attempt_status !=
+                               img_info->last_attempt_status) {
+                               efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+                                            &img_info->image_type_id);
+                               return false;
+                       }
+
+                       /*
+                        * The entry with fw_class = img_uuid matches with the
+                        * remainder fmp input.
+                        */
+                       return true;
+               }
+       }
+
+       /* There exists no entry with fw_class equal to img_uuid in the ESRT. */
+       efi_st_error("ESRT no entry with fw_class= %pUl\n", &img_info->image_type_id);
+
+       return false;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Initialize the test FMP datastructure.
+ *
+ * @handle:    handle of the loaded image
+ * @systable:  system table
+ * @return:    EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+                const struct efi_system_table *systable)
+{
+       local_systable = systable;
+
+       efi_test_esrt_init_info();
+
+       return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Uninstall the test FMP.
+ *
+ * @return:    EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+       efi_status_t ret = EFI_SUCCESS;
+       struct efi_boot_services *bt;
+
+       bt = local_systable->boottime;
+
+       if (!bt) {
+               efi_st_error("Cannot find boottime services structure\n");
+               return EFI_ST_FAILURE;
+       }
+
+       ret = bt->uninstall_multiple_protocol_interfaces
+               (fmp_handle, &efi_fmp_guid,
+                &efi_test_fmp, NULL);
+
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Failed to uninstall FMP\n");
+               return EFI_ST_FAILURE;
+       }
+
+       return EFI_ST_SUCCESS;
+}
+
+/*
+ * Perform the test
+ *
+ * The test consists of the following steps:
+ *
+ * 1) Obtain the ESRT
+ * 2) Record the number of ESRT entries prior to test start
+ * 3) Install the test FMP
+ * 4) Re-obtain the ESRT (the ESRT pointer may have changed with the FMP install)
+ * 5) verify that the ESRT entries have increased by the number of entries in the
+ *     test FMP.
+ * 6) Traverse all the elements used as the test FMP input and verify that each
+ *     has a corresponding ESRT entry and that the fields are correctly set.
+ *
+ * The failure of any of the above steps results in a test failure.
+ *
+ */
+static int execute(void)
+{
+       struct efi_system_resource_table *esrt;
+       efi_status_t ret = EFI_SUCCESS;
+       u32 base_entry_count;
+       u32 entry_delta;
+       struct efi_boot_services *bt;
+
+       bt = local_systable->boottime;
+
+       if (!bt) {
+               efi_st_error("Cannot find boottime services structure\n");
+               return EFI_ST_FAILURE;
+       }
+
+       esrt = lib_test_get_esrt();
+       if (!esrt) {
+               efi_st_error("ESRT table not present\n");
+               return EFI_ST_FAILURE;
+       }
+       base_entry_count = esrt->fw_resource_count;
+
+       ret = bt->install_multiple_protocol_interfaces(&fmp_handle,
+                                                      &efi_fmp_guid,
+                                                      &efi_test_fmp,
+                                                      NULL);
+
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Failed to install FMP\n");
+               return EFI_ST_FAILURE;
+       }
+
+       esrt = lib_test_get_esrt();
+       if (!esrt) {
+               efi_st_error("ESRT table not present\n");
+               return EFI_ST_FAILURE;
+       }
+
+       entry_delta = esrt->fw_resource_count - base_entry_count;
+       if (entry_delta != TEST_ESRT_NUM_ENTRIES) {
+               efi_st_error("ESRT mismatch in new entry count (%d), expected (%d).\n",
+                            entry_delta, TEST_ESRT_NUM_ENTRIES);
+               return EFI_ST_FAILURE;
+       }
+
+       for (u32 idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++)
+               if (!lib_test_check_uuid_entry(esrt, &static_img_info[idx])) {
+                       efi_st_error("ESRT entry mismatch\n");
+                       return EFI_ST_FAILURE;
+               }
+
+       return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(esrt) = {
+       .name = "esrt",
+       .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+       .setup = setup,
+       .execute = execute,
+       .teardown = teardown,
+};
index b097a81..8e2e8ba 100644 (file)
@@ -201,7 +201,7 @@ static int execute(void)
 
 EFI_UNIT_TEST(virtaddrmap) = {
        .name = "virtual address map",
-       .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+       .phase = EFI_SETTING_VIRTUAL_ADDRESS_MAP,
        .setup = setup,
        .execute = execute,
 };
index b89f988..34203f9 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright (C) 2020, Bachmann electronic GmbH
  */
 
+#define LOG_CATEGORY   LOGC_BOOT
+
 #include <common.h>
 #include <smbios.h>
 
@@ -94,3 +96,39 @@ const char *smbios_string(const struct smbios_header *header, int index)
 
        return string_from_smbios_table(header, index);
 }
+
+int smbios_update_version_full(void *smbios_tab, const char *version)
+{
+       const struct smbios_header *hdr;
+       struct smbios_type0 *bios;
+       uint old_len, len;
+       char *ptr;
+
+       log_info("Updating SMBIOS table at %p\n", smbios_tab);
+       hdr = smbios_header(smbios_tab, SMBIOS_BIOS_INFORMATION);
+       if (!hdr)
+               return log_msg_ret("tab", -ENOENT);
+       bios = (struct smbios_type0 *)hdr;
+       ptr = (char *)smbios_string(hdr, bios->bios_ver);
+       if (!ptr)
+               return log_msg_ret("str", -ENOMEDIUM);
+
+       /*
+        * This string is supposed to have at least enough bytes and is
+        * padded with spaces. Update it, taking care not to move the
+        * \0 terminator, so that other strings in the string table
+        * are not disturbed. See smbios_add_string()
+        */
+       old_len = strnlen(ptr, SMBIOS_STR_MAX);
+       len = strnlen(version, SMBIOS_STR_MAX);
+       if (len > old_len)
+               return log_ret(-ENOSPC);
+
+       log_debug("Replacing SMBIOS type 0 version string '%s'\n", ptr);
+       memcpy(ptr, version, len);
+#ifdef LOG_DEBUG
+       print_buffer((ulong)ptr, ptr, 1, old_len + 1, 0);
+#endif
+
+       return 0;
+}
index 7d463c8..9eb226e 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
-enum {
-       SMBIOS_STR_MAX  = 64,   /* Maximum length allowed for a string */
-};
-
 /**
  * struct smbios_ctx - context for writing SMBIOS tables
  *
index e4af87f..4277846 100644 (file)
@@ -166,6 +166,7 @@ u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
        u8 response_buffer[COMMAND_BUFFER_SIZE];
        size_t response_length;
        int i;
+       uint size;
 
        if (response) {
                response_length = *size_ptr;
@@ -174,8 +175,13 @@ u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
                response_length = sizeof(response_buffer);
        }
 
-       err = tpm_xfer(dev, command, tpm_command_size(command),
-                      response, &response_length);
+       size = tpm_command_size(command);
+       log_debug("TPM request [size:%d]: ", size);
+       for (i = 0; i < size; i++)
+               log_debug("%02x ", ((u8 *)command)[i]);
+       log_debug("\n");
+
+       err = tpm_xfer(dev, command, size, response, &response_length);
 
        if (err < 0)
                return err;
index a846fe0..8dc1440 100644 (file)
@@ -32,7 +32,7 @@ static struct session_data oiap_session = {0, };
 
 #endif /* CONFIG_TPM_AUTH_SESSIONS */
 
-u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
+u32 tpm1_startup(struct udevice *dev, enum tpm_startup_type mode)
 {
        const u8 command[12] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
@@ -48,12 +48,12 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
        return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_resume(struct udevice *dev)
+u32 tpm1_resume(struct udevice *dev)
 {
-       return tpm_startup(dev, TPM_ST_STATE);
+       return tpm1_startup(dev, TPM_ST_STATE);
 }
 
-u32 tpm_self_test_full(struct udevice *dev)
+u32 tpm1_self_test_full(struct udevice *dev)
 {
        const u8 command[10] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
@@ -61,7 +61,7 @@ u32 tpm_self_test_full(struct udevice *dev)
        return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_continue_self_test(struct udevice *dev)
+u32 tpm1_continue_self_test(struct udevice *dev)
 {
        const u8 command[10] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
@@ -69,35 +69,33 @@ u32 tpm_continue_self_test(struct udevice *dev)
        return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_clear_and_reenable(struct udevice *dev)
+u32 tpm1_clear_and_reenable(struct udevice *dev)
 {
        u32 ret;
 
        log_info("TPM: Clear and re-enable\n");
-       ret = tpm_force_clear(dev);
+       ret = tpm1_force_clear(dev);
        if (ret != TPM_SUCCESS) {
                log_err("Can't initiate a force clear\n");
                return ret;
        }
 
-       if (tpm_get_version(dev) == TPM_V1) {
-               ret = tpm_physical_enable(dev);
-               if (ret != TPM_SUCCESS) {
-                       log_err("TPM: Can't set enabled state\n");
-                       return ret;
-               }
+       ret = tpm1_physical_enable(dev);
+       if (ret != TPM_SUCCESS) {
+               log_err("TPM: Can't set enabled state\n");
+               return ret;
+       }
 
-               ret = tpm_physical_set_deactivated(dev, 0);
-               if (ret != TPM_SUCCESS) {
-                       log_err("TPM: Can't set deactivated state\n");
-                       return ret;
-               }
+       ret = tpm1_physical_set_deactivated(dev, 0);
+       if (ret != TPM_SUCCESS) {
+               log_err("TPM: Can't set deactivated state\n");
+               return ret;
        }
 
        return TPM_SUCCESS;
 }
 
-u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
+u32 tpm1_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
 {
        const u8 command[101] = {
                0x0, 0xc1,              /* TPM_TAG */
@@ -140,12 +138,12 @@ u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
        return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_nv_set_locked(struct udevice *dev)
+u32 tpm1_nv_set_locked(struct udevice *dev)
 {
-       return tpm_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
+       return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
 }
 
-u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
+u32 tpm1_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
 {
        const u8 command[22] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
@@ -179,8 +177,8 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
        return 0;
 }
 
-u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
-                      u32 length)
+u32 tpm1_nv_write_value(struct udevice *dev, u32 index, const void *data,
+                       u32 length)
 {
        const u8 command[256] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
@@ -210,13 +208,8 @@ u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
        return 0;
 }
 
-uint32_t tpm_set_global_lock(struct udevice *dev)
-{
-       return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0);
-}
-
-u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
-              void *out_digest)
+u32 tpm1_extend(struct udevice *dev, u32 index, const void *in_digest,
+               void *out_digest)
 {
        const u8 command[34] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
@@ -247,7 +240,7 @@ u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
        return 0;
 }
 
-u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
+u32 tpm1_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
 {
        const u8 command[14] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
@@ -275,7 +268,7 @@ u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
        return 0;
 }
 
-u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
+u32 tpm1_tsc_physical_presence(struct udevice *dev, u16 presence)
 {
        const u8 command[12] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
@@ -291,7 +284,7 @@ u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
        return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_finalise_physical_presence(struct udevice *dev)
+u32 tpm1_finalise_physical_presence(struct udevice *dev)
 {
        const u8 command[12] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
@@ -300,7 +293,7 @@ u32 tpm_finalise_physical_presence(struct udevice *dev)
        return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
+u32 tpm1_read_pubek(struct udevice *dev, void *data, size_t count)
 {
        const u8 command[30] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
@@ -331,7 +324,7 @@ u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
        return 0;
 }
 
-u32 tpm_force_clear(struct udevice *dev)
+u32 tpm1_force_clear(struct udevice *dev)
 {
        const u8 command[10] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
@@ -340,7 +333,7 @@ u32 tpm_force_clear(struct udevice *dev)
        return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_physical_enable(struct udevice *dev)
+u32 tpm1_physical_enable(struct udevice *dev)
 {
        const u8 command[10] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
@@ -349,7 +342,7 @@ u32 tpm_physical_enable(struct udevice *dev)
        return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_physical_disable(struct udevice *dev)
+u32 tpm1_physical_disable(struct udevice *dev)
 {
        const u8 command[10] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
@@ -358,7 +351,7 @@ u32 tpm_physical_disable(struct udevice *dev)
        return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
+u32 tpm1_physical_set_deactivated(struct udevice *dev, u8 state)
 {
        const u8 command[11] = {
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
@@ -374,8 +367,8 @@ u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
        return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
-                      void *cap, size_t count)
+u32 tpm1_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+                       void *cap, size_t count)
 {
        const u8 command[22] = {
                0x0, 0xc1,              /* TPM_TAG */
@@ -414,8 +407,8 @@ u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
        return 0;
 }
 
-u32 tpm_get_permanent_flags(struct udevice *dev,
-                           struct tpm_permanent_flags *pflags)
+u32 tpm1_get_permanent_flags(struct udevice *dev,
+                            struct tpm_permanent_flags *pflags)
 {
        const u8 command[22] = {
                0x0, 0xc1,              /* TPM_TAG */
@@ -453,7 +446,7 @@ u32 tpm_get_permanent_flags(struct udevice *dev,
        return 0;
 }
 
-u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
+u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm)
 {
        const u8 command[22] = {
                0x0, 0xc1,              /* TPM_TAG */
@@ -482,7 +475,7 @@ u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
 }
 
 #ifdef CONFIG_TPM_FLUSH_RESOURCES
-u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
+u32 tpm1_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
 {
        const u8 command[18] = {
                0x00, 0xc1,             /* TPM_TAG */
@@ -641,7 +634,7 @@ static u32 verify_response_auth(u32 command_code, const void *response,
        return TPM_SUCCESS;
 }
 
-u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle)
+u32 tpm1_terminate_auth_session(struct udevice *dev, u32 auth_handle)
 {
        const u8 command[18] = {
                0x00, 0xc1,             /* TPM_TAG */
@@ -663,16 +656,16 @@ u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle)
        return tpm_sendrecv_command(dev, request, NULL, NULL);
 }
 
-u32 tpm_end_oiap(struct udevice *dev)
+u32 tpm1_end_oiap(struct udevice *dev)
 {
        u32 err = TPM_SUCCESS;
 
        if (oiap_session.valid)
-               err = tpm_terminate_auth_session(dev, oiap_session.handle);
+               err = tpm1_terminate_auth_session(dev, oiap_session.handle);
        return err;
 }
 
-u32 tpm_oiap(struct udevice *dev, u32 *auth_handle)
+u32 tpm1_oiap(struct udevice *dev, u32 *auth_handle)
 {
        const u8 command[10] = {
                0x00, 0xc1,             /* TPM_TAG */
@@ -686,7 +679,7 @@ u32 tpm_oiap(struct udevice *dev, u32 *auth_handle)
        u32 err;
 
        if (oiap_session.valid)
-               tpm_terminate_auth_session(dev, oiap_session.handle);
+               tpm1_terminate_auth_session(dev, oiap_session.handle);
 
        err = tpm_sendrecv_command(dev, command, response, &response_length);
        if (err)
@@ -702,9 +695,9 @@ u32 tpm_oiap(struct udevice *dev, u32 *auth_handle)
        return 0;
 }
 
-u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
-                      size_t key_length, const void *parent_key_usage_auth,
-                      u32 *key_handle)
+u32 tpm1_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
+                       size_t key_length, const void *parent_key_usage_auth,
+                       u32 *key_handle)
 {
        const u8 command[14] = {
                0x00, 0xc2,             /* TPM_TAG */
@@ -723,7 +716,7 @@ u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
        u32 err;
 
        if (!oiap_session.valid) {
-               err = tpm_oiap(dev, NULL);
+               err = tpm1_oiap(dev, NULL);
                if (err)
                        return err;
        }
@@ -768,9 +761,9 @@ u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
        return 0;
 }
 
-u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
-                        const void *usage_auth, void *pubkey,
-                        size_t *pubkey_len)
+u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
+                         const void *usage_auth, void *pubkey,
+                         size_t *pubkey_len)
 {
        const u8 command[14] = {
                0x00, 0xc2,             /* TPM_TAG */
@@ -788,7 +781,7 @@ u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
        u32 err;
 
        if (!oiap_session.valid) {
-               err = tpm_oiap(dev, NULL);
+               err = tpm1_oiap(dev, NULL);
                if (err)
                        return err;
        }
@@ -834,8 +827,8 @@ u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
 }
 
 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
-u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
-                     const u8 pubkey_digest[20], u32 *handle)
+u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20],
+                      const u8 pubkey_digest[20], u32 *handle)
 {
        u16 key_count;
        u32 key_handles[10];
@@ -876,7 +869,7 @@ u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
 
 #endif /* CONFIG_TPM_AUTH_SESSIONS */
 
-u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
+u32 tpm1_get_random(struct udevice *dev, void *data, u32 count)
 {
        const u8 command[14] = {
                0x0, 0xc1,              /* TPM_TAG */
index 1f3deb0..235f8c2 100644 (file)
@@ -47,9 +47,11 @@ u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
 u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
               const ssize_t pw_sz)
 {
+       /* Length of the message header, up to start of password */
+       uint offset = 27;
        u8 command_v2[COMMAND_BUFFER_SIZE] = {
                tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
-               tpm_u32(27 + pw_sz),            /* Length */
+               tpm_u32(offset + pw_sz),        /* Length */
                tpm_u32(TPM2_CC_CLEAR),         /* Command code */
 
                /* HANDLE */
@@ -64,7 +66,6 @@ u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
                tpm_u16(pw_sz),                 /* Size of <hmac/password> */
                /* STRING(pw)                      <hmac/password> (if any) */
        };
-       unsigned int offset = 27;
        int ret;
 
        /*
@@ -80,12 +81,61 @@ u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
        return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
+u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
+                        size_t space_size, u32 nv_attributes,
+                        const u8 *nv_policy, size_t nv_policy_size)
+{
+       /*
+        * Calculate the offset of the nv_policy piece by adding each of the
+        * chunks below.
+        */
+       uint offset = 10 + 8 + 13 + 14;
+       u8 command_v2[COMMAND_BUFFER_SIZE] = {
+               /* header 10 bytes */
+               tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
+               tpm_u32(offset + nv_policy_size),/* Length */
+               tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
+
+               /* handles 8 bytes */
+               tpm_u32(TPM2_RH_PLATFORM),      /* Primary platform seed */
+
+               /* session header 13 bytes */
+               tpm_u32(9),                     /* Header size */
+               tpm_u32(TPM2_RS_PW),            /* Password authorisation */
+               tpm_u16(0),                     /* nonce_size */
+               0,                              /* session_attrs */
+               tpm_u16(0),                     /* auth_size */
+
+               /* message 14 bytes + policy */
+               tpm_u16(12 + nv_policy_size),   /* size */
+               tpm_u32(space_index),
+               tpm_u16(TPM2_ALG_SHA256),
+               tpm_u32(nv_attributes),
+               tpm_u16(nv_policy_size),
+               /* nv_policy */
+       };
+       int ret;
+
+       /*
+        * Fill the command structure starting from the first buffer:
+        *     - the password (if any)
+        */
+       ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
+                              offset, nv_policy, nv_policy_size);
+       if (ret)
+               return TPM_LIB_ERROR;
+
+       return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
 u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
                    const u8 *digest, u32 digest_len)
 {
+       /* Length of the message header, up to start of digest */
+       uint offset = 33;
        u8 command_v2[COMMAND_BUFFER_SIZE] = {
                tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
-               tpm_u32(33 + digest_len),       /* Length */
+               tpm_u32(offset + digest_len),   /* Length */
                tpm_u32(TPM2_CC_PCR_EXTEND),    /* Command code */
 
                /* HANDLE */
@@ -99,11 +149,12 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
                0,                              /* Attributes: Cont/Excl/Rst */
                tpm_u16(0),                     /* Size of <hmac/password> */
                                                /* <hmac/password> (if any) */
+
+               /* hashes */
                tpm_u32(1),                     /* Count (number of hashes) */
                tpm_u16(algorithm),     /* Algorithm of the hash */
                /* STRING(digest)                  Digest */
        };
-       unsigned int offset = 33;
        int ret;
 
        /*
@@ -112,13 +163,96 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
         */
        ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
                               offset, digest, digest_len);
-       offset += digest_len;
        if (ret)
                return TPM_LIB_ERROR;
 
        return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
+u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
+{
+       u8 command_v2[COMMAND_BUFFER_SIZE] = {
+               /* header 10 bytes */
+               tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
+               tpm_u32(10 + 8 + 4 + 9 + 4),    /* Length */
+               tpm_u32(TPM2_CC_NV_READ),       /* Command code */
+
+               /* handles 8 bytes */
+               tpm_u32(TPM2_RH_PLATFORM),      /* Primary platform seed */
+               tpm_u32(HR_NV_INDEX + index),   /* Password authorisation */
+
+               /* AUTH_SESSION */
+               tpm_u32(9),                     /* Authorization size */
+               tpm_u32(TPM2_RS_PW),            /* Session handle */
+               tpm_u16(0),                     /* Size of <nonce> */
+                                               /* <nonce> (if any) */
+               0,                              /* Attributes: Cont/Excl/Rst */
+               tpm_u16(0),                     /* Size of <hmac/password> */
+                                               /* <hmac/password> (if any) */
+
+               tpm_u16(count),                 /* Number of bytes */
+               tpm_u16(0),                     /* Offset */
+       };
+       size_t response_len = COMMAND_BUFFER_SIZE;
+       u8 response[COMMAND_BUFFER_SIZE];
+       int ret;
+       u16 tag;
+       u32 size, code;
+
+       ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
+       if (ret)
+               return log_msg_ret("read", ret);
+       if (unpack_byte_string(response, response_len, "wdds",
+                              0, &tag, 2, &size, 6, &code,
+                              16, data, count))
+               return TPM_LIB_ERROR;
+
+       return 0;
+}
+
+u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
+                       u32 count)
+{
+       struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
+       uint offset = 10 + 8 + 4 + 9 + 2;
+       uint len = offset + count + 2;
+       /* Use empty password auth if platform hierarchy is disabled */
+       u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
+               TPM2_RH_PLATFORM;
+       u8 command_v2[COMMAND_BUFFER_SIZE] = {
+               /* header 10 bytes */
+               tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
+               tpm_u32(len),                   /* Length */
+               tpm_u32(TPM2_CC_NV_WRITE),      /* Command code */
+
+               /* handles 8 bytes */
+               tpm_u32(auth),                  /* Primary platform seed */
+               tpm_u32(HR_NV_INDEX + index),   /* Password authorisation */
+
+               /* AUTH_SESSION */
+               tpm_u32(9),                     /* Authorization size */
+               tpm_u32(TPM2_RS_PW),            /* Session handle */
+               tpm_u16(0),                     /* Size of <nonce> */
+                                               /* <nonce> (if any) */
+               0,                              /* Attributes: Cont/Excl/Rst */
+               tpm_u16(0),                     /* Size of <hmac/password> */
+                                               /* <hmac/password> (if any) */
+
+               tpm_u16(count),
+       };
+       size_t response_len = COMMAND_BUFFER_SIZE;
+       u8 response[COMMAND_BUFFER_SIZE];
+       int ret;
+
+       ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
+                              offset, data, count,
+                              offset + count, 0);
+       if (ret)
+               return TPM_LIB_ERROR;
+
+       return tpm_sendrecv_command(dev, command_v2, response, &response_len);
+}
+
 u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
                  void *data, unsigned int *updates)
 {
@@ -467,3 +601,61 @@ u32 tpm2_get_random(struct udevice *dev, void *data, u32 count)
 
        return 0;
 }
+
+u32 tpm2_write_lock(struct udevice *dev, u32 index)
+{
+       u8 command_v2[COMMAND_BUFFER_SIZE] = {
+               /* header 10 bytes */
+               tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
+               tpm_u32(10 + 8 + 13), /* Length */
+               tpm_u32(TPM2_CC_NV_WRITELOCK), /* Command code */
+
+               /* handles 8 bytes */
+               tpm_u32(TPM2_RH_PLATFORM),      /* Primary platform seed */
+               tpm_u32(HR_NV_INDEX + index),   /* Password authorisation */
+
+               /* session header 9 bytes */
+               tpm_u32(9),                     /* Header size */
+               tpm_u32(TPM2_RS_PW),            /* Password authorisation */
+               tpm_u16(0),                     /* nonce_size */
+               0,                              /* session_attrs */
+               tpm_u16(0),                     /* auth_size */
+       };
+
+       return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
+u32 tpm2_disable_platform_hierarchy(struct udevice *dev)
+{
+       struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
+       u8 command_v2[COMMAND_BUFFER_SIZE] = {
+               /* header 10 bytes */
+               tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
+               tpm_u32(10 + 4 + 13 + 5),       /* Length */
+               tpm_u32(TPM2_CC_HIER_CONTROL),  /* Command code */
+
+               /* 4 bytes */
+               tpm_u32(TPM2_RH_PLATFORM),      /* Primary platform seed */
+
+               /* session header 9 bytes */
+               tpm_u32(9),                     /* Header size */
+               tpm_u32(TPM2_RS_PW),            /* Password authorisation */
+               tpm_u16(0),                     /* nonce_size */
+               0,                              /* session_attrs */
+               tpm_u16(0),                     /* auth_size */
+
+               /* payload 5 bytes */
+               tpm_u32(TPM2_RH_PLATFORM),      /* Hierarchy to disable */
+               0,                              /* 0=disable */
+       };
+       int ret;
+
+       ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+       log_info("ret=%s, %x\n", dev->name, ret);
+       if (ret)
+               return ret;
+
+       priv->plat_hier_disabled = true;
+
+       return 0;
+}
diff --git a/lib/tpm_api.c b/lib/tpm_api.c
new file mode 100644 (file)
index 0000000..4c66264
--- /dev/null
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <tpm_api.h>
+#include <tpm-v1.h>
+#include <tpm-v2.h>
+#include <tpm_api.h>
+
+static bool is_tpm1(struct udevice *dev)
+{
+       return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1;
+}
+
+static bool is_tpm2(struct udevice *dev)
+{
+       return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2;
+}
+
+u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
+{
+       if (is_tpm1(dev)) {
+               return tpm1_startup(dev, mode);
+       } else if (is_tpm2(dev)) {
+               enum tpm2_startup_types type;
+
+               switch (mode) {
+               case TPM_ST_CLEAR:
+                       type = TPM2_SU_CLEAR;
+                       break;
+               case TPM_ST_STATE:
+                       type = TPM2_SU_STATE;
+                       break;
+               default:
+               case TPM_ST_DEACTIVATED:
+                       return -EINVAL;
+               }
+               return tpm2_startup(dev, type);
+       } else {
+               return -ENOSYS;
+       }
+}
+
+u32 tpm_resume(struct udevice *dev)
+{
+       if (is_tpm1(dev))
+               return tpm1_startup(dev, TPM_ST_STATE);
+       else if (is_tpm2(dev))
+               return tpm2_startup(dev, TPM2_SU_STATE);
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_self_test_full(struct udevice *dev)
+{
+       if (is_tpm1(dev))
+               return tpm1_self_test_full(dev);
+       else if (is_tpm2(dev))
+               return tpm2_self_test(dev, TPMI_YES);
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_continue_self_test(struct udevice *dev)
+{
+       if (is_tpm1(dev))
+               return tpm1_continue_self_test(dev);
+       else if (is_tpm2(dev))
+               return tpm2_self_test(dev, TPMI_NO);
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_clear_and_reenable(struct udevice *dev)
+{
+       u32 ret;
+
+       log_info("TPM: Clear and re-enable\n");
+       ret = tpm_force_clear(dev);
+       if (ret != TPM_SUCCESS) {
+               log_err("Can't initiate a force clear\n");
+               return ret;
+       }
+
+       if (is_tpm1(dev)) {
+               ret = tpm1_physical_enable(dev);
+               if (ret != TPM_SUCCESS) {
+                       log_err("TPM: Can't set enabled state\n");
+                       return ret;
+               }
+
+               ret = tpm1_physical_set_deactivated(dev, 0);
+               if (ret != TPM_SUCCESS) {
+                       log_err("TPM: Can't set deactivated state\n");
+                       return ret;
+               }
+       }
+
+       return TPM_SUCCESS;
+}
+
+u32 tpm_nv_enable_locking(struct udevice *dev)
+{
+       if (is_tpm1(dev))
+               return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
+       else if (is_tpm2(dev))
+               return -ENOSYS;
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
+{
+       if (is_tpm1(dev))
+               return tpm1_nv_read_value(dev, index, data, count);
+       else if (is_tpm2(dev))
+               return tpm2_nv_read_value(dev, index, data, count);
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
+                      u32 count)
+{
+       if (is_tpm1(dev))
+               return tpm1_nv_write_value(dev, index, data, count);
+       else if (is_tpm2(dev))
+               return tpm2_nv_write_value(dev, index, data, count);
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_set_global_lock(struct udevice *dev)
+{
+       return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0);
+}
+
+u32 tpm_write_lock(struct udevice *dev, u32 index)
+{
+       if (is_tpm1(dev))
+               return -ENOSYS;
+       else if (is_tpm2(dev))
+               return tpm2_write_lock(dev, index);
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
+                  void *out_digest)
+{
+       if (is_tpm1(dev))
+               return tpm1_extend(dev, index, in_digest, out_digest);
+       else if (is_tpm2(dev))
+               return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest,
+                                      TPM2_DIGEST_LEN);
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
+{
+       if (is_tpm1(dev))
+               return tpm1_pcr_read(dev, index, data, count);
+       else if (is_tpm2(dev))
+               return -ENOSYS;
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
+{
+       if (is_tpm1(dev))
+               return tpm1_tsc_physical_presence(dev, presence);
+
+       /*
+        * Nothing to do on TPM2 for this; use platform hierarchy availability
+        * instead.
+        */
+       else if (is_tpm2(dev))
+               return 0;
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_finalise_physical_presence(struct udevice *dev)
+{
+       if (is_tpm1(dev))
+               return tpm1_finalise_physical_presence(dev);
+
+       /* Nothing needs to be done with tpm2 */
+       else if (is_tpm2(dev))
+               return 0;
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
+{
+       if (is_tpm1(dev))
+               return tpm1_read_pubek(dev, data, count);
+       else if (is_tpm2(dev))
+               return -ENOSYS; /* not implemented yet */
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_force_clear(struct udevice *dev)
+{
+       if (is_tpm1(dev))
+               return tpm1_force_clear(dev);
+       else if (is_tpm2(dev))
+               return tpm2_clear(dev, TPM2_RH_PLATFORM, NULL, 0);
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_physical_enable(struct udevice *dev)
+{
+       if (is_tpm1(dev))
+               return tpm1_physical_enable(dev);
+
+       /* Nothing needs to be done with tpm2 */
+       else if (is_tpm2(dev))
+               return 0;
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_physical_disable(struct udevice *dev)
+{
+       if (is_tpm1(dev))
+               return tpm1_physical_disable(dev);
+
+       /* Nothing needs to be done with tpm2 */
+       else if (is_tpm2(dev))
+               return 0;
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
+{
+       if (is_tpm1(dev))
+               return tpm1_physical_set_deactivated(dev, state);
+       /* Nothing needs to be done with tpm2 */
+       else if (is_tpm2(dev))
+               return 0;
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+                      void *cap, size_t count)
+{
+       if (is_tpm1(dev))
+               return tpm1_get_capability(dev, cap_area, sub_cap, cap, count);
+       else if (is_tpm2(dev))
+               return tpm2_get_capability(dev, cap_area, sub_cap, cap, count);
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
+{
+       if (is_tpm1(dev))
+               return tpm1_get_permissions(dev, index, perm);
+       else if (is_tpm2(dev))
+               return -ENOSYS; /* not implemented yet */
+       else
+               return -ENOSYS;
+}
+
+u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
+{
+       if (is_tpm1(dev))
+               return tpm1_get_random(dev, data, count);
+       else if (is_tpm2(dev))
+               return -ENOSYS; /* not implemented yet */
+       else
+               return -ENOSYS;
+}
index 1fd63ef..ca98822 100644 (file)
@@ -120,10 +120,25 @@ endif
 u-boot-spl-init := $(head-y)
 u-boot-spl-main := $(libs-y)
 ifdef CONFIG_$(SPL_TPL_)OF_PLATDATA
-u-boot-spl-platdata := $(obj)/dts/dt-plat.o
-u-boot-spl-platdata_c := $(patsubst %.o,%.c,$(u-boot-spl-platdata))
+platdata-hdr := include/generated/dt-structs-gen.h include/generated/dt-decl.h
+platdata-inst := $(obj)/dts/dt-uclass.o $(obj)/dts/dt-device.o
+platdata-noinst := $(obj)/dts/dt-plat.o
+
+ifdef CONFIG_$(SPL_TPL_)OF_PLATDATA_INST
+u-boot-spl-platdata := $(platdata-inst)
+u-boot-spl-old-platdata := $(platdata-noinst)
+else
+u-boot-spl-platdata := $(platdata-noinst)
+u-boot-spl-old-platdata := $(platdata-inst)
 endif
 
+# Files we need to generate
+u-boot-spl-platdata_c := $(patsubst %.o,%.c,$(u-boot-spl-platdata))
+
+# Files we won't generate and should remove
+u-boot-spl-old-platdata_c := $(patsubst %.o,%.c,$(u-boot-spl-old-platdata))
+endif  # OF_PLATDATA
+
 # Linker Script
 # First test whether there's a linker-script for the specific stage defined...
 ifneq ($(CONFIG_$(SPL_TPL_)LDSCRIPT),)
@@ -311,7 +326,11 @@ $(obj)/$(SPL_BIN).dtb: $(obj)/dts/dt-$(SPL_NAME).dtb FORCE
 pythonpath = PYTHONPATH=scripts/dtc/pylibfdt
 
 DTOC_ARGS := $(pythonpath) $(srctree)/tools/dtoc/dtoc \
-       -d $(obj)/$(SPL_BIN).dtb
+       -d $(obj)/$(SPL_BIN).dtb -p $(SPL_NAME)
+
+ifneq ($(CONFIG_$(SPL_TPL_)OF_PLATDATA_INST),)
+DTOC_ARGS += -i
+endif
 
 quiet_cmd_dtoc = DTOC    $@
 cmd_dtoc = $(DTOC_ARGS) -c $(obj)/dts -C include/generated all
@@ -319,18 +338,17 @@ cmd_dtoc = $(DTOC_ARGS) -c $(obj)/dts -C include/generated all
 quiet_cmd_plat = PLAT    $@
 cmd_plat = $(CC) $(c_flags) -c $< -o $(filter-out $(PHONY),$@)
 
-targets += $(u-boot-spl-platdata)
-
-$(obj)/dts/dt-%.o: $(obj)/dts/dt-%.c \
-               include/generated/dt-structs-gen.h prepare FORCE
+$(obj)/dts/dt-%.o: $(obj)/dts/dt-%.c $(platdata-hdr)
        $(call if_changed,plat)
 
-PHONY += dts_dir
-dts_dir:
-       $(shell [ -d $(obj)/dts ] || mkdir -p $(obj)/dts)
-
-include/generated/dt-structs-gen.h $(u-boot-spl-platdata_c) &: \
-               $(obj)/$(SPL_BIN).dtb dts_dir FORCE
+# Don't use dts_dir here, since it forces running this expensive rule every time
+$(platdata-hdr) $(u-boot-spl-platdata_c) &: $(obj)/$(SPL_BIN).dtb
+       @[ -d $(obj)/dts ] || mkdir -p $(obj)/dts
+       @# Remove old files since which ones we generate depends on the setting
+       @# of OF_PLATDATA_INST and this might change between builds. Leaving old
+       @# ones around is confusing and it is possible that switching the
+       @# setting again will use the old one instead of regenerating it.
+       @rm -f $(u-boot-spl-all-platdata_c) $(u-boot-spl-all-platdata)
        $(call if_changed,dtoc)
 
 ifdef CONFIG_SAMSUNG
@@ -471,6 +489,10 @@ FORCE:
 $(obj)/dts/dt-$(SPL_NAME).dtb: dts/dt.dtb
        $(Q)$(MAKE) $(build)=$(obj)/dts spl_dtbs
 
+PHONY += dts_dir
+dts_dir:
+       $(shell [ -d $(obj)/dts ] || mkdir -p $(obj)/dts)
+
 # Declare the contents of the .PHONY variable as phony.  We keep that
 # information in a variable so we can use it in if_changed and friends.
 .PHONY: $(PHONY)
index 43295ee..85857a7 100644 (file)
@@ -1629,7 +1629,6 @@ CONFIG_STV0991
 CONFIG_STV0991_HZ
 CONFIG_STV0991_HZ_CLOCK
 CONFIG_ST_SMI
-CONFIG_SUNXI_MAX_FB_SIZE
 CONFIG_SXNI855T
 CONFIG_SYSFLAGS_ADDR
 CONFIG_SYSFS
index 80b6ad2..4782dd4 100644 (file)
@@ -23,12 +23,18 @@ quiet_cmd_pymod = PYMOD   $@
                SWIG_OPTS="-I$(LIBFDT_srcdir) -I$(LIBFDT_srcdir)/.." \
                $(PYTHON3) $< --quiet build_ext --inplace
 
-$(obj)/_libfdt.so: $(src)/setup.py $(PYLIBFDT_srcs) FORCE
+rebuild: $(src)/setup.py $(PYLIBFDT_srcs)
        @# Remove the library since otherwise Python doesn't seem to regenerate
        @# the libfdt.py file if it is missing.
-       rm -f $(obj)/_libfdt*.so
+       @rm -f $(obj)/_libfdt*.so
        $(call if_changed,pymod)
+       @# Rename the file to _libfdt.so so this Makefile doesn't run every time
+       @if [ ! -e $(obj)/_libfdt.so ]; then \
+               mv $(obj)/_libfdt*.so $(obj)/_libfdt.so; \
+       fi
 
-always += _libfdt.so
+$(obj)/_libfdt.so $(obj)/libfdt.py &: rebuild
+
+always += _libfdt.so libfdt.py
 
 clean-files += libfdt.i _libfdt.so libfdt.py libfdt_wrap.c
index 932e517..a26e915 100644 (file)
@@ -2,6 +2,9 @@
 #
 # (C) Copyright 2012 The Chromium Authors
 
+obj-y += test-main.o
+obj-$(CONFIG_SANDBOX) += image/
+
 ifneq ($(CONFIG_$(SPL_)BLOBLIST),)
 obj-$(CONFIG_$(SPL_)CMDLINE) += bloblist.o
 obj-$(CONFIG_$(SPL_)CMDLINE) += bootm.o
index 6953d30..d876b63 100644 (file)
@@ -387,9 +387,8 @@ BLOBLIST_TEST(bloblist_test_reloc, 0);
 int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
                   char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test,
-                                                bloblist_test);
-       const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
 
        return cmd_ut_category("bloblist", "bloblist_test_",
                               tests, n_ents, argc, argv);
index 563d6eb..8528982 100644 (file)
@@ -240,8 +240,8 @@ BOOTM_TEST(bootm_test_subst_both, 0);
 
 int do_ut_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test, bootm_test);
-       const int n_ents = ll_entry_count(struct unit_test, bootm_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(bootm_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(bootm_test);
 
        return cmd_ut_category("bootm", "bootm_test_", tests, n_ents,
                               argc, argv);
index fbaa8a4..d76f47c 100644 (file)
@@ -12,8 +12,8 @@
 
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test, mem_test);
-       const int n_ents = ll_entry_count(struct unit_test, mem_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(mem_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(mem_test);
 
        return cmd_ut_category("cmd_mem", "mem_test_", tests, n_ents, argc,
                               argv);
index fd6d869..c537e89 100644 (file)
@@ -15,7 +15,7 @@
 
 #define BUF_SIZE       0x100
 
-/* Declare a new mem test */
+/* Declare a new setexpr test */
 #define SETEXPR_TEST(_name, _flags)    UNIT_TEST(_name, _flags, setexpr_test)
 
 /* Test 'setexpr' command with simply setting integers */
@@ -306,8 +306,8 @@ static int setexpr_test_str(struct unit_test_state *uts)
        ut_asserteq(1, run_command("setexpr.s fred 0", 0));
        ut_assertok(ut_check_delta(start_mem));
 
-       start_mem = ut_check_free();
        ut_assertok(env_set("fred", "12345"));
+       start_mem = ut_check_free();
        ut_assertok(run_command("setexpr.s fred *0", 0));
        ut_asserteq_str("hello", env_get("fred"));
        ut_assertok(ut_check_delta(start_mem));
@@ -345,7 +345,22 @@ static int setexpr_test_str_oper(struct unit_test_state *uts)
        start_mem = ut_check_free();
        ut_assertok(run_command("setexpr.s fred *0 + *10", 0));
        ut_asserteq_str("hello there", env_get("fred"));
-       ut_assertok(ut_check_delta(start_mem));
+
+       /*
+        * This check does not work with sandbox_flattree, apparently due to
+        * memory allocations in env_set().
+        *
+        * The truetype console produces lots of memory allocations even though
+        * the LCD display is not visible. But even without these, it does not
+        * work.
+        *
+        * A better test would be for dlmalloc to record the allocs and frees
+        * for a particular caller, but that is not supported.
+        *
+        * For now, drop this test.
+        *
+        * ut_assertok(ut_check_delta(start_mem));
+        */
 
        unmap_sysmem(buf);
 
@@ -375,10 +390,9 @@ SETEXPR_TEST(setexpr_test_str_long, UT_TESTF_CONSOLE_REC);
 
 int do_ut_setexpr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test,
-                                                setexpr_test);
-       const int n_ents = ll_entry_count(struct unit_test, setexpr_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(setexpr_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(setexpr_test);
 
-       return cmd_ut_category("cmd_setexpr", "cmd_mem_", tests, n_ents, argc,
-                              argv);
+       return cmd_ut_category("cmd_setexpr", "setexpr_test_", tests, n_ents,
+                              argc, argv);
 }
index aa5cebc..9d60d7d 100644 (file)
@@ -44,9 +44,10 @@ static int lib_test_hush_echo(struct unit_test_state *uts)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(echo_data); ++i) {
+               ut_silence_console(uts);
                console_record_reset_enable();
                ut_assertok(run_command(echo_data[i].cmd, 0));
-               gd->flags &= ~GD_FLG_RECORD;
+               ut_unsilence_console(uts);
                console_record_readline(uts->actual_str,
                                        sizeof(uts->actual_str));
                ut_asserteq_str(echo_data[i].expected, uts->actual_str);
index 8728cc8..b9c1660 100644 (file)
@@ -9,6 +9,7 @@
 #include <console.h>
 #include <test/suites.h>
 #include <test/test.h>
+#include <test/ut.h>
 
 static int do_ut_all(struct cmd_tbl *cmdtp, int flag, int argc,
                     char *const argv[]);
@@ -17,41 +18,12 @@ int cmd_ut_category(const char *name, const char *prefix,
                    struct unit_test *tests, int n_ents,
                    int argc, char *const argv[])
 {
-       struct unit_test_state uts = { .fail_count = 0 };
-       struct unit_test *test;
-       int prefix_len = prefix ? strlen(prefix) : 0;
+       int ret;
 
-       if (argc == 1)
-               printf("Running %d %s tests\n", n_ents, name);
+       ret = ut_run_list(name, prefix, tests, n_ents,
+                         argc > 1 ? argv[1] : NULL);
 
-       for (test = tests; test < tests + n_ents; test++) {
-               const char *test_name = test->name;
-
-               /* Remove the prefix */
-               if (prefix && !strncmp(test_name, prefix, prefix_len))
-                       test_name += prefix_len;
-
-               if (argc > 1 && strcmp(argv[1], test_name))
-                       continue;
-               printf("Test: %s\n", test->name);
-
-               if (test->flags & UT_TESTF_CONSOLE_REC) {
-                       int ret = console_record_reset_enable();
-
-                       if (ret) {
-                               printf("Skipping: Console recording disabled\n");
-                               continue;
-                       }
-               }
-
-               uts.start = mallinfo();
-
-               test->func(&uts);
-       }
-
-       printf("Failures: %d\n", uts.fail_count);
-
-       return uts.fail_count ? CMD_RET_FAILURE : 0;
+       return ret ? CMD_RET_FAILURE : 0;
 }
 
 static struct cmd_tbl cmd_ut_sub[] = {
index a2a4b9f..4cd1be5 100644 (file)
@@ -539,9 +539,8 @@ COMPRESSION_TEST(compression_test_bootm_none, 0);
 int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
                      char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test,
-                                                compression_test);
-       const int n_ents = ll_entry_count(struct unit_test, compression_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
 
        return cmd_ut_category("compression", "compression_test_",
                               tests, n_ents, argc, argv);
index fd14551..f5cc554 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Copyright (c) 2013 Google, Inc
 
-obj-$(CONFIG_UT_DM) += test-main.o
+obj-$(CONFIG_UT_DM) += test-dm.o
 
 # Tests for particular subsystems - when enabling driver model for a new
 # subsystem you must add sandbox tests here.
index 240187c..2edab7b 100644 (file)
@@ -360,24 +360,24 @@ static int dm_test_acpi_cmd_list(struct unit_test_state *uts)
        run_command("acpi list", 0);
        addr = (ulong)map_to_sysmem(buf);
        ut_assert_nextline("ACPI tables start at %lx", addr);
-       ut_assert_nextline("RSDP %08lx %06lx (v02 U-BOOT)", addr,
+       ut_assert_nextline("RSDP %08lx %06zx (v02 U-BOOT)", addr,
                           sizeof(struct acpi_rsdp));
        addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16);
-       ut_assert_nextline("RSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+       ut_assert_nextline("RSDT %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
                           addr, sizeof(struct acpi_table_header) +
                           3 * sizeof(u32), U_BOOT_BUILD_DATE);
        addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16);
-       ut_assert_nextline("XSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+       ut_assert_nextline("XSDT %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
                           addr, sizeof(struct acpi_table_header) +
                           3 * sizeof(u64), U_BOOT_BUILD_DATE);
        addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64);
-       ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+       ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
                           addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
        addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
-       ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+       ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
                           addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
        addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
-       ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+       ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
                           addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
        ut_assert_console_end();
 
index 35ca689..2210345 100644 (file)
@@ -117,14 +117,13 @@ int dm_leak_check_end(struct unit_test_state *uts)
 /* Test that binding with plat occurs correctly */
 static int dm_test_autobind(struct unit_test_state *uts)
 {
-       struct dm_test_state *dms = uts->priv;
        struct udevice *dev;
 
        /*
         * We should have a single class (UCLASS_ROOT) and a single root
         * device with no children.
         */
-       ut_assert(dms->root);
+       ut_assert(uts->root);
        ut_asserteq(1, list_count_items(gd->uclass_root));
        ut_asserteq(0, list_count_items(&gd->dm_root->child_head));
        ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]);
@@ -207,7 +206,6 @@ DM_TEST(dm_test_autobind_uclass_pdata_valid, UT_TESTF_SCAN_PDATA);
 /* Test that autoprobe finds all the expected devices */
 static int dm_test_autoprobe(struct unit_test_state *uts)
 {
-       struct dm_test_state *dms = uts->priv;
        int expected_base_add;
        struct udevice *dev;
        struct uclass *uc;
@@ -221,7 +219,7 @@ static int dm_test_autoprobe(struct unit_test_state *uts)
        ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]);
 
        /* The root device should not be activated until needed */
-       ut_assert(dev_get_flags(dms->root) & DM_FLAG_ACTIVATED);
+       ut_assert(dev_get_flags(uts->root) & DM_FLAG_ACTIVATED);
 
        /*
         * We should be able to find the three test devices, and they should
@@ -241,7 +239,7 @@ static int dm_test_autoprobe(struct unit_test_state *uts)
 
                /* Activating a device should activate the root device */
                if (!i)
-                       ut_assert(dev_get_flags(dms->root) & DM_FLAG_ACTIVATED);
+                       ut_assert(dev_get_flags(uts->root) & DM_FLAG_ACTIVATED);
        }
 
        /*
@@ -293,7 +291,6 @@ DM_TEST(dm_test_plat, UT_TESTF_SCAN_PDATA);
 /* Test that we can bind, probe, remove, unbind a driver */
 static int dm_test_lifecycle(struct unit_test_state *uts)
 {
-       struct dm_test_state *dms = uts->priv;
        int op_count[DM_TEST_OP_COUNT];
        struct udevice *dev, *test_dev;
        int pingret;
@@ -301,7 +298,7 @@ static int dm_test_lifecycle(struct unit_test_state *uts)
 
        memcpy(op_count, dm_testdrv_op_count, sizeof(op_count));
 
-       ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+       ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
                                        &dev));
        ut_assert(dev);
        ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND]
@@ -309,7 +306,7 @@ static int dm_test_lifecycle(struct unit_test_state *uts)
        ut_assert(!dev_get_priv(dev));
 
        /* Probe the device - it should fail allocating private data */
-       dms->force_fail_alloc = 1;
+       uts->force_fail_alloc = 1;
        ret = device_probe(dev);
        ut_assert(ret == -ENOMEM);
        ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE]
@@ -317,7 +314,7 @@ static int dm_test_lifecycle(struct unit_test_state *uts)
        ut_assert(!dev_get_priv(dev));
 
        /* Try again without the alloc failure */
-       dms->force_fail_alloc = 0;
+       uts->force_fail_alloc = 0;
        ut_assertok(device_probe(dev));
        ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE]
                        == op_count[DM_TEST_OP_PROBE] + 2);
@@ -349,19 +346,18 @@ DM_TEST(dm_test_lifecycle, UT_TESTF_SCAN_PDATA | UT_TESTF_PROBE_TEST);
 /* Test that we can bind/unbind and the lists update correctly */
 static int dm_test_ordering(struct unit_test_state *uts)
 {
-       struct dm_test_state *dms = uts->priv;
        struct udevice *dev, *dev_penultimate, *dev_last, *test_dev;
        int pingret;
 
-       ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+       ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
                                        &dev));
        ut_assert(dev);
 
        /* Bind two new devices (numbers 4 and 5) */
-       ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+       ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
                                        &dev_penultimate));
        ut_assert(dev_penultimate);
-       ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+       ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
                                        &dev_last));
        ut_assert(dev_last);
 
@@ -376,7 +372,7 @@ static int dm_test_ordering(struct unit_test_state *uts)
        ut_assert(dev_last == test_dev);
 
        /* Add back the original device 3, now in position 5 */
-       ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+       ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
                                        &dev));
        ut_assert(dev);
 
@@ -568,7 +564,6 @@ static int create_children(struct unit_test_state *uts, struct udevice *parent,
 
 static int dm_test_children(struct unit_test_state *uts)
 {
-       struct dm_test_state *dms = uts->priv;
        struct udevice *top[NODE_COUNT];
        struct udevice *child[NODE_COUNT];
        struct udevice *grandchild[NODE_COUNT];
@@ -578,12 +573,12 @@ static int dm_test_children(struct unit_test_state *uts)
        int i;
 
        /* We don't care about the numbering for this test */
-       dms->skip_post_probe = 1;
+       uts->skip_post_probe = 1;
 
        ut_assert(NODE_COUNT > 5);
 
        /* First create 10 top-level children */
-       ut_assertok(create_children(uts, dms->root, NODE_COUNT, 0, top));
+       ut_assertok(create_children(uts, uts->root, NODE_COUNT, 0, top));
 
        /* Now a few have their own children */
        ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL));
@@ -654,7 +649,6 @@ DM_TEST(dm_test_children, 0);
 
 static int dm_test_device_reparent(struct unit_test_state *uts)
 {
-       struct dm_test_state *dms = uts->priv;
        struct udevice *top[NODE_COUNT];
        struct udevice *child[NODE_COUNT];
        struct udevice *grandchild[NODE_COUNT];
@@ -664,12 +658,12 @@ static int dm_test_device_reparent(struct unit_test_state *uts)
        int i;
 
        /* We don't care about the numbering for this test */
-       dms->skip_post_probe = 1;
+       uts->skip_post_probe = 1;
 
        ut_assert(NODE_COUNT > 5);
 
        /* First create 10 top-level children */
-       ut_assertok(create_children(uts, dms->root, NODE_COUNT, 0, top));
+       ut_assertok(create_children(uts, uts->root, NODE_COUNT, 0, top));
 
        /* Now a few have their own children */
        ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL));
@@ -815,15 +809,14 @@ DM_TEST(dm_test_device_reparent, 0);
 /* Test that pre-relocation devices work as expected */
 static int dm_test_pre_reloc(struct unit_test_state *uts)
 {
-       struct dm_test_state *dms = uts->priv;
        struct udevice *dev;
 
        /* The normal driver should refuse to bind before relocation */
-       ut_asserteq(-EPERM, device_bind_by_name(dms->root, true,
+       ut_asserteq(-EPERM, device_bind_by_name(uts->root, true,
                                                &driver_info_manual, &dev));
 
        /* But this one is marked pre-reloc */
-       ut_assertok(device_bind_by_name(dms->root, true,
+       ut_assertok(device_bind_by_name(uts->root, true,
                                        &driver_info_pre_reloc, &dev));
 
        return 0;
@@ -836,10 +829,9 @@ DM_TEST(dm_test_pre_reloc, 0);
  */
 static int dm_test_remove_active_dma(struct unit_test_state *uts)
 {
-       struct dm_test_state *dms = uts->priv;
        struct udevice *dev;
 
-       ut_assertok(device_bind_by_name(dms->root, false, &driver_info_act_dma,
+       ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma,
                                        &dev));
        ut_assert(dev);
 
@@ -872,7 +864,7 @@ static int dm_test_remove_active_dma(struct unit_test_state *uts)
         * the active DMA remove call
         */
        ut_assertok(device_unbind(dev));
-       ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+       ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
                                        &dev));
        ut_assert(dev);
 
@@ -895,25 +887,24 @@ DM_TEST(dm_test_remove_active_dma, 0);
 /* Test removal of 'vital' devices */
 static int dm_test_remove_vital(struct unit_test_state *uts)
 {
-       struct dm_test_state *dms = uts->priv;
        struct udevice *normal, *dma, *vital, *dma_vital;
 
        /* Skip the behaviour in test_post_probe() */
-       dms->skip_post_probe = 1;
+       uts->skip_post_probe = 1;
 
-       ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+       ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
                                        &normal));
        ut_assertnonnull(normal);
 
-       ut_assertok(device_bind_by_name(dms->root, false, &driver_info_act_dma,
+       ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma,
                                        &dma));
        ut_assertnonnull(dma);
 
-       ut_assertok(device_bind_by_name(dms->root, false,
+       ut_assertok(device_bind_by_name(uts->root, false,
                                        &driver_info_vital_clk, &vital));
        ut_assertnonnull(vital);
 
-       ut_assertok(device_bind_by_name(dms->root, false,
+       ut_assertok(device_bind_by_name(uts->root, false,
                                        &driver_info_act_dma_vital_clk,
                                        &dma_vital));
        ut_assertnonnull(dma_vital);
@@ -1133,11 +1124,10 @@ DM_TEST(dm_test_uclass_names, UT_TESTF_SCAN_PDATA);
 
 static int dm_test_inactive_child(struct unit_test_state *uts)
 {
-       struct dm_test_state *dms = uts->priv;
        struct udevice *parent, *dev1, *dev2;
 
        /* Skip the behaviour in test_post_probe() */
-       dms->skip_post_probe = 1;
+       uts->skip_post_probe = 1;
 
        ut_assertok(uclass_first_device_err(UCLASS_TEST, &parent));
 
index d7b85e7..33ae987 100644 (file)
@@ -80,15 +80,15 @@ static int dm_test_gpio(struct unit_test_state *uts)
 
        /* Make it an open drain output, and reset it */
        ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
-                   sandbox_gpio_get_dir_flags(dev, offset));
-       ut_assertok(ops->set_dir_flags(dev, offset,
-                                      GPIOD_IS_OUT | GPIOD_OPEN_DRAIN));
+                   sandbox_gpio_get_flags(dev, offset));
+       ut_assertok(ops->set_flags(dev, offset,
+                                  GPIOD_IS_OUT | GPIOD_OPEN_DRAIN));
        ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
-                   sandbox_gpio_get_dir_flags(dev, offset));
-       ut_assertok(ops->set_dir_flags(dev, offset,
-                                      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
+                   sandbox_gpio_get_flags(dev, offset));
+       ut_assertok(ops->set_flags(dev, offset,
+                                  GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
        ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
-                   sandbox_gpio_get_dir_flags(dev, offset));
+                   sandbox_gpio_get_flags(dev, offset));
 
        /* Make it an input */
        ut_assertok(ops->direction_input(dev, offset));
@@ -176,54 +176,64 @@ static int dm_test_gpio_opendrain_opensource(struct unit_test_state *uts)
 
        /* GPIO 0 is (GPIO_OUT|GPIO_OPEN_DRAIN) */
        ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
-                   sandbox_gpio_get_dir_flags(gpio_c, 0));
+                   sandbox_gpio_get_flags(gpio_c, 0));
 
-       /* Set it as output high, should become an input */
+       /* Set it as output high */
        ut_assertok(dm_gpio_set_value(&desc_list[0], 1));
-       ut_assertok(gpio_get_status(gpio_c, 0, buf, sizeof(buf)));
-       ut_asserteq_str("c0: input: 0 [x] a-test.test3-gpios0", buf);
+       ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN | GPIOD_IS_OUT_ACTIVE,
+                   sandbox_gpio_get_flags(gpio_c, 0));
 
-       /* Set it as output low, should become output low */
+       /* Set it as output low */
        ut_assertok(dm_gpio_set_value(&desc_list[0], 0));
-       ut_assertok(gpio_get_status(gpio_c, 0, buf, sizeof(buf)));
-       ut_asserteq_str("c0: output: 0 [x] a-test.test3-gpios0", buf);
+       ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
+                   sandbox_gpio_get_flags(gpio_c, 0));
 
        /* GPIO 1 is (GPIO_OUT|GPIO_OPEN_SOURCE) */
        ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
-                   sandbox_gpio_get_dir_flags(gpio_c, 1));
+                   sandbox_gpio_get_flags(gpio_c, 1));
 
        /* Set it as output high, should become output high */
        ut_assertok(dm_gpio_set_value(&desc_list[1], 1));
        ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf)));
        ut_asserteq_str("c1: output: 1 [x] a-test.test3-gpios1", buf);
 
-       /* Set it as output low, should become an input */
+       /* Set it as output low */
        ut_assertok(dm_gpio_set_value(&desc_list[1], 0));
+       ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
+                   sandbox_gpio_get_flags(gpio_c, 1));
+
        ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf)));
-       ut_asserteq_str("c1: input: 1 [x] a-test.test3-gpios1", buf);
+       ut_asserteq_str("c1: output: 0 [x] a-test.test3-gpios1", buf);
 
-       /* GPIO 6 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN) */
-       ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
-                   sandbox_gpio_get_dir_flags(gpio_c, 6));
+       /*
+        * GPIO 6 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN). Looking at it
+        * directlt from the driver, we get GPIOD_IS_OUT_ACTIVE also, since it
+        * is active low
+        */
+       ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN |
+                   GPIOD_IS_OUT_ACTIVE,
+                   sandbox_gpio_get_flags(gpio_c, 6));
 
        /* Set it as output high, should become output low */
        ut_assertok(dm_gpio_set_value(&desc_list[6], 1));
        ut_assertok(gpio_get_status(gpio_c, 6, buf, sizeof(buf)));
        ut_asserteq_str("c6: output: 0 [x] a-test.test3-gpios6", buf);
 
-       /* Set it as output low, should become an input */
+       /* Set it as output low */
        ut_assertok(dm_gpio_set_value(&desc_list[6], 0));
-       ut_assertok(gpio_get_status(gpio_c, 6, buf, sizeof(buf)));
-       ut_asserteq_str("c6: input: 0 [x] a-test.test3-gpios6", buf);
+       ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN |
+                   GPIOD_IS_OUT_ACTIVE,
+                   sandbox_gpio_get_flags(gpio_c, 6));
 
        /* GPIO 7 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_SOURCE) */
-       ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
-                   sandbox_gpio_get_dir_flags(gpio_c, 7));
+       ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE |
+                   GPIOD_IS_OUT_ACTIVE,
+                   sandbox_gpio_get_flags(gpio_c, 7));
 
-       /* Set it as output high, should become an input */
+       /* Set it as output high */
        ut_assertok(dm_gpio_set_value(&desc_list[7], 1));
-       ut_assertok(gpio_get_status(gpio_c, 7, buf, sizeof(buf)));
-       ut_asserteq_str("c7: input: 0 [x] a-test.test3-gpios7", buf);
+       ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
+                   sandbox_gpio_get_flags(gpio_c, 7));
 
        /* Set it as output low, should become output high */
        ut_assertok(dm_gpio_set_value(&desc_list[7], 0));
@@ -363,12 +373,12 @@ static int dm_test_gpio_phandles(struct unit_test_state *uts)
        ut_assertok(gpio_free_list(dev, desc_list, 3));
 
        ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
-                   sandbox_gpio_get_dir_flags(gpio_a, 1));
+                   sandbox_gpio_get_flags(gpio_a, 1));
        ut_asserteq(6, gpio_request_list_by_name(dev, "test2-gpios", desc_list,
                                                 ARRAY_SIZE(desc_list), 0));
 
        /* This was set to output previously but flags resetted to 0 = INPUT */
-       ut_asserteq(0, sandbox_gpio_get_dir_flags(gpio_a, 1));
+       ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 1));
        ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 1, NULL));
 
        /* Active low should invert the input value */
@@ -397,22 +407,22 @@ static int dm_test_gpio_get_dir_flags(struct unit_test_state *uts)
        ut_asserteq(6, gpio_request_list_by_name(dev, "test3-gpios", desc_list,
                                                 ARRAY_SIZE(desc_list), 0));
 
-       ut_assertok(dm_gpio_get_dir_flags(&desc_list[0], &flags));
+       ut_assertok(dm_gpio_get_flags(&desc_list[0], &flags));
        ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, flags);
 
-       ut_assertok(dm_gpio_get_dir_flags(&desc_list[1], &flags));
+       ut_assertok(dm_gpio_get_flags(&desc_list[1], &flags));
        ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, flags);
 
-       ut_assertok(dm_gpio_get_dir_flags(&desc_list[2], &flags));
+       ut_assertok(dm_gpio_get_flags(&desc_list[2], &flags));
        ut_asserteq(GPIOD_IS_OUT, flags);
 
-       ut_assertok(dm_gpio_get_dir_flags(&desc_list[3], &flags));
+       ut_assertok(dm_gpio_get_flags(&desc_list[3], &flags));
        ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags);
 
-       ut_assertok(dm_gpio_get_dir_flags(&desc_list[4], &flags));
+       ut_assertok(dm_gpio_get_flags(&desc_list[4], &flags));
        ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_DOWN, flags);
 
-       ut_assertok(dm_gpio_get_dir_flags(&desc_list[5], &flags));
+       ut_assertok(dm_gpio_get_flags(&desc_list[5], &flags));
        ut_asserteq(GPIOD_IS_IN, flags);
 
        ut_assertok(gpio_free_list(dev, desc_list, 6));
@@ -582,3 +592,189 @@ static int dm_test_gpio_devm(struct unit_test_state *uts)
        return 0;
 }
 DM_TEST(dm_test_gpio_devm, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int dm_test_clrset_flags(struct unit_test_state *uts)
+{
+       struct gpio_desc desc;
+       struct udevice *dev;
+       ulong flags;
+
+       ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+       ut_asserteq_str("a-test", dev->name);
+       ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0));
+
+       ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_OUT));
+       ut_assertok(dm_gpio_get_flags(&desc, &flags));
+       ut_asserteq(GPIOD_IS_OUT, flags);
+       ut_asserteq(GPIOD_IS_OUT, desc.flags);
+       ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+       ut_assertok(dm_gpio_clrset_flags(&desc, 0, GPIOD_IS_OUT_ACTIVE));
+       ut_assertok(dm_gpio_get_flags(&desc, &flags));
+       ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, flags);
+       ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, desc.flags);
+       ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset));
+       ut_asserteq(1, dm_gpio_get_value(&desc));
+
+       ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN));
+       ut_assertok(dm_gpio_get_flags(&desc, &flags));
+       ut_asserteq(GPIOD_IS_IN, flags & GPIOD_MASK_DIR);
+       ut_asserteq(GPIOD_IS_IN, desc.flags & GPIOD_MASK_DIR);
+
+       ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_PULL,
+                                        GPIOD_PULL_UP));
+       ut_assertok(dm_gpio_get_flags(&desc, &flags));
+       ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags);
+       ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, desc.flags);
+
+       /* Check we cannot set both PULL_UP and PULL_DOWN */
+       ut_asserteq(-EINVAL, dm_gpio_clrset_flags(&desc, 0, GPIOD_PULL_DOWN));
+
+       return 0;
+}
+DM_TEST(dm_test_clrset_flags, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Check that an active-low GPIO works as expected */
+static int dm_test_clrset_flags_invert(struct unit_test_state *uts)
+{
+       struct gpio_desc desc;
+       struct udevice *dev;
+       ulong flags;
+
+       ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+       ut_asserteq_str("a-test", dev->name);
+       ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc,
+                                        GPIOD_IS_OUT | GPIOD_ACTIVE_LOW));
+
+       /*
+        * From this size we see it as 0 (active low), but the sandbox driver
+        * sees the pin value high
+        */
+       ut_asserteq(0, dm_gpio_get_value(&desc));
+       ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+       ut_assertok(dm_gpio_set_value(&desc, 1));
+       ut_asserteq(1, dm_gpio_get_value(&desc));
+       ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+       /* Do the same with dm_gpio_clrset_flags() */
+       ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_IS_OUT_ACTIVE, 0));
+       ut_asserteq(0, dm_gpio_get_value(&desc));
+       ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+       ut_assertok(dm_gpio_clrset_flags(&desc, 0, GPIOD_IS_OUT_ACTIVE));
+       ut_asserteq(1, dm_gpio_get_value(&desc));
+       ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+       ut_assertok(dm_gpio_get_flags(&desc, &flags));
+       ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE,
+                   flags);
+       ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE,
+                   desc.flags);
+
+       ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_IS_OUT_ACTIVE, 0));
+       ut_assertok(dm_gpio_get_flags(&desc, &flags));
+       ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW, flags);
+       ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW, desc.flags);
+
+       return 0;
+}
+DM_TEST(dm_test_clrset_flags_invert, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int set_gpios(struct unit_test_state *uts, struct gpio_desc *desc,
+                    int count, uint value)
+{
+       int i;
+
+       for (i = 0; i < count; i++) {
+               const uint mask = 1 << i;
+
+               ut_assertok(sandbox_gpio_set_value(desc[i].dev, desc[i].offset,
+                                                  value & mask));
+       }
+
+       return 0;
+}
+
+/* Check that an active-low GPIO works as expected */
+static int dm_test_gpio_get_values_as_int(struct unit_test_state *uts)
+{
+       const int gpio_count = 3;
+       struct gpio_desc desc[gpio_count];
+       struct udevice *dev;
+
+       ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+       ut_asserteq_str("a-test", dev->name);
+
+       ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc,
+                                                gpio_count, GPIOD_IS_IN));
+       ut_assertok(set_gpios(uts, desc, gpio_count, 0));
+       ut_asserteq(0, dm_gpio_get_values_as_int(desc, gpio_count));
+
+       ut_assertok(set_gpios(uts, desc, gpio_count, 5));
+       ut_asserteq(5, dm_gpio_get_values_as_int(desc, gpio_count));
+
+       ut_assertok(set_gpios(uts, desc, gpio_count, 7));
+       ut_asserteq(7, dm_gpio_get_values_as_int(desc, gpio_count));
+
+       return 0;
+}
+DM_TEST(dm_test_gpio_get_values_as_int,
+       UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Check that an active-low GPIO works as expected */
+static int dm_test_gpio_get_values_as_int_base3(struct unit_test_state *uts)
+{
+       const int gpio_count = 3;
+       struct gpio_desc desc[gpio_count];
+       struct udevice *dev;
+
+       ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+       ut_asserteq_str("a-test", dev->name);
+
+       ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc,
+                                                gpio_count, GPIOD_IS_IN));
+
+       /*
+        * First test the sandbox GPIO driver works as expected. The external
+        * pull resistor should be stronger than the internal one.
+        */
+       sandbox_gpio_set_flags(desc[0].dev, desc[0].offset,
+                              GPIOD_IS_IN | GPIOD_EXT_PULL_UP | GPIOD_PULL_UP);
+       ut_asserteq(1, dm_gpio_get_value(desc));
+
+       sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_IS_IN |
+                              GPIOD_EXT_PULL_DOWN | GPIOD_PULL_UP);
+       ut_asserteq(0, dm_gpio_get_value(desc));
+
+       sandbox_gpio_set_flags(desc[0].dev, desc[0].offset,
+                              GPIOD_IS_IN | GPIOD_PULL_UP);
+       ut_asserteq(1, dm_gpio_get_value(desc));
+
+       sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_PULL_DOWN);
+       ut_asserteq(0, dm_gpio_get_value(desc));
+
+       /*
+        * Set up pins: pull-up (1), pull-down (0) and floating (2). This should
+        * result in digits 2 0 1, i.e. 2 * 9 + 1 * 3 = 19
+        */
+       sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_EXT_PULL_UP);
+       sandbox_gpio_set_flags(desc[1].dev, desc[1].offset,
+                              GPIOD_EXT_PULL_DOWN);
+       sandbox_gpio_set_flags(desc[2].dev, desc[2].offset, 0);
+       ut_asserteq(19, dm_gpio_get_values_as_int_base3(desc, gpio_count));
+
+       /*
+        * Set up pins: floating (2), pull-up (1) and pull-down (0). This should
+        * result in digits 0 1 2, i.e. 1 * 3 + 2 = 5
+        */
+       sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, 0);
+       sandbox_gpio_set_flags(desc[1].dev, desc[1].offset, GPIOD_EXT_PULL_UP);
+       sandbox_gpio_set_flags(desc[2].dev, desc[2].offset,
+                              GPIOD_EXT_PULL_DOWN);
+       ut_asserteq(5, dm_gpio_get_values_as_int_base3(desc, gpio_count));
+
+       return 0;
+}
+DM_TEST(dm_test_gpio_get_values_as_int_base3,
+       UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
index e9804cc..0f89c7a 100644 (file)
@@ -142,12 +142,14 @@ static int find_driver_info(struct unit_test_state *uts, struct udevice *parent,
 /* Check that every device is recorded in its driver_info struct */
 static int dm_test_of_plat_dev(struct unit_test_state *uts)
 {
-       const struct driver_info *info =
-               ll_entry_start(struct driver_info, driver_info);
        const int n_ents = ll_entry_count(struct driver_info, driver_info);
        bool found[n_ents];
        uint i;
 
+       /* Skip this test if there is no platform data */
+       if (!CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT))
+               return 0;
+
        /* Record the indexes that are found */
        memset(found, '\0', sizeof(found));
        ut_assertok(find_driver_info(uts, gd->dm_root, found));
@@ -155,18 +157,16 @@ static int dm_test_of_plat_dev(struct unit_test_state *uts)
        /* Make sure that the driver entries without devices have no ->dev */
        for (i = 0; i < n_ents; i++) {
                const struct driver_rt *drt = gd_dm_driver_rt() + i;
-               const struct driver_info *entry = info + i;
                struct udevice *dev;
 
                if (found[i]) {
                        /* Make sure we can find it */
                        ut_assertnonnull(drt->dev);
-                       ut_assertok(device_get_by_driver_info(entry, &dev));
+                       ut_assertok(device_get_by_ofplat_idx(i, &dev));
                        ut_asserteq_ptr(dev, drt->dev);
                } else {
                        ut_assertnull(drt->dev);
-                       ut_asserteq(-ENOENT,
-                                   device_get_by_driver_info(entry, &dev));
+                       ut_asserteq(-ENOENT, device_get_by_ofplat_idx(i, &dev));
                }
        }
 
@@ -184,22 +184,22 @@ static int dm_test_of_plat_phandle(struct unit_test_state *uts)
        ut_asserteq_str("sandbox_clk_test", dev->name);
        plat = dev_get_plat(dev);
 
-       ut_assertok(device_get_by_driver_info_idx(plat->clocks[0].idx, &clk));
-       ut_asserteq_str("fixed_clock", clk->name);
+       ut_assertok(device_get_by_ofplat_idx(plat->clocks[0].idx, &clk));
+       ut_asserteq_str("sandbox_fixed_clock", clk->name);
 
-       ut_assertok(device_get_by_driver_info_idx(plat->clocks[1].idx, &clk));
+       ut_assertok(device_get_by_ofplat_idx(plat->clocks[1].idx, &clk));
        ut_asserteq_str("sandbox_clk", clk->name);
        ut_asserteq(1, plat->clocks[1].arg[0]);
 
-       ut_assertok(device_get_by_driver_info_idx(plat->clocks[2].idx, &clk));
+       ut_assertok(device_get_by_ofplat_idx(plat->clocks[2].idx, &clk));
        ut_asserteq_str("sandbox_clk", clk->name);
        ut_asserteq(0, plat->clocks[2].arg[0]);
 
-       ut_assertok(device_get_by_driver_info_idx(plat->clocks[3].idx, &clk));
+       ut_assertok(device_get_by_ofplat_idx(plat->clocks[3].idx, &clk));
        ut_asserteq_str("sandbox_clk", clk->name);
        ut_asserteq(3, plat->clocks[3].arg[0]);
 
-       ut_assertok(device_get_by_driver_info_idx(plat->clocks[4].idx, &clk));
+       ut_assertok(device_get_by_ofplat_idx(plat->clocks[4].idx, &clk));
        ut_asserteq_str("sandbox_clk", clk->name);
        ut_asserteq(2, plat->clocks[4].arg[0]);
 
@@ -211,11 +211,11 @@ DM_TEST(dm_test_of_plat_phandle, UT_TESTF_SCAN_PDATA);
 /* Test that device parents are correctly set up */
 static int dm_test_of_plat_parent(struct unit_test_state *uts)
 {
-       struct udevice *dev, *bus;
+       struct udevice *rtc, *i2c;
 
-       ut_assertok(uclass_first_device_err(UCLASS_SIMPLE_BUS, &bus));
-       ut_assertok(device_first_child_err(bus, &dev));
-       ut_asserteq_ptr(bus, dev_get_parent(dev));
+       ut_assertok(uclass_first_device_err(UCLASS_RTC, &rtc));
+       ut_assertok(uclass_first_device_err(UCLASS_I2C, &i2c));
+       ut_asserteq_ptr(i2c, dev_get_parent(rtc));
 
        return 0;
 }
index cc1fc4d..17d43fe 100644 (file)
@@ -21,7 +21,7 @@
 /* Simple test of sandbox SPI flash */
 static int dm_test_spi_flash(struct unit_test_state *uts)
 {
-       struct udevice *dev;
+       struct udevice *dev, *emul;
        int full_size = 0x200000;
        int size = 0x10000;
        u8 *src, *dst;
@@ -51,6 +51,14 @@ static int dm_test_spi_flash(struct unit_test_state *uts)
        ut_assertok(spi_flash_read_dm(dev, 0, size, dst));
        ut_asserteq_mem(src, dst, size);
 
+       /* Try the write-protect stuff */
+       ut_assertok(uclass_first_device_err(UCLASS_SPI_EMUL, &emul));
+       ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
+       sandbox_sf_set_block_protect(emul, 1);
+       ut_asserteq(1, spl_flash_get_sw_write_prot(dev));
+       sandbox_sf_set_block_protect(emul, 0);
+       ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
+
        /* Check mapping */
        ut_assertok(dm_spi_get_mmap(dev, &map_base, &map_size, &offset));
        ut_asserteq(0x1000, map_base);
diff --git a/test/dm/test-dm.c b/test/dm/test-dm.c
new file mode 100644 (file)
index 0000000..9ba2ba2
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 Google, Inc
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <asm/state.h>
+#include <dm/root.h>
+#include <dm/uclass-internal.h>
+#include <test/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * dm_test_run() - Run driver model tests
+ *
+ * Run all the available driver model tests, or a selection
+ *
+ * @test_name: Name of single test to run (e.g. "dm_test_fdt_pre_reloc" or just
+ *     "fdt_pre_reloc"), or NULL to run all
+ * @return 0 if all tests passed, 1 if not
+ */
+static int dm_test_run(const char *test_name)
+{
+       struct unit_test *tests = UNIT_TEST_SUITE_START(dm_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(dm_test);
+       int ret;
+
+       ret = ut_run_list("driver model", "dm_test_", tests, n_ents, test_name);
+
+       return ret ? CMD_RET_FAILURE : 0;
+}
+
+int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+       const char *test_name = NULL;
+
+       if (argc > 1)
+               test_name = argv[1];
+
+       return dm_test_run(test_name);
+}
index ca7626a..02cb974 100644 (file)
@@ -18,7 +18,6 @@
 #include <test/ut.h>
 
 int dm_testdrv_op_count[DM_TEST_OP_COUNT];
-static struct unit_test_state *uts = &global_dm_test_state;
 
 static int testdrv_ping(struct udevice *dev, int pingval, int *pingret)
 {
@@ -37,6 +36,8 @@ static const struct test_ops test_ops = {
 
 static int test_bind(struct udevice *dev)
 {
+       struct unit_test_state *uts = test_get_state();
+
        /* Private data should not be allocated */
        ut_assert(!dev_get_priv(dev));
 
@@ -46,6 +47,7 @@ static int test_bind(struct udevice *dev)
 
 static int test_probe(struct udevice *dev)
 {
+       struct unit_test_state *uts = test_get_state();
        struct dm_test_priv *priv = dev_get_priv(dev);
 
        /* Private data should be allocated */
@@ -58,6 +60,8 @@ static int test_probe(struct udevice *dev)
 
 static int test_remove(struct udevice *dev)
 {
+       struct unit_test_state *uts = test_get_state();
+
        /* Private data should still be allocated */
        ut_assert(dev_get_priv(dev));
 
@@ -67,6 +71,8 @@ static int test_remove(struct udevice *dev)
 
 static int test_unbind(struct udevice *dev)
 {
+       struct unit_test_state *uts = test_get_state();
+
        /* Private data should not be allocated */
        ut_assert(!dev_get_priv(dev));
 
@@ -116,10 +122,10 @@ static int test_manual_bind(struct udevice *dev)
 
 static int test_manual_probe(struct udevice *dev)
 {
-       struct dm_test_state *dms = uts->priv;
+       struct unit_test_state *uts = test_get_state();
 
        dm_testdrv_op_count[DM_TEST_OP_PROBE]++;
-       if (!dms->force_fail_alloc)
+       if (!uts->force_fail_alloc)
                dev_set_priv(dev, calloc(1, sizeof(struct dm_test_priv)));
        if (!dev_get_priv(dev))
                return -ENOMEM;
index 6e83aee..6552d09 100644 (file)
@@ -330,7 +330,7 @@ static int dm_test_fdt_uclass_seq_more(struct unit_test_state *uts)
 
        /* Check creating a device with an alias */
        node = ofnode_path("/some-bus/c-test@1");
-       ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(testfdt_drv),
+       ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test),
                                "c-test@1", NULL, node, &dev));
        ut_asserteq(12, dev_seq(dev));
        ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 12, &dev));
@@ -350,11 +350,11 @@ static int dm_test_fdt_uclass_seq_more(struct unit_test_state *uts)
         *
         * So next available is 19
         */
-       ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(testfdt_drv),
+       ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test),
                                "fred", NULL, ofnode_null(), &dev));
        ut_asserteq(19, dev_seq(dev));
 
-       ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(testfdt_drv),
+       ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test),
                                "fred2", NULL, ofnode_null(), &dev));
        ut_asserteq(20, dev_seq(dev));
 
diff --git a/test/dm/test-main.c b/test/dm/test-main.c
deleted file mode 100644 (file)
index 560f8d6..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2013 Google, Inc
- */
-
-#include <common.h>
-#include <command.h>
-#include <console.h>
-#include <dm.h>
-#include <errno.h>
-#include <log.h>
-#include <malloc.h>
-#include <asm/global_data.h>
-#include <asm/state.h>
-#include <dm/test.h>
-#include <dm/root.h>
-#include <dm/uclass-internal.h>
-#include <test/test.h>
-#include <test/test.h>
-#include <test/ut.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct unit_test_state global_dm_test_state;
-static struct dm_test_state _global_priv_dm_test_state;
-
-/* Get ready for testing */
-static int dm_test_init(struct unit_test_state *uts, bool of_live)
-{
-       struct dm_test_state *dms = uts->priv;
-
-       memset(dms, '\0', sizeof(*dms));
-       gd->dm_root = NULL;
-       if (!CONFIG_IS_ENABLED(OF_PLATDATA))
-               memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count));
-       state_reset_for_test(state_get_current());
-
-       /* Determine whether to make the live tree available */
-       gd_set_of_root(of_live ? uts->of_root : NULL);
-       ut_assertok(dm_init(of_live));
-       dms->root = dm_root();
-
-       return 0;
-}
-
-/* Ensure all the test devices are probed */
-static int do_autoprobe(struct unit_test_state *uts)
-{
-       struct udevice *dev;
-       int ret;
-
-       /* Scanning the uclass is enough to probe all the devices */
-       for (ret = uclass_first_device(UCLASS_TEST, &dev);
-            dev;
-            ret = uclass_next_device(&dev))
-               ;
-
-       return ret;
-}
-
-static int dm_test_destroy(struct unit_test_state *uts)
-{
-       int id;
-
-       for (id = 0; id < UCLASS_COUNT; id++) {
-               struct uclass *uc;
-
-               /*
-                * If the uclass doesn't exist we don't want to create it. So
-                * check that here before we call uclass_find_device().
-                */
-               uc = uclass_find(id);
-               if (!uc)
-                       continue;
-               ut_assertok(uclass_destroy(uc));
-       }
-
-       return 0;
-}
-
-static int dm_do_test(struct unit_test_state *uts, struct unit_test *test,
-                     bool of_live)
-{
-       struct sandbox_state *state = state_get_current();
-       const char *fname = strrchr(test->file, '/') + 1;
-
-       printf("Test: %s: %s%s\n", test->name, fname,
-              !of_live ? " (flat tree)" : "");
-       ut_assertok(dm_test_init(uts, of_live));
-
-       uts->start = mallinfo();
-       if (test->flags & UT_TESTF_SCAN_PDATA)
-               ut_assertok(dm_scan_plat(false));
-       if (test->flags & UT_TESTF_PROBE_TEST)
-               ut_assertok(do_autoprobe(uts));
-       if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
-           (test->flags & UT_TESTF_SCAN_FDT))
-               ut_assertok(dm_extended_scan(false));
-
-       /*
-        * Silence the console and rely on console recording to get
-        * our output.
-        */
-       console_record_reset_enable();
-       if (!state->show_test_output)
-               gd->flags |= GD_FLG_SILENT;
-       test->func(uts);
-       gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
-       state_set_skip_delays(false);
-
-       ut_assertok(dm_test_destroy(uts));
-
-       return 0;
-}
-
-/**
- * dm_test_run_on_flattree() - Check if we should run a test with flat DT
- *
- * This skips long/slow tests where there is not much value in running a flat
- * DT test in addition to a live DT test.
- *
- * @return true to run the given test on the flat device tree
- */
-static bool dm_test_run_on_flattree(struct unit_test *test)
-{
-       const char *fname = strrchr(test->file, '/') + 1;
-
-       return !strstr(fname, "video") || strstr(test->name, "video_base");
-}
-
-static bool test_matches(const char *test_name, const char *find_name)
-{
-       if (!find_name)
-               return true;
-
-       if (!strcmp(test_name, find_name))
-               return true;
-
-       /* All tests have this prefix */
-       if (!strncmp(test_name, "dm_test_", 8))
-               test_name += 8;
-
-       if (!strcmp(test_name, find_name))
-               return true;
-
-       return false;
-}
-
-int dm_test_main(const char *test_name)
-{
-       struct unit_test *tests = ll_entry_start(struct unit_test, dm_test);
-       const int n_ents = ll_entry_count(struct unit_test, dm_test);
-       struct unit_test_state *uts = &global_dm_test_state;
-       struct unit_test *test;
-       int found;
-
-       uts->priv = &_global_priv_dm_test_state;
-       uts->fail_count = 0;
-
-       if (!CONFIG_IS_ENABLED(OF_PLATDATA)) {
-               /*
-                * If we have no device tree, or it only has a root node, then
-                * these * tests clearly aren't going to work...
-                */
-               if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) {
-                       puts("Please run with test device tree:\n"
-                            "    ./u-boot -d arch/sandbox/dts/test.dtb\n");
-                       ut_assert(gd->fdt_blob);
-               }
-       }
-
-       if (!test_name)
-               printf("Running %d driver model tests\n", n_ents);
-       else
-
-       found = 0;
-       uts->of_root = gd_of_root();
-       for (test = tests; test < tests + n_ents; test++) {
-               const char *name = test->name;
-               int runs;
-
-               if (!test_matches(name, test_name))
-                       continue;
-
-               /* Run with the live tree if possible */
-               runs = 0;
-               if (CONFIG_IS_ENABLED(OF_LIVE)) {
-                       if (!(test->flags & UT_TESTF_FLAT_TREE)) {
-                               ut_assertok(dm_do_test(uts, test, true));
-                               runs++;
-                       }
-               }
-
-               /*
-                * Run with the flat tree if we couldn't run it with live tree,
-                * or it is a core test.
-                */
-               if (!(test->flags & UT_TESTF_LIVE_TREE) &&
-                   (!runs || dm_test_run_on_flattree(test))) {
-                       ut_assertok(dm_do_test(uts, test, false));
-                       runs++;
-               }
-               found++;
-       }
-
-       if (test_name && !found)
-               printf("Test '%s' not found\n", test_name);
-       else
-               printf("Failures: %d\n", uts->fail_count);
-
-       /* Put everything back to normal so that sandbox works as expected */
-       gd_set_of_root(uts->of_root);
-       gd->dm_root = NULL;
-       ut_assertok(dm_init(CONFIG_IS_ENABLED(OF_LIVE)));
-       dm_scan_plat(false);
-       if (!CONFIG_IS_ENABLED(OF_PLATDATA))
-               dm_scan_fdt(false);
-
-       return uts->fail_count ? CMD_RET_FAILURE : 0;
-}
-
-int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
-       const char *test_name = NULL;
-
-       if (argc > 1)
-               test_name = argv[1];
-
-       return dm_test_main(test_name);
-}
index f1b7aaa..0677017 100644 (file)
@@ -17,8 +17,6 @@
 #include <test/test.h>
 #include <test/ut.h>
 
-static struct unit_test_state *uts = &global_dm_test_state;
-
 int test_ping(struct udevice *dev, int pingval, int *pingret)
 {
        const struct test_ops *ops = device_get_ops(dev);
@@ -31,6 +29,7 @@ int test_ping(struct udevice *dev, int pingval, int *pingret)
 
 static int test_post_bind(struct udevice *dev)
 {
+       struct unit_test_state *uts = test_get_state();
        struct dm_test_perdev_uc_pdata *uc_pdata;
 
        dm_testdrv_op_count[DM_TEST_OP_POST_BIND]++;
@@ -56,6 +55,7 @@ static int test_pre_unbind(struct udevice *dev)
 static int test_pre_probe(struct udevice *dev)
 {
        struct dm_test_uclass_perdev_priv *priv = dev_get_uclass_priv(dev);
+       struct unit_test_state *uts = test_get_state();
 
        dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]++;
        ut_assert(priv);
@@ -66,18 +66,18 @@ static int test_pre_probe(struct udevice *dev)
 
 static int test_post_probe(struct udevice *dev)
 {
+       struct unit_test_state *uts = test_get_state();
        struct udevice *prev = list_entry(dev->uclass_node.prev,
                                            struct udevice, uclass_node);
 
        struct dm_test_uclass_perdev_priv *priv = dev_get_uclass_priv(dev);
        struct uclass *uc = dev->uclass;
-       struct dm_test_state *dms = uts->priv;
 
        dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]++;
        ut_assert(priv);
        ut_assert(device_active(dev));
        priv->base_add = 0;
-       if (dms->skip_post_probe)
+       if (uts->skip_post_probe)
                return 0;
        if (&prev->uclass_node != &uc->dev_head) {
                struct dm_test_uclass_perdev_priv *prev_uc_priv
@@ -101,6 +101,8 @@ static int test_pre_remove(struct udevice *dev)
 
 static int test_init(struct uclass *uc)
 {
+       struct unit_test_state *uts = test_get_state();
+
        dm_testdrv_op_count[DM_TEST_OP_INIT]++;
        ut_assert(uclass_get_priv(uc));
 
index a440b1b..d65a321 100644 (file)
@@ -12,8 +12,8 @@
 
 int do_ut_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test, env_test);
-       const int n_ents = ll_entry_count(struct unit_test, env_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(env_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(env_test);
 
        return cmd_ut_category("environment", "env_test_",
                               tests, n_ents, argc, argv);
diff --git a/test/image/Makefile b/test/image/Makefile
new file mode 100644 (file)
index 0000000..c4039df
--- /dev/null
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2021 Google LLC
+
+obj-$(CONFIG_SPL_BUILD) += spl_load.o
diff --git a/test/image/spl_load.c b/test/image/spl_load.c
new file mode 100644 (file)
index 0000000..851603d
--- /dev/null
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <image.h>
+#include <mapmem.h>
+#include <os.h>
+#include <spl.h>
+#include <test/ut.h>
+
+/* Declare a new SPL test */
+#define SPL_TEST(_name, _flags)                UNIT_TEST(_name, _flags, spl_test)
+
+/* Context used for this test */
+struct text_ctx {
+       int fd;
+};
+
+static ulong read_fit_image(struct spl_load_info *load, ulong sector,
+                           ulong count, void *buf)
+{
+       struct text_ctx *text_ctx = load->priv;
+       off_t offset, ret;
+       ssize_t res;
+
+       offset = sector * load->bl_len;
+       ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET);
+       if (ret != offset) {
+               printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset,
+                      ret, errno);
+               return 0;
+       }
+
+       res = os_read(text_ctx->fd, buf, count * load->bl_len);
+       if (res == -1) {
+               printf("Failed to read %lx bytes, got %ld (errno=%d)\n",
+                      count * load->bl_len, res, errno);
+               return 0;
+       }
+
+       return count;
+}
+
+int board_fit_config_name_match(const char *name)
+{
+       return 0;
+}
+
+struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+       return map_sysmem(0x100000, 0);
+}
+
+static int spl_test_load(struct unit_test_state *uts)
+{
+       struct spl_image_info image;
+       struct image_header *header;
+       struct text_ctx text_ctx;
+       struct spl_load_info load;
+       char fname[256];
+       int ret;
+       int fd;
+
+       memset(&load, '\0', sizeof(load));
+       load.bl_len = 512;
+       load.read = read_fit_image;
+
+       ret = os_find_u_boot(fname, sizeof(fname), true);
+       if (ret) {
+               printf("(%s not found, error %d)\n", fname, ret);
+               return ret;
+       }
+       load.filename = fname;
+
+       header = spl_get_load_buffer(-sizeof(*header), sizeof(*header));
+
+       fd = os_open(fname, OS_O_RDONLY);
+       ut_assert(fd >= 0);
+       ut_asserteq(512, os_read(fd, header, 512));
+       text_ctx.fd = fd;
+
+       load.priv = &text_ctx;
+
+       ut_assertok(spl_load_simple_fit(&image, &load, 0, header));
+
+       return 0;
+}
+SPL_TEST(spl_test_load, 0);
index f5c7bf3..f1ac015 100644 (file)
@@ -13,8 +13,8 @@
 
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test, lib_test);
-       const int n_ents = ll_entry_count(struct unit_test, lib_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(lib_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(lib_test);
 
        return cmd_ut_category("lib", "lib_test_", tests, n_ents, argc, argv);
 }
index 12972f1..a60a5a5 100644 (file)
@@ -18,12 +18,14 @@ DECLARE_GLOBAL_DATA_PTR;
 static int test_print_freq(struct unit_test_state *uts,
                           uint64_t freq, char *expected)
 {
+       ut_silence_console(uts);
        console_record_reset_enable();
        print_freq(freq, ";\n");
-       gd->flags &= ~GD_FLG_RECORD;
+       ut_unsilence_console(uts);
        console_record_readline(uts->actual_str, sizeof(uts->actual_str));
        ut_asserteq_str(expected, uts->actual_str);
        ut_assertok(ut_check_console_end(uts));
+
        return 0;
 }
 
@@ -46,12 +48,14 @@ LIB_TEST(lib_test_print_freq, 0);
 static int test_print_size(struct unit_test_state *uts,
                           uint64_t freq, char *expected)
 {
+       ut_silence_console(uts);
        console_record_reset_enable();
        print_size(freq, ";\n");
-       gd->flags &= ~GD_FLG_RECORD;
+       ut_unsilence_console(uts);
        console_record_readline(uts->actual_str, sizeof(uts->actual_str));
        ut_asserteq_str(expected, uts->actual_str);
        ut_assertok(ut_check_console_end(uts));
+
        return 0;
 }
 
index 3f09deb..a3dedac 100644 (file)
@@ -7,7 +7,7 @@ obj-$(CONFIG_CMD_LOG) += log_filter.o
 
 ifdef CONFIG_UT_LOG
 
-obj-y += test-main.o
+obj-y += log_ut.o
 
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_LOG_SYSLOG) += syslog_test.o
index 16379a7..de7b7f0 100644 (file)
@@ -15,8 +15,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define BUFFSIZE 64
-
 static int log_test_cont(struct unit_test_state *uts)
 {
        int log_fmt;
@@ -29,12 +27,13 @@ static int log_test_cont(struct unit_test_state *uts)
        gd->log_fmt = (1 << LOGF_CAT) | (1 << LOGF_LEVEL) | (1 << LOGF_MSG);
        gd->default_log_level = LOGL_INFO;
        console_record_reset_enable();
-       log(LOGC_ARCH, LOGL_ERR, "ea%d ", 1);
+       log(LOGC_ARCH, LOGL_ERR, "ea%d\n", 1);
        log(LOGC_CONT, LOGL_CONT, "cc%d\n", 2);
        gd->default_log_level = log_level;
        gd->log_fmt = log_fmt;
        gd->flags &= ~GD_FLG_RECORD;
-       ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1 ERR.arch, cc2"));
+       ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1"));
+       ut_assertok(ut_check_console_line(uts, "ERR.arch, cc2"));
        ut_assertok(ut_check_console_end(uts));
 
        /* Write a third message which is not a continuation */
@@ -48,6 +47,18 @@ static int log_test_cont(struct unit_test_state *uts)
        ut_assertok(ut_check_console_line(uts, "INFO.efi, ie3"));
        ut_assertok(ut_check_console_end(uts));
 
+       /* Write two messages without a newline between them */
+       gd->log_fmt = (1 << LOGF_CAT) | (1 << LOGF_LEVEL) | (1 << LOGF_MSG);
+       gd->default_log_level = LOGL_INFO;
+       console_record_reset_enable();
+       log(LOGC_ARCH, LOGL_ERR, "ea%d ", 1);
+       log(LOGC_CONT, LOGL_CONT, "cc%d\n", 2);
+       gd->default_log_level = log_level;
+       gd->log_fmt = log_fmt;
+       gd->flags &= ~GD_FLG_RECORD;
+       ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1 cc2"));
+       ut_assertok(ut_check_console_end(uts));
+
        return 0;
 }
 LOG_TEST(log_test_cont);
similarity index 75%
rename from test/log/test-main.c
rename to test/log/log_ut.c
index c534add..5aa3a18 100644 (file)
@@ -13,8 +13,8 @@
 
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test, log_test);
-       const int n_ents = ll_entry_count(struct unit_test, log_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(log_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(log_test);
 
        return cmd_ut_category("log", "log_test_",
                               tests, n_ents, argc, argv);
index 9fa4c91..c3887ab 100644 (file)
@@ -94,9 +94,8 @@ OPTEE_TEST(optee_fdt_protected_memory, 0);
 
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test,
-                                                optee_test);
-       const int n_ents = ll_entry_count(struct unit_test, optee_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(optee_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(optee_test);
        struct unit_test_state *uts;
        void *fdt_optee = &__dtb_test_optee_optee_begin;
        void *fdt_no_optee = &__dtb_test_optee_no_optee_begin;
index c001fb1..56a3df1 100644 (file)
@@ -213,9 +213,8 @@ OVERLAY_TEST(fdt_overlay_stacked, 0);
 
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test,
-                                                overlay_test);
-       const int n_ents = ll_entry_count(struct unit_test, overlay_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(overlay_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(overlay_test);
        struct unit_test_state *uts;
        void *fdt_base = &__dtb_test_fdt_base_begin;
        void *fdt_overlay = &__dtb_test_fdt_overlay_begin;
index 9bfd926..1b909cd 100644 (file)
@@ -226,7 +226,7 @@ def pytest_configure(config):
         import u_boot_console_exec_attach
         console = u_boot_console_exec_attach.ConsoleExecAttach(log, ubconfig)
 
-re_ut_test_list = re.compile(r'_u_boot_list_2_(.*)_test_2_\1_test_(.*)\s*$')
+re_ut_test_list = re.compile(r'_u_boot_list_2_ut_(.*)_test_2_\1_test_(.*)\s*$')
 def generate_ut_subtest(metafunc, fixture_name, sym_path):
     """Provide parametrization for a ut_subtest fixture.
 
index f006fa9..160a64a 100644 (file)
@@ -39,7 +39,7 @@ class TestEfiCapsuleFirmwareFit(object):
         with u_boot_console.log.section('Test Case 1-a, before reboot'):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
-                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi ""',
                 'efidebug boot order 1',
                 'env set -e OsIndications',
                 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
@@ -114,7 +114,7 @@ class TestEfiCapsuleFirmwareFit(object):
         with u_boot_console.log.section('Test Case 2-a, before reboot'):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
-                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi ""',
                 'efidebug boot order 1',
                 'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
                 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
@@ -188,7 +188,7 @@ class TestEfiCapsuleFirmwareFit(object):
         with u_boot_console.log.section('Test Case 3-a, before reboot'):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
-                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi ""',
                 'efidebug boot order 1',
                 'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
                 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
@@ -229,6 +229,14 @@ class TestEfiCapsuleFirmwareFit(object):
                 output = u_boot_console.run_command(
                     'env print -e -all Capsule0000')
 
+            output = u_boot_console.run_command_list(['efidebug capsule esrt'])
+
+            # ensure that EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID is in the ESRT.
+            assert 'AE13FF2D-9AD4-4E25-9AC8-6D80B3B22147' in ''.join(output)
+
+            # ensure that  EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID is in the ESRT.
+            assert 'E2BB9C06-70E9-4B14-97A3-5A7913176E3F' in ''.join(output)
+
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
                 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
index 863685e..75f5ea7 100644 (file)
@@ -28,7 +28,7 @@ class TestEfiSignedImage(object):
             # Test Case 1a, run signed image if no PK
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
-                'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert 'Hello, world!' in ''.join(output)
@@ -36,7 +36,7 @@ class TestEfiSignedImage(object):
         with u_boot_console.log.section('Test Case 1b'):
             # Test Case 1b, run unsigned image if no PK
             output = u_boot_console.run_command_list([
-                'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 2 HELLO2 host 0:1 /helloworld.efi ""',
                 'efidebug boot next 2',
                 'bootefi bootmgr'])
             assert 'Hello, world!' in ''.join(output)
@@ -58,13 +58,13 @@ class TestEfiSignedImage(object):
                 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
             assert 'Failed to set EFI variable' not in ''.join(output)
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert('\'HELLO1\' failed' in ''.join(output))
             assert('efi_start_image() returned: 26' in ''.join(output))
             output = u_boot_console.run_command_list([
-                'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 2 HELLO2 host 0:1 /helloworld.efi ""',
                 'efidebug boot next 2',
                 'efidebug test bootmgr'])
             assert '\'HELLO2\' failed' in ''.join(output)
@@ -104,7 +104,7 @@ class TestEfiSignedImage(object):
                 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
             assert 'Failed to set EFI variable' not in ''.join(output)
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert '\'HELLO\' failed' in ''.join(output)
@@ -142,7 +142,7 @@ class TestEfiSignedImage(object):
                 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
             assert 'Failed to set EFI variable' not in ''.join(output)
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert '\'HELLO\' failed' in ''.join(output)
@@ -169,7 +169,7 @@ class TestEfiSignedImage(object):
                 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
             assert 'Failed to set EFI variable' not in ''.join(output)
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert 'Hello, world!' in ''.join(output)
@@ -227,7 +227,7 @@ class TestEfiSignedImage(object):
                 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
             assert 'Failed to set EFI variable' not in ''.join(output)
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert 'Hello, world!' in ''.join(output)
index 70d6be0..0849572 100644 (file)
@@ -39,7 +39,7 @@ class TestEfiSignedImageIntca(object):
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO_a host 0:1 /helloworld.efi.signed_a ""',
+                'efidebug boot add -b 1 HELLO_a host 0:1 /helloworld.efi.signed_a ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert '\'HELLO_a\' failed' in ''.join(output)
@@ -48,7 +48,7 @@ class TestEfiSignedImageIntca(object):
         with u_boot_console.log.section('Test Case 1b'):
             # Test Case 1b, signed and authenticated by root CA
             output = u_boot_console.run_command_list([
-                'efidebug boot add 2 HELLO_ab host 0:1 /helloworld.efi.signed_ab ""',
+                'efidebug boot add -b 2 HELLO_ab host 0:1 /helloworld.efi.signed_ab ""',
                 'efidebug boot next 2',
                 'bootefi bootmgr'])
             assert 'Hello, world!' in ''.join(output)
@@ -70,7 +70,7 @@ class TestEfiSignedImageIntca(object):
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
+                'efidebug boot add -b 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert '\'HELLO_abc\' failed' in ''.join(output)
@@ -116,7 +116,7 @@ class TestEfiSignedImageIntca(object):
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
+                'efidebug boot add -b 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert 'Hello, world!' in ''.join(output)
index 56f56e1..8e026f7 100644 (file)
@@ -35,7 +35,7 @@ class TestEfiUnsignedImage(object):
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert '\'HELLO\' failed' in ''.join(output)
@@ -64,7 +64,7 @@ class TestEfiUnsignedImage(object):
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert 'Hello, world!' in ''.join(output)
@@ -88,7 +88,7 @@ class TestEfiUnsignedImage(object):
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert '\'HELLO\' failed' in ''.join(output)
@@ -106,7 +106,7 @@ class TestEfiUnsignedImage(object):
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert '\'HELLO\' failed' in ''.join(output)
index f889120..140dcb9 100644 (file)
@@ -45,5 +45,4 @@ def test_log_dropped(u_boot_console):
     cons = u_boot_console
     cons.restart_uboot()
     output = cons.get_spawn_output().replace('\r', '')
-    assert 'sandbox: starting...' in output
     assert (not 'debug: main' in output)
index 92d09b7..e9cce4d 100644 (file)
@@ -4,7 +4,7 @@
 import pytest
 import u_boot_utils as util
 
-@pytest.mark.boardspec('sandbox')
+@pytest.mark.boardspec('sandbox_spl')
 @pytest.mark.buildconfigspec('spl_of_platdata')
 def test_spl_devicetree(u_boot_console):
     """Test content of spl device-tree"""
diff --git a/test/py/tests/test_scp03.py b/test/py/tests/test_scp03.py
new file mode 100644 (file)
index 0000000..1f68925
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright (c) 2021 Foundries.io Ltd
+#
+# SPDX-License-Identifier:  GPL-2.0+
+#
+# SCP03 command test
+
+"""
+This tests SCP03 command in U-boot.
+
+For additional details check doc/usage/scp03.rst
+"""
+
+import pytest
+import u_boot_utils as util
+
+@pytest.mark.buildconfigspec('cmd_scp03')
+def test_scp03(u_boot_console):
+    """Enable and provision keys with SCP03
+    """
+
+    success_str1 = "SCP03 is enabled"
+    success_str2 = "SCP03 is provisioned"
+
+    response = u_boot_console.run_command('scp03 enable')
+    assert success_str1 in response
+    response = u_boot_console.run_command('scp03 provision')
+    assert success_str2 in response
index 735628e..869406c 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -30,6 +30,10 @@ fi
 run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \
                -k 'test_ofplatdata or test_handoff or test_spl'
 
+# Run the sane tests with sandbox_noinst (i.e. without OF_PLATDATA_INST)
+run_test "sandbox_spl" ./test/py/test.py --bd sandbox_noinst --build \
+               -k 'test_ofplatdata or test_handoff or test_spl'
+
 if [ -z "$tools_only" ]; then
        # Run tests for the flat-device-tree version of sandbox. This is a special
        # build which does not enable CONFIG_OF_LIVE for the live device tree, so we can
index cd50455..359d7d4 100644 (file)
@@ -107,9 +107,8 @@ STR_TEST(str_simple_strtoul, 0);
 
 int do_ut_str(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test,
-                                                str_test);
-       const int n_ents = ll_entry_count(struct unit_test, str_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(str_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(str_test);
 
        return cmd_ut_category("str", "str_", tests, n_ents, argc, argv);
 }
diff --git a/test/test-main.c b/test/test-main.c
new file mode 100644 (file)
index 0000000..46a0c2e
--- /dev/null
@@ -0,0 +1,434 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <asm/state.h>
+#include <dm/root.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* This is valid when a test is running, NULL otherwise */
+static struct unit_test_state *cur_test_state;
+
+struct unit_test_state *test_get_state(void)
+{
+       return cur_test_state;
+}
+
+void test_set_state(struct unit_test_state *uts)
+{
+       cur_test_state = uts;
+}
+
+/**
+ * dm_test_pre_run() - Get ready to run a driver model test
+ *
+ * This clears out the driver model data structures. For sandbox it resets the
+ * state structure
+ *
+ * @uts: Test state
+ */
+static int dm_test_pre_run(struct unit_test_state *uts)
+{
+       bool of_live = uts->of_live;
+
+       uts->root = NULL;
+       uts->testdev = NULL;
+       uts->force_fail_alloc = false;
+       uts->skip_post_probe = false;
+       gd->dm_root = NULL;
+       if (!CONFIG_IS_ENABLED(OF_PLATDATA))
+               memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count));
+       state_reset_for_test(state_get_current());
+
+       /* Determine whether to make the live tree available */
+       gd_set_of_root(of_live ? uts->of_root : NULL);
+       ut_assertok(dm_init(of_live));
+       uts->root = dm_root();
+
+       return 0;
+}
+
+static int dm_test_post_run(struct unit_test_state *uts)
+{
+       int id;
+
+       /*
+        * With of-platdata-inst the uclasses are created at build time. If we
+        * destroy them we cannot get them back since uclass_add() is not
+        * supported. So skip this.
+        */
+       if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+               for (id = 0; id < UCLASS_COUNT; id++) {
+                       struct uclass *uc;
+
+                       /*
+                        * If the uclass doesn't exist we don't want to create
+                        * it. So check that here before we call
+                        * uclass_find_device().
+                        */
+                       uc = uclass_find(id);
+                       if (!uc)
+                               continue;
+                       ut_assertok(uclass_destroy(uc));
+               }
+       }
+
+       return 0;
+}
+
+/* Ensure all the test devices are probed */
+static int do_autoprobe(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+       int ret;
+
+       /* Scanning the uclass is enough to probe all the devices */
+       for (ret = uclass_first_device(UCLASS_TEST, &dev);
+            dev;
+            ret = uclass_next_device(&dev))
+               ;
+
+       return ret;
+}
+
+/*
+ * ut_test_run_on_flattree() - Check if we should run a test with flat DT
+ *
+ * This skips long/slow tests where there is not much value in running a flat
+ * DT test in addition to a live DT test.
+ *
+ * @return true to run the given test on the flat device tree
+ */
+static bool ut_test_run_on_flattree(struct unit_test *test)
+{
+       const char *fname = strrchr(test->file, '/') + 1;
+
+       if (!(test->flags & UT_TESTF_DM))
+               return false;
+
+       return !strstr(fname, "video") || strstr(test->name, "video_base");
+}
+
+/**
+ * test_matches() - Check if a test should be run
+ *
+ * This checks if the a test should be run. In the normal case of running all
+ * tests, @select_name is NULL.
+ *
+ * @prefix: String prefix for the tests. Any tests that have this prefix will be
+ *     printed without the prefix, so that it is easier to see the unique part
+ *     of the test name. If NULL, any suite name (xxx_test) is considered to be
+ *     a prefix.
+ * @test_name: Name of current test
+ * @select_name: Name of test to run (or NULL for all)
+ * @return true to run this test, false to skip it
+ */
+static bool test_matches(const char *prefix, const char *test_name,
+                        const char *select_name)
+{
+       if (!select_name)
+               return true;
+
+       if (!strcmp(test_name, select_name))
+               return true;
+
+       if (!prefix) {
+               const char *p = strstr(test_name, "_test_");
+
+               /* convert xxx_test_yyy to yyy, i.e. remove the suite name */
+               if (p)
+                       test_name = p + 6;
+       } else {
+               /* All tests have this prefix */
+               if (!strncmp(test_name, prefix, strlen(prefix)))
+                       test_name += strlen(prefix);
+       }
+
+       if (!strcmp(test_name, select_name))
+               return true;
+
+       return false;
+}
+
+/**
+ * ut_list_has_dm_tests() - Check if a list of tests has driver model ones
+ *
+ * @tests: List of tests to run
+ * @count: Number of tests to ru
+ * @return true if any of the tests have the UT_TESTF_DM flag
+ */
+static bool ut_list_has_dm_tests(struct unit_test *tests, int count)
+{
+       struct unit_test *test;
+
+       for (test = tests; test < tests + count; test++) {
+               if (test->flags & UT_TESTF_DM)
+                       return true;
+       }
+
+       return false;
+}
+
+/**
+ * dm_test_restore() Put things back to normal so sandbox works as expected
+ *
+ * @of_root: Value to set for of_root
+ * @return 0 if OK, -ve on error
+ */
+static int dm_test_restore(struct device_node *of_root)
+{
+       int ret;
+
+       gd_set_of_root(of_root);
+       gd->dm_root = NULL;
+       ret = dm_init(CONFIG_IS_ENABLED(OF_LIVE));
+       if (ret)
+               return ret;
+       dm_scan_plat(false);
+       if (!CONFIG_IS_ENABLED(OF_PLATDATA))
+               dm_scan_fdt(false);
+
+       return 0;
+}
+
+/**
+ * test_pre_run() - Handle any preparation needed to run a test
+ *
+ * @uts: Test state
+ * @test: Test to prepare for
+ * @return 0 if OK, -EAGAIN to skip this test since some required feature is not
+ *     available, other -ve on error (meaning that testing cannot likely
+ *     continue)
+ */
+static int test_pre_run(struct unit_test_state *uts, struct unit_test *test)
+{
+       if (test->flags & UT_TESTF_DM)
+               ut_assertok(dm_test_pre_run(uts));
+
+       ut_set_skip_delays(uts, false);
+
+       uts->start = mallinfo();
+
+       if (test->flags & UT_TESTF_SCAN_PDATA)
+               ut_assertok(dm_scan_plat(false));
+
+       if (test->flags & UT_TESTF_PROBE_TEST)
+               ut_assertok(do_autoprobe(uts));
+
+       if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
+           (test->flags & UT_TESTF_SCAN_FDT))
+               ut_assertok(dm_extended_scan(false));
+
+       if (test->flags & UT_TESTF_CONSOLE_REC) {
+               int ret = console_record_reset_enable();
+
+               if (ret) {
+                       printf("Skipping: Console recording disabled\n");
+                       return -EAGAIN;
+               }
+       }
+       ut_silence_console(uts);
+
+       return 0;
+}
+
+/**
+ * test_post_run() - Handle cleaning up after a test
+ *
+ * @uts: Test state
+ * @test: Test to clean up after
+ * @return 0 if OK, -ve on error (meaning that testing cannot likely continue)
+ */
+static int test_post_run(struct unit_test_state *uts, struct unit_test *test)
+{
+       ut_unsilence_console(uts);
+       if (test->flags & UT_TESTF_DM)
+               ut_assertok(dm_test_post_run(uts));
+
+       return 0;
+}
+
+/**
+ * ut_run_test() - Run a single test
+ *
+ * This runs the test, handling any preparation and clean-up needed. It prints
+ * the name of each test before running it.
+ *
+ * @uts: Test state to update. The caller should ensure that this is zeroed for
+ *     the first call to this function. On exit, @uts->fail_count is
+ *     incremented by the number of failures (0, one hopes)
+ * @test_name: Test to run
+ * @name: Name of test, possibly skipping a prefix that should not be displayed
+ * @return 0 if all tests passed, -EAGAIN if the test should be skipped, -1 if
+ *     any failed
+ */
+static int ut_run_test(struct unit_test_state *uts, struct unit_test *test,
+                      const char *test_name)
+{
+       const char *fname = strrchr(test->file, '/') + 1;
+       const char *note = "";
+       int ret;
+
+       if ((test->flags & UT_TESTF_DM) && !uts->of_live)
+               note = " (flat tree)";
+       printf("Test: %s: %s%s\n", test_name, fname, note);
+
+       /* Allow access to test state from drivers */
+       test_set_state(uts);
+
+       ret = test_pre_run(uts, test);
+       if (ret == -EAGAIN)
+               return -EAGAIN;
+       if (ret)
+               return ret;
+
+       test->func(uts);
+
+       ret = test_post_run(uts, test);
+       if (ret)
+               return ret;
+
+       test_set_state( NULL);
+
+       return 0;
+}
+
+/**
+ * ut_run_test_live_flat() - Run a test with both live and flat tree
+ *
+ * This calls ut_run_test() with livetree enabled, which is the standard setup
+ * for runnig tests. Then, for driver model test, it calls it again with
+ * livetree disabled. This allows checking of flattree being used when OF_LIVE
+ * is enabled, as is the case in U-Boot proper before relocation, as well as in
+ * SPL.
+ *
+ * @uts: Test state to update. The caller should ensure that this is zeroed for
+ *     the first call to this function. On exit, @uts->fail_count is
+ *     incremented by the number of failures (0, one hopes)
+ * @test: Test to run
+ * @name: Name of test, possibly skipping a prefix that should not be displayed
+ * @return 0 if all tests passed, -EAGAIN if the test should be skipped, -1 if
+ *     any failed
+ */
+static int ut_run_test_live_flat(struct unit_test_state *uts,
+                                struct unit_test *test, const char *name)
+{
+       int runs;
+
+       /* Run with the live tree if possible */
+       runs = 0;
+       if (CONFIG_IS_ENABLED(OF_LIVE)) {
+               if (!(test->flags & UT_TESTF_FLAT_TREE)) {
+                       uts->of_live = true;
+                       ut_assertok(ut_run_test(uts, test, test->name));
+                       runs++;
+               }
+       }
+
+       /*
+        * Run with the flat tree if we couldn't run it with live tree,
+        * or it is a core test.
+        */
+       if (!(test->flags & UT_TESTF_LIVE_TREE) &&
+           (!runs || ut_test_run_on_flattree(test))) {
+               uts->of_live = false;
+               ut_assertok(ut_run_test(uts, test, test->name));
+               runs++;
+       }
+
+       return 0;
+}
+
+/**
+ * ut_run_tests() - Run a set of tests
+ *
+ * This runs the tests, handling any preparation and clean-up needed. It prints
+ * the name of each test before running it.
+ *
+ * @uts: Test state to update. The caller should ensure that this is zeroed for
+ *     the first call to this function. On exit, @uts->fail_count is
+ *     incremented by the number of failures (0, one hopes)
+ * @prefix: String prefix for the tests. Any tests that have this prefix will be
+ *     printed without the prefix, so that it is easier to see the unique part
+ *     of the test name. If NULL, no prefix processing is done
+ * @tests: List of tests to run
+ * @count: Number of tests to run
+ * @select_name: Name of a single test to run (from the list provided). If NULL
+ *     then all tests are run
+ * @return 0 if all tests passed, -ENOENT if test @select_name was not found,
+ *     -EBADF if any failed
+ */
+static int ut_run_tests(struct unit_test_state *uts, const char *prefix,
+                       struct unit_test *tests, int count,
+                       const char *select_name)
+{
+       struct unit_test *test;
+       int found = 0;
+
+       for (test = tests; test < tests + count; test++) {
+               const char *test_name = test->name;
+               int ret;
+
+               if (!test_matches(prefix, test_name, select_name))
+                       continue;
+               ret = ut_run_test_live_flat(uts, test, select_name);
+               found++;
+               if (ret == -EAGAIN)
+                       continue;
+               if (ret)
+                       return ret;
+       }
+       if (select_name && !found)
+               return -ENOENT;
+
+       return uts->fail_count ? -EBADF : 0;
+}
+
+int ut_run_list(const char *category, const char *prefix,
+               struct unit_test *tests, int count, const char *select_name)
+{
+       struct unit_test_state uts = { .fail_count = 0 };
+       bool has_dm_tests = false;
+       int ret;
+
+       if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
+           ut_list_has_dm_tests(tests, count)) {
+               has_dm_tests = true;
+               /*
+                * If we have no device tree, or it only has a root node, then
+                * these * tests clearly aren't going to work...
+                */
+               if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) {
+                       puts("Please run with test device tree:\n"
+                            "    ./u-boot -d arch/sandbox/dts/test.dtb\n");
+                       return CMD_RET_FAILURE;
+               }
+       }
+
+       if (!select_name)
+               printf("Running %d %s tests\n", count, category);
+
+       uts.of_root = gd_of_root();
+       ret = ut_run_tests(&uts, prefix, tests, count, select_name);
+
+       if (ret == -ENOENT)
+               printf("Test '%s' not found\n", select_name);
+       else
+               printf("Failures: %d\n", uts.fail_count);
+
+       /* Best efforts only...ignore errors */
+       if (has_dm_tests)
+               dm_test_restore(uts.of_root);
+
+       return ret;
+}
index 6f6aea5..617eed8 100644 (file)
@@ -729,8 +729,8 @@ UNICODE_TEST(unicode_test_efi_create_indexed_name);
 
 int do_ut_unicode(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-       struct unit_test *tests = ll_entry_start(struct unit_test, unicode_test);
-       const int n_ents = ll_entry_count(struct unit_test, unicode_test);
+       struct unit_test *tests = UNIT_TEST_SUITE_START(unicode_test);
+       const int n_ents = UNIT_TEST_SUITE_COUNT(unicode_test);
 
        return cmd_ut_category("Unicode", "unicode_test_",
                               tests, n_ents, argc, argv);
index 7328338..ea0af15 100644 (file)
--- a/test/ut.c
+++ b/test/ut.c
@@ -133,3 +133,10 @@ void ut_unsilence_console(struct unit_test_state *uts)
 {
        gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
 }
+
+void ut_set_skip_delays(struct unit_test_state *uts, bool skip_delays)
+{
+#ifdef CONFIG_SANDBOX
+       state_set_skip_delays(skip_delays);
+#endif
+}
diff --git a/tools/binman/README.rst b/tools/binman/README.rst
new file mode 120000 (symlink)
index 0000000..b734f54
--- /dev/null
@@ -0,0 +1 @@
+binman.rst
\ No newline at end of file
similarity index 63%
rename from tools/binman/README
rename to tools/binman/binman.rst
index a00c902..1aa2459 100644 (file)
@@ -1,47 +1,51 @@
-# SPDX-License-Identifier: GPL-2.0+
-# Copyright (c) 2016 Google, Inc
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (c) 2016 Google, Inc
 
 Introduction
-------------
+============
 
 Firmware often consists of several components which must be packaged together.
 For example, we may have SPL, U-Boot, a device tree and an environment area
 grouped together and placed in MMC flash. When the system starts, it must be
 able to find these pieces.
 
-So far U-Boot has not provided a way to handle creating such images in a
-general way. Each SoC does what it needs to build an image, often packing or
-concatenating images in the U-Boot build system.
-
-Binman aims to provide a mechanism for building images, from simple
-SPL + U-Boot combinations, to more complex arrangements with many parts.
+Building firmware should be separate from packaging it. Many of the complexities
+of modern firmware build systems come from trying to do both at once. With
+binman, you build all the pieces that are needed, using whatever assortment of
+projects and build systems are needed, then use binman to stitch everything
+together.
 
 
 What it does
 ------------
 
 Binman reads your board's device tree and finds a node which describes the
-required image layout. It uses this to work out what to place where. The
-output file normally contains the device tree, so it is in principle possible
-to read an image and extract its constituent parts.
+required image layout. It uses this to work out what to place where.
+
+Binman provides a mechanism for building images, from simple SPL + U-Boot
+combinations, to more complex arrangements with many parts. It also allows
+users to inspect images, extract and replace binaries within them, repacking if
+needed.
 
 
 Features
 --------
 
-So far binman is pretty simple. It supports binary blobs, such as 'u-boot',
-'spl' and 'fdt'. It supports empty entries (such as setting to 0xff). It can
-place entries at a fixed location in the image, or fit them together with
-suitable padding and alignment. It provides a way to process binaries before
-they are included, by adding a Python plug-in. The device tree is available
-to U-Boot at run-time so that the images can be interpreted.
+Apart from basic padding, alignment and positioning features, Binman supports
+hierarchical images, compression, hashing and dealing with the binary blobs
+which are a sad trend in open-source firmware at present.
 
-Binman can update the device tree with the final location of everything when it
-is done. Entry positions can be provided to U-Boot SPL as run-time symbols,
-avoiding device-tree code overhead.
+Executable binaries can access the location of other binaries in an image by
+using special linker symbols (zero-overhead but somewhat limited) or by reading
+the devicetree description of the image.
 
-Binman can also support incorporating filesystems in the image if required.
-For example x86 platforms may use CBFS in some cases.
+Binman is designed primarily for use with U-Boot and associated binaries such
+as ARM Trusted Firmware, but it is suitable for use with other projects, such
+as Zephyr. Binman also provides facilities useful in Chromium OS, such as CBFS,
+vblocks and and the like.
+
+Binman provides a way to process binaries before they are included, by adding a
+Python plug-in.
 
 Binman is intended for use with U-Boot but is designed to be general enough
 to be useful in other image-packaging situations.
@@ -50,11 +54,11 @@ to be useful in other image-packaging situations.
 Motivation
 ----------
 
-Packaging of firmware is quite a different task from building the various
-parts. In many cases the various binaries which go into the image come from
-separate build systems. For example, ARM Trusted Firmware is used on ARMv8
-devices but is not built in the U-Boot tree. If a Linux kernel is included
-in the firmware image, it is built elsewhere.
+As mentioned above, packaging of firmware is quite a different task from
+building the various parts. In many cases the various binaries which go into
+the image come from separate build systems. For example, ARM Trusted Firmware
+is used on ARMv8 devices but is not built in the U-Boot tree. If a Linux kernel
+is included in the firmware image, it is built elsewhere.
 
 It is of course possible to add more and more build rules to the U-Boot
 build system to cover these cases. It can shell out to other Makefiles and
@@ -67,18 +71,19 @@ standard format, we can support making valid images for any board without
 manual effort, lots of READMEs, etc.
 
 Benefits:
-- Each binary can have its own build system and tool chain without creating
-any dependencies between them
-- Avoids the need for a single-shot build: individual parts can be updated
-and brought in as needed
-- Provides for a standard image description available in the build and at
-run-time
-- SoC-specific image-signing tools can be accommodated
-- Avoids cluttering the U-Boot build system with image-building code
-- The image description is automatically available at run-time in U-Boot,
-SPL. It can be made available to other software also
-- The image description is easily readable (it's a text file in device-tree
-format) and permits flexible packing of binaries
+
+  - Each binary can have its own build system and tool chain without creating
+    any dependencies between them
+  - Avoids the need for a single-shot build: individual parts can be updated
+    and brought in as needed
+  - Provides for a standard image description available in the build and at
+    run-time
+  - SoC-specific image-signing tools can be accommodated
+  - Avoids cluttering the U-Boot build system with image-building code
+  - The image description is automatically available at run-time in U-Boot,
+    SPL. It can be made available to other software also
+  - The image description is easily readable (it's a text file in device-tree
+    format) and permits flexible packing of binaries
 
 
 Terminology
@@ -136,6 +141,9 @@ the boundaries between building input files (mkimage) and packaging then
 into a final image (binman).
 
 
+Using binman
+============
+
 Example use of binman in U-Boot
 -------------------------------
 
@@ -144,14 +152,14 @@ build system.
 
 Consider sunxi. It has the following steps:
 
-1. It uses a custom mksunxiboot tool to build an SPL image called
-sunxi-spl.bin. This should probably move into mkimage.
+  #. It uses a custom mksunxiboot tool to build an SPL image called
+     sunxi-spl.bin. This should probably move into mkimage.
 
-2. It uses mkimage to package U-Boot into a legacy image file (so that it can
-hold the load and execution address) called u-boot.img.
+  #. It uses mkimage to package U-Boot into a legacy image file (so that it can
+     hold the load and execution address) called u-boot.img.
 
-3. It builds a final output image called u-boot-sunxi-with-spl.bin which
-consists of sunxi-spl.bin, some padding and u-boot.img.
+  #. It builds a final output image called u-boot-sunxi-with-spl.bin which
+     consists of sunxi-spl.bin, some padding and u-boot.img.
 
 Binman is intended to replace the last step. The U-Boot build system builds
 u-boot.bin and sunxi-spl.bin. Binman can then take over creation of
@@ -180,22 +188,22 @@ the configuration of the Intel-format descriptor.
 Running binman
 --------------
 
-First install prerequisites, e.g.
+First install prerequisites, e.g::
 
-       sudo apt-get install python-pyelftools python3-pyelftools lzma-alone \
-               liblz4-tool
+    sudo apt-get install python-pyelftools python3-pyelftools lzma-alone \
+        liblz4-tool
 
-Type:
+Type::
 
-       binman build -b <board_name>
+    binman build -b <board_name>
 
 to build an image for a board. The board name is the same name used when
 configuring U-Boot (e.g. for sandbox_defconfig the board name is 'sandbox').
 Binman assumes that the input files for the build are in ../b/<board_name>.
 
-Or you can specify this explicitly:
+Or you can specify this explicitly::
 
-       binman build -I <build_path>
+    binman build -I <build_path>
 
 where <build_path> is the build directory containing the output of the U-Boot
 build.
@@ -211,17 +219,12 @@ Binman has a few other options which you can see by running 'binman -h'.
 Enabling binman for a board
 ---------------------------
 
-At present binman is invoked from a rule in the main Makefile. Typically you
-will have a rule like:
+At present binman is invoked from a rule in the main Makefile. You should be
+able to enable CONFIG_BINMAN to enable this rule.
 
-ifneq ($(CONFIG_ARCH_<something>),)
-u-boot-<your_suffix>.bin: <input_file_1> <input_file_2> checkbinman FORCE
-       $(call if_changed,binman)
-endif
-
-This assumes that u-boot-<your_suffix>.bin is a target, and is the final file
-that you need to produce. You can make it a target by adding it to INPUTS-y
-either in the main Makefile or in a config.mk file in your arch subdirectory.
+The output file is typically named image.bin and is located in the output
+directory. If input files are needed to you add these to INPUTS-y either in the
+main Makefile or in a config.mk file in your arch subdirectory.
 
 Once binman is executed it will pick up its instructions from a device-tree
 file, typically <soc>-u-boot.dtsi, where <soc> is your CONFIG_SYS_SOC value.
@@ -229,22 +232,125 @@ You can use other, more specific CONFIG options - see 'Automatic .dtsi
 inclusion' below.
 
 
+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
+is useful to be able to find the location of U-Boot so that it can be executed
+when SPL is finished.
+
+Binman allows you to declare symbols in the SPL image which are filled in
+with their correct values during the build. For example::
+
+    binman_sym_declare(ulong, u_boot_any, image_pos);
+
+declares a ulong value which will be assigned to the image-pos 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_offset = binman_sym(ulong, u_boot_any, image_pos);
+
+Thus u_boot_offset will be set to the image-pos of U-Boot in memory, assuming
+that the whole image has been loaded, or is available in flash. You can then
+jump to that address to start U-Boot.
+
+At present this feature is only supported in SPL and TPL. In principle it is
+possible to fill in such symbols in U-Boot proper, as well, but a future C
+library is planned for this instead, to read from the device tree.
+
+As well as image-pos, it is possible to read the size of an entry and its
+offset (which is the start position of the entry within its parent).
+
+A small technical note: Binman automatically adds the base address of the image
+(i.e. __image_copy_start) to the value of the image-pos symbol, so that when the
+image is loaded to its linked address, the value will be correct and actually
+point into the image.
+
+For example, say SPL is at the start of the image and linked to start at address
+80108000. If U-Boot's image-pos is 0x8000 then binman will write an image-pos
+for U-Boot of 80110000 into the SPL binary, since it assumes the image is loaded
+to 80108000, with SPL at 80108000 and U-Boot at 80110000.
+
+For x86 devices (with the end-at-4gb property) this base address is not added
+since it is assumed that images are XIP and the offsets already include the
+address.
+
+
+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.
+
+Alternatively, an FDT map entry can be used to add a special FDT containing
+just the information about the image. This is preceded by a magic string so can
+be located anywhere in the image. An image header (typically at the start or end
+of the image) can be used to point to the FDT map. See fdtmap and image-header
+entries for more information.
+
+
+Map files
+---------
+
+The -m option causes binman to output a .map file for each image that it
+generates. This shows the offset and size of each entry. For example::
+
+      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
+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.
+
+
 Image description format
-------------------------
+========================
 
 The binman node is called 'binman'. An example image description is shown
-below:
-
-       binman {
-               filename = "u-boot-sunxi-with-spl.bin";
-               pad-byte = <0xff>;
-               blob {
-                       filename = "spl/sunxi-spl.bin";
-               };
-               u-boot {
-                       offset = <CONFIG_SPL_PAD_TO>;
-               };
-       };
+below::
+
+    binman {
+        filename = "u-boot-sunxi-with-spl.bin";
+        pad-byte = <0xff>;
+        blob {
+            filename = "spl/sunxi-spl.bin";
+        };
+        u-boot {
+            offset = <CONFIG_SPL_PAD_TO>;
+        };
+    };
 
 
 This requests binman to create an image file called u-boot-sunxi-with-spl.bin
@@ -270,184 +376,198 @@ use any unique name, with the 'type' property providing the type.
 The attributes supported for entries are described below.
 
 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.
+    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 offset is adjusted
-       so that the entry starts on an aligned boundary within the containing
-       section or image. For example 'align = <16>' means that the entry will
-       start on a 16-byte boundary. This may mean that padding is added before
-       the entry. The padding is part of the containing section but is not
-       included in the entry, meaning that an empty space may be created before
-       the entry starts. Alignment should be a power of 2. If 'align' is not
-       provided, no alignment is performed.
+    This sets the alignment of the entry. The entry offset is adjusted
+    so that the entry starts on an aligned boundary within the containing
+    section or image. For example 'align = <16>' means that the entry will
+    start on a 16-byte boundary. This may mean that padding is added before
+    the entry. The padding is part of the containing section but is not
+    included in the entry, meaning that an empty space may be created before
+    the entry starts. Alignment should be a power of 2. If 'align' is not
+    provided, no alignment is performed.
 
 size:
-       This sets the size of the entry. The contents will be padded out to
-       this size. If this is not provided, it will be set to the size of the
-       contents.
+    This sets the size of the entry. The contents will be padded out to
+    this size. If this is not provided, it will be set to the size of the
+    contents.
 
 pad-before:
-       Padding before the contents of the entry. Normally this is 0, meaning
-       that the contents start at the beginning of the entry. This can be used
-       to offset the entry contents a little. While this does not affect the
-       contents of the entry within binman itself (the padding is performed
-       only when its parent section is assembled), the end result will be that
-       the entry starts with the padding bytes, so may grow. Defaults to 0.
+    Padding before the contents of the entry. Normally this is 0, meaning
+    that the contents start at the beginning of the entry. This can be used
+    to offset the entry contents a little. While this does not affect the
+    contents of the entry within binman itself (the padding is performed
+    only when its parent section is assembled), the end result will be that
+    the entry starts with the padding bytes, so may grow. Defaults to 0.
 
 pad-after:
-       Padding after the contents of the entry. Normally this is 0, meaning
-       that the entry ends at the last byte of content (unless adjusted by
-       other properties). This allows room to be created in the image for
-       this entry to expand later. While this does not affect the contents of
-       the entry within binman itself (the padding is performed only when its
-       parent section is assembled), the end result will be that the entry ends
-       with the padding bytes, so may grow. Defaults to 0.
+    Padding after the contents of the entry. Normally this is 0, meaning
+    that the entry ends at the last byte of content (unless adjusted by
+    other properties). This allows room to be created in the image for
+    this entry to expand later. While this does not affect the contents of
+    the entry within binman itself (the padding is performed only when its
+    parent section is assembled), the end result will be that the entry ends
+    with the padding bytes, so may grow. Defaults to 0.
 
 align-size:
-       This sets the alignment of the entry size. For example, to ensure
-       that the size of an entry is a multiple of 64 bytes, set this to 64.
-       While this does not affect the contents of the entry within binman
-       itself (the padding is performed only when its parent section is
-       assembled), the end result is that the entry ends with the padding
-       bytes, so may grow. If 'align-size' is not provided, no alignment is
-       performed.
+    This sets the alignment of the entry size. For example, to ensure
+    that the size of an entry is a multiple of 64 bytes, set this to 64.
+    While this does not affect the contents of the entry within binman
+    itself (the padding is performed only when its parent section is
+    assembled), the end result is that the entry ends with the padding
+    bytes, so may grow. If 'align-size' is not provided, no alignment is
+    performed.
 
 align-end:
-       This sets the alignment of the end of an entry with respect to the
-       containing section. Some entries require that they end on an alignment
-       boundary, regardless of where they start. This does not move the start
-       of the entry, so the contents of the entry will still start at the
-       beginning. But there may be padding at the end. While this does not
-       affect the contents of the entry within binman itself (the padding is
-       performed only when its parent section is assembled), the end result
-       is that the entry ends with the padding bytes, so may grow.
-       If 'align-end' is not provided, no alignment is performed.
+    This sets the alignment of the end of an entry with respect to the
+    containing section. Some entries require that they end on an alignment
+    boundary, regardless of where they start. This does not move the start
+    of the entry, so the contents of the entry will still start at the
+    beginning. But there may be padding at the end. While this does not
+    affect the contents of the entry within binman itself (the padding is
+    performed only when its parent section is assembled), the end result
+    is that the entry ends with the padding bytes, so may grow.
+    If 'align-end' is not provided, no alignment is performed.
 
 filename:
-       For 'blob' types this provides the filename containing the binary to
-       put into the entry. If binman knows about the entry type (like
-       u-boot-bin), then there is no need to specify this.
+    For 'blob' types this provides the filename containing the binary to
+    put into the entry. If binman knows about the entry type (like
+    u-boot-bin), then there is no need to specify this.
 
 type:
-       Sets the type of an entry. This defaults to the entry name, but it is
-       possible to use any name, and then add (for example) 'type = "u-boot"'
-       to specify the type.
+    Sets the type of an entry. This defaults to the entry name, but it is
+    possible to use any name, and then add (for example) 'type = "u-boot"'
+    to specify the type.
 
 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 offset (with the GetOffsets() method).
+    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 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.
+    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.
 
 expand-size:
-       Expand the size of this entry to fit available space. This space is only
-       limited by the size of the image/section and the position of the next
-       entry.
+    Expand the size of this entry to fit available space. This space is only
+    limited by the size of the image/section and the position of the next
+    entry.
 
 compress:
-       Sets the compression algortihm to use (for blobs only). See the entry
-       documentation for details.
+    Sets the compression algortihm to use (for blobs only). See the entry
+    documentation for details.
 
 missing-msg:
-       Sets the tag of the message to show if this entry is missing. This is
-       used for external blobs. When they are missing it is helpful to show
-       information about what needs to be fixed. See missing-blob-help for the
-       message for each tag.
+    Sets the tag of the message to show if this entry is missing. This is
+    used for external blobs. When they are missing it is helpful to show
+    information about what needs to be fixed. See missing-blob-help for the
+    message for each tag.
+
+no-expanded:
+    By default binman substitutes entries with expanded versions if available,
+    so that a `u-boot` entry type turns into `u-boot-expanded`, for example. The
+    `--no-expanded` command-line option disables this globally. The
+    `no-expanded` property disables this just for a single entry. Put the
+    `no-expanded` boolean property in the node to select this behaviour.
 
 The attributes supported for images and sections are described below. Several
 are similar to those for entries.
 
 size:
-       Sets the image size in bytes, for example 'size = <0x100000>' for a
-       1MB image.
+    Sets the image size in bytes, for example 'size = <0x100000>' for a
+    1MB image.
 
 offset:
-       This is similar to 'offset' in entries, setting the offset of a section
-       within the image or section containing it. The first byte of the section
-       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.
+    This is similar to 'offset' in entries, setting the offset of a section
+    within the image or section containing it. The first byte of the section
+    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-size:
-       This sets the alignment of the image size. For example, to ensure
-       that the image ends on a 512-byte boundary, use 'align-size = <512>'.
-       If 'align-size' is not provided, no alignment is performed.
+    This sets the alignment of the image size. For example, to ensure
+    that the image ends on a 512-byte boundary, use 'align-size = <512>'.
+    If 'align-size' is not provided, no alignment is performed.
 
 pad-before:
-       This sets the padding before the image entries. The first entry will
-       be positioned after the padding. This defaults to 0.
+    This sets the padding before the image entries. The first entry will
+    be positioned after the padding. This defaults to 0.
 
 pad-after:
-       This sets the padding after the image entries. The padding will be
-       placed after the last entry. This defaults to 0.
+    This sets the padding after the image entries. The padding will be
+    placed after the last entry. This defaults to 0.
 
 pad-byte:
-       This specifies the pad byte to use when padding in the image. It
-       defaults to 0. To use 0xff, you would add 'pad-byte = <0xff>'.
+    This specifies the pad byte to use when padding in the image. It
+    defaults to 0. To use 0xff, you would add 'pad-byte = <0xff>'.
 
 filename:
-       This specifies the image filename. It defaults to 'image.bin'.
+    This specifies the image filename. It defaults to 'image.bin'.
 
 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 'offset' properties are set by CONFIG options, so their ordering is
-       not known a priori.
+    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 '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-offset;' to your description.
+    This is a boolean property so needs no value. To enable it, add a
+    line 'sort-by-offset;' to your description.
 
 multiple-images:
-       Normally only a single image is generated. To create more than one
-       image, put this property in the binman node. For example, this will
-       create image1.bin containing u-boot.bin, and image2.bin containing
-       both spl/u-boot-spl.bin and u-boot.bin:
-
-       binman {
-               multiple-images;
-               image1 {
-                       u-boot {
-                       };
-               };
-
-               image2 {
-                       spl {
-                       };
-                       u-boot {
-                       };
-               };
-       };
+    Normally only a single image is generated. To create more than one
+    image, put this property in the binman node. For example, this will
+    create image1.bin containing u-boot.bin, and image2.bin containing
+    both spl/u-boot-spl.bin and u-boot.bin::
+
+        binman {
+            multiple-images;
+            image1 {
+                u-boot {
+                };
+            };
+
+            image2 {
+                spl {
+                };
+                u-boot {
+                };
+            };
+        };
 
 end-at-4gb:
-       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 offset of the first entry would be 0xfff80000 with
-       this option, instead of 0 without this option.
+    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 offset of the first entry would be 0xfff80000 with
+    this option, instead of 0 without this option.
 
 skip-at-start:
-       This property specifies the entry offset of the first entry.
+    This property specifies the entry offset of the first entry.
+
+    For PowerPC mpc85xx based CPU, CONFIG_SYS_TEXT_BASE is the entry
+    offset of the first entry. It can be 0xeff40000 or 0xfff40000 for
+    nor flash boot, 0x201000 for sd boot etc.
 
-       For PowerPC mpc85xx based CPU, CONFIG_SYS_TEXT_BASE is the entry
-       offset of the first entry. It can be 0xeff40000 or 0xfff40000 for
-       nor flash boot, 0x201000 for sd boot etc.
+    'end-at-4gb' property is not applicable where CONFIG_SYS_TEXT_BASE +
+    Image size != 4gb.
 
-       'end-at-4gb' property is not applicable where CONFIG_SYS_TEXT_BASE +
-       Image size != 4gb.
+align-default:
+    Specifies the default alignment for entries in this section, if they do
+    not specify an alignment. Note that this only applies to top-level entries
+    in the section (direct subentries), not any subentries of those entries.
+    This means that each section must specify its own default alignment, if
+    required.
 
 Examples of the above options can be found in the tests. See the
 tools/binman/test directory.
@@ -470,23 +590,23 @@ This feature provides a way of creating hierarchical images. For example here
 is an example image with two copies of U-Boot. One is read-only (ro), intended
 to be written only in the factory. Another is read-write (rw), so that it can be
 upgraded in the field. The sizes are fixed so that the ro/rw boundary is known
-and can be programmed:
-
-       binman {
-               section@0 {
-                       read-only;
-                       name-prefix = "ro-";
-                       size = <0x100000>;
-                       u-boot {
-                       };
-               };
-               section@1 {
-                       name-prefix = "rw-";
-                       size = <0x100000>;
-                       u-boot {
-                       };
-               };
-       };
+and can be programmed::
+
+    binman {
+        section@0 {
+            read-only;
+            name-prefix = "ro-";
+            size = <0x100000>;
+            u-boot {
+            };
+        };
+        section@1 {
+            name-prefix = "rw-";
+            size = <0x100000>;
+            u-boot {
+            };
+        };
+    };
 
 This image could be placed into a SPI flash chip, with the protection boundary
 set at 1MB.
@@ -494,14 +614,14 @@ set at 1MB.
 A few special properties are provided for sections:
 
 read-only:
-       Indicates that this section is read-only. This has no impact on binman's
-       operation, but his property can be read at run time.
+    Indicates that this section is read-only. This has no impact on binman's
+    operation, but his property can be read at run time.
 
 name-prefix:
-       This string is prepended to all the names of the binaries in the
-       section. In the example above, the 'u-boot' binaries which actually be
-       renamed to 'ro-u-boot' and 'rw-u-boot'. This can be useful to
-       distinguish binaries with otherwise identical names.
+    This string is prepended to all the names of the binaries in the
+    section. In the example above, the 'u-boot' binaries which actually be
+    renamed to 'ro-u-boot' and 'rw-u-boot'. This can be useful to
+    distinguish binaries with otherwise identical names.
 
 
 Image Properties
@@ -510,37 +630,196 @@ Image Properties
 Image nodes act like sections but also have a few extra properties:
 
 filename:
-       Output filename for the image. This defaults to image.bin (or in the
-       case of multiple images <nodename>.bin where <nodename> is the name of
-       the image node.
+    Output filename for the image. This defaults to image.bin (or in the
+    case of multiple images <nodename>.bin where <nodename> is the name of
+    the image node.
 
 allow-repack:
-       Create an image that can be repacked. With this option it is possible
-       to change anything in the image after it is created, including updating
-       the position and size of image components. By default this is not
-       permitted since it is not possibly to know whether this might violate a
-       constraint in the image description. For example, if a section has to
-       increase in size to hold a larger binary, that might cause the section
-       to fall out of its allow region (e.g. read-only portion of flash).
+    Create an image that can be repacked. With this option it is possible
+    to change anything in the image after it is created, including updating
+    the position and size of image components. By default this is not
+    permitted since it is not possibly to know whether this might violate a
+    constraint in the image description. For example, if a section has to
+    increase in size to hold a larger binary, that might cause the section
+    to fall out of its allow region (e.g. read-only portion of flash).
+
+    Adding this property causes the original offset and size values in the
+    image description to be stored in the FDT and fdtmap.
+
+
+Hashing Entries
+---------------
+
+It is possible to ask binman to hash the contents of an entry and write that
+value back to the device-tree node. For example::
+
+    binman {
+        u-boot {
+            hash {
+                algo = "sha256";
+            };
+        };
+    };
+
+Here, a new 'value' property will be written to the 'hash' node containing
+the hash of the 'u-boot' entry. Only SHA256 is supported at present. Whole
+sections can be hased if desired, by adding the 'hash' node to the section.
+
+The has value can be chcked at runtime by hashing the data actually read and
+comparing this has to the value in the device tree.
+
+
+Expanded entries
+----------------
+
+Binman automatically replaces 'u-boot' with an expanded version of that, i.e.
+'u-boot-expanded'. This means that when you write::
+
+    u-boot {
+    };
+
+you actually get::
+
+    u-boot {
+        type = "u-boot-expanded';
+    };
+
+which in turn expands to::
+
+    u-boot {
+        type = "section";
+
+        u-boot-nodtb {
+        };
+
+        u-boot-dtb {
+        };
+    };
+
+U-Boot's various phase binaries actually comprise two or three pieces.
+For example, u-boot.bin has the executable followed by a devicetree.
+
+With binman we want to be able to update that devicetree with full image
+information so that it is accessible to the executable. This is tricky
+if it is not clear where the devicetree starts.
+
+The above feature ensures that the devicetree is clearly separated from the
+U-Boot executable and can be updated separately by binman as needed. It can be
+disabled with the --no-expanded flag if required.
+
+The same applies for u-boot-spl and u-boot-spl. In those cases, the expansion
+includes the BSS padding, so for example::
+
+    spl {
+        type = "u-boot-spl"
+    };
+
+you actually get::
+
+    spl {
+        type = "u-boot-expanded';
+    };
+
+which in turn expands to::
+
+    spl {
+        type = "section";
+
+        u-boot-spl-nodtb {
+        };
+
+        u-boot-spl-bss-pad {
+        };
+
+        u-boot-spl-dtb {
+        };
+    };
+
+Of course we should not expand SPL if it has no devicetree. Also if the BSS
+padding is not needed (because BSS is in RAM as with CONFIG_SPL_SEPARATE_BSS),
+the 'u-boot-spl-bss-pad' subnode should not be created. The use of the expaned
+entry type is controlled by the UseExpanded() method. In the SPL case it checks
+the 'spl-dtb' entry arg, which is 'y' or '1' if SPL has a devicetree.
+
+For the BSS case, a 'spl-bss-pad' entry arg controls whether it is present. All
+entry args are provided by the U-Boot Makefile.
+
+
+Compression
+-----------
+
+Binman support compression for 'blob' entries (those of type 'blob' and
+derivatives). To enable this for an entry, add a 'compress' property::
+
+    blob {
+        filename = "datafile";
+        compress = "lz4";
+    };
+
+The entry will then contain the compressed data, using the 'lz4' compression
+algorithm. Currently this is the only one that is supported. The uncompressed
+size is written to the node in an 'uncomp-size' property, if -u is used.
+
+Compression is also supported for sections. In that case the entire section is
+compressed in one block, including all its contents. This means that accessing
+an entry from the section required decompressing the entire section. Also, the
+size of a section indicates the space that it consumes in its parent section
+(and typically the image). With compression, the section may contain more data,
+and the uncomp-size property indicates that, as above. The contents of the
+section is compressed first, before any padding is added. This ensures that the
+padding itself is not compressed, which would be a waste of time.
+
+
+Automatic .dtsi inclusion
+-------------------------
+
+It is sometimes inconvenient to add a 'binman' node to the .dts file for each
+board. This can be done by using #include to bring in a common file. Another
+approach supported by the U-Boot build system is to automatically include
+a common header. You can then put the binman node (and anything else that is
+specific to U-Boot, such as u-boot,dm-pre-reloc properies) in that header
+file.
+
+Binman will search for the following files in arch/<arch>/dts::
+
+   <dts>-u-boot.dtsi where <dts> is the base name of the .dts file
+   <CONFIG_SYS_SOC>-u-boot.dtsi
+   <CONFIG_SYS_CPU>-u-boot.dtsi
+   <CONFIG_SYS_VENDOR>-u-boot.dtsi
+   u-boot.dtsi
 
-       Adding this property causes the original offset and size values in the
-       image description to be stored in the FDT and fdtmap.
+U-Boot will only use the first one that it finds. If you need to include a
+more general file you can do that from the more specific file using #include.
+If you are having trouble figuring out what is going on, you can uncomment
+the 'warning' line in scripts/Makefile.lib to see what it has found::
+
+   # Uncomment for debugging
+   # This shows all the files that were considered and the one that we chose.
+   # u_boot_dtsi_options_debug = $(u_boot_dtsi_options_raw)
 
 
 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:
+see entries.rst which is generated from the source code using:
+
+    binman entry-docs >tools/binman/entries.rst
 
-       binman entry-docs >tools/binman/README.entries
+.. toctree::
+   :maxdepth: 2
 
+   entries
+
+
+Managing images
+===============
 
 Listing images
 --------------
 
 It is possible to list the entries in an existing firmware image created by
-binman, provided that there is an 'fdtmap' entry in the image. For example:
+binman, provided that there is an 'fdtmap' entry in the image. For example::
 
     $ binman ls -i image.bin
     Name              Image-pos  Size  Entry-type    Offset  Uncomp-size
@@ -559,7 +838,7 @@ This shows the hierarchy of the image, the position, size and type of each
 entry, the offset of each entry within its parent and the uncompressed size if
 the entry is compressed.
 
-It is also possible to list just some files in an image, e.g.
+It is also possible to list just some files in an image, e.g.::
 
     $ binman ls -i image.bin section/cbfs
     Name              Image-pos  Size  Entry-type  Offset  Uncomp-size
@@ -568,7 +847,7 @@ It is also possible to list just some files in an image, e.g.
           u-boot            138     4  u-boot          38
           u-boot-dtb        180   108  u-boot-dtb      80          3b5
 
-or with wildcards:
+or with wildcards::
 
     $ binman ls -i image.bin "*cb*" "*head*"
     Name              Image-pos  Size  Entry-type    Offset  Uncomp-size
@@ -583,22 +862,22 @@ Extracting files from images
 ----------------------------
 
 You can extract files from an existing firmware image created by binman,
-provided that there is an 'fdtmap' entry in the image. For example:
+provided that there is an 'fdtmap' entry in the image. For example::
 
     $ binman extract -i image.bin section/cbfs/u-boot
 
 which will write the uncompressed contents of that entry to the file 'u-boot' in
 the current directory. You can also extract to a particular file, in this case
-u-boot.bin:
+u-boot.bin::
 
     $ binman extract -i image.bin section/cbfs/u-boot -f u-boot.bin
 
 It is possible to extract all files into a destination directory, which will
-put files in subdirectories matching the entry hierarchy:
+put files in subdirectories matching the entry hierarchy::
 
     $ binman extract -i image.bin -O outdir
 
-or just a selection:
+or just a selection::
 
     $ binman extract -i image.bin "*u-boot*" -O outdir
 
@@ -616,18 +895,18 @@ to the that entry, compressing if necessary. If the entry size changes, you must
 add the 'allow-repack' property to the original image before generating it (see
 above), otherwise you will get an error.
 
-You can also use a particular file, in this case u-boot.bin:
+You can also use a particular file, in this case u-boot.bin::
 
     $ binman replace -i image.bin section/cbfs/u-boot -f u-boot.bin
 
 It is possible to replace all files from a source directory which uses the same
-hierarchy as the entries:
+hierarchy as the entries::
 
     $ binman replace -i image.bin -I indir
 
 Files that are missing will generate a warning.
 
-You can also replace just a selection of entries:
+You can also replace just a selection of entries::
 
     $ binman replace -i image.bin "*u-boot*" -I indir
 
@@ -637,7 +916,8 @@ Logging
 
 Binman normally operates silently unless there is an error, in which case it
 just displays the error. The -D/--debug option can be used to create a full
-backtrace when errors occur.
+backtrace when errors occur. You can use BINMAN_DEBUG=1 when building to select
+this.
 
 Internally binman logs some output while it is running. This can be displayed
 by increasing the -v/--verbosity from the default of 1:
@@ -649,28 +929,11 @@ by increasing the -v/--verbosity from the default of 1:
    4: detailed information about each operation
    5: debug (all output)
 
+You can use BINMAN_VERBOSE=5 (for example) when building to select this.
 
-Hashing Entries
----------------
-
-It is possible to ask binman to hash the contents of an entry and write that
-value back to the device-tree node. For example:
-
-       binman {
-               u-boot {
-                       hash {
-                               algo = "sha256";
-                       };
-               };
-       };
-
-Here, a new 'value' property will be written to the 'hash' node containing
-the hash of the 'u-boot' entry. Only SHA256 is supported at present. Whole
-sections can be hased if desired, by adding the 'hash' node to the section.
-
-The has value can be chcked at runtime by hashing the data actually read and
-comparing this has to the value in the device tree.
 
+Technical details
+=================
 
 Order of image creation
 -----------------------
@@ -747,162 +1010,6 @@ what happens in this stage.
 final step.
 
 
-Automatic .dtsi inclusion
--------------------------
-
-It is sometimes inconvenient to add a 'binman' node to the .dts file for each
-board. This can be done by using #include to bring in a common file. Another
-approach supported by the U-Boot build system is to automatically include
-a common header. You can then put the binman node (and anything else that is
-specific to U-Boot, such as u-boot,dm-pre-reloc properies) in that header
-file.
-
-Binman will search for the following files in arch/<arch>/dts:
-
-   <dts>-u-boot.dtsi where <dts> is the base name of the .dts file
-   <CONFIG_SYS_SOC>-u-boot.dtsi
-   <CONFIG_SYS_CPU>-u-boot.dtsi
-   <CONFIG_SYS_VENDOR>-u-boot.dtsi
-   u-boot.dtsi
-
-U-Boot will only use the first one that it finds. If you need to include a
-more general file you can do that from the more specific file using #include.
-If you are having trouble figuring out what is going on, you can uncomment
-the 'warning' line in scripts/Makefile.lib to see what it has found:
-
-   # Uncomment for debugging
-   # This shows all the files that were considered and the one that we chose.
-   # u_boot_dtsi_options_debug = $(u_boot_dtsi_options_raw)
-
-
-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
-is useful to be able to find the location of U-Boot so that it can be executed
-when SPL is finished.
-
-Binman allows you to declare symbols in the SPL image which are filled in
-with their correct values during the build. For example:
-
-    binman_sym_declare(ulong, u_boot_any, image_pos);
-
-declares a ulong value which will be assigned to the image-pos 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_offset = binman_sym(ulong, u_boot_any, image_pos);
-
-Thus u_boot_offset will be set to the image-pos of U-Boot in memory, assuming
-that the whole image has been loaded, or is available in flash. You can then
-jump to that address to start U-Boot.
-
-At present this feature is only supported in SPL and TPL. In principle it is
-possible to fill in such symbols in U-Boot proper, as well, but a future C
-library is planned for this instead, to read from the device tree.
-
-As well as image-pos, it is possible to read the size of an entry and its
-offset (which is the start position of the entry within its parent).
-
-A small technical note: Binman automatically adds the base address of the image
-(i.e. __image_copy_start) to the value of the image-pos symbol, so that when the
-image is loaded to its linked address, the value will be correct and actually
-point into the image.
-
-For example, say SPL is at the start of the image and linked to start at address
-80108000. If U-Boot's image-pos is 0x8000 then binman will write an image-pos
-for U-Boot of 80110000 into the SPL binary, since it assumes the image is loaded
-to 80108000, with SPL at 80108000 and U-Boot at 80110000.
-
-For x86 devices (with the end-at-4gb property) this base address is not added
-since it is assumed that images are XIP and the offsets already include the
-address.
-
-
-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.
-
-Alternatively, an FDT map entry can be used to add a special FDT containing
-just the information about the image. This is preceded by a magic string so can
-be located anywhere in the image. An image header (typically at the start or end
-of the image) can be used to point to the FDT map. See fdtmap and image-header
-entries for more information.
-
-
-Compression
------------
-
-Binman support compression for 'blob' entries (those of type 'blob' and
-derivatives). To enable this for an entry, add a 'compress' property:
-
-    blob {
-        filename = "datafile";
-        compress = "lz4";
-    };
-
-The entry will then contain the compressed data, using the 'lz4' compression
-algorithm. Currently this is the only one that is supported. The uncompressed
-size is written to the node in an 'uncomp-size' property, if -u is used.
-
-Compression is also supported for sections. In that case the entire section is
-compressed in one block, including all its contents. This means that accessing
-an entry from the section required decompressing the entire section. Also, the
-size of a section indicates the space that it consumes in its parent section
-(and typically the image). With compression, the section may contain more data,
-and the uncomp-size property indicates that, as above. The contents of the
-section is compressed first, before any padding is added. This ensures that the
-padding itself is not compressed, which would be a waste of time.
-
-
-Map files
----------
-
-The -m option causes binman to output a .map file for each image that it
-generates. This shows the offset and size of each entry. For example:
-
-      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
-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.
-
-
 External tools
 --------------
 
@@ -925,7 +1032,7 @@ Code coverage
 Binman is a critical tool and is designed to be very testable. Entry
 implementations target 100% test coverage. Run 'binman test -T' to check this.
 
-To enable Python test coverage on Debian-type distributions (e.g. Ubuntu):
+To enable Python test coverage on Debian-type distributions (e.g. Ubuntu)::
 
    $ sudo apt-get install python-coverage python3-coverage python-pytest
 
@@ -936,7 +1043,7 @@ Concurrent tests
 Binman tries to run tests concurrently. This means that the tests make use of
 all available CPUs to run.
 
- To enable this:
+ To enable this::
 
    $ sudo apt-get install python-subunit python3-subunit
 
@@ -959,19 +1066,19 @@ Binman's tests have been written under the assumption that they'll be run on a
 x86-like host and there hasn't been an attempt to make them portable yet.
 However, it's possible to run the tests by cross-compiling to x86.
 
-To install an x86 cross-compiler on Debian-type distributions (e.g. Ubuntu):
+To install an x86 cross-compiler on Debian-type distributions (e.g. Ubuntu)::
 
   $ sudo apt-get install gcc-x86-64-linux-gnu
 
-Then, you can run the tests under cross-compilation:
+Then, you can run the tests under cross-compilation::
 
   $ CROSS_COMPILE=x86_64-linux-gnu- binman test -T
 
 You can also use gcc-i686-linux-gnu similar to the above.
 
 
-Advanced Features / Technical docs
-----------------------------------
+Writing new entries and debugging
+---------------------------------
 
 The behaviour of entries is defined by the Entry class. All other entries are
 a subclass of this. An important subclass is Entry_blob which takes binary
@@ -999,13 +1106,13 @@ the DTC environment variable. This can be useful when the system dtc is too
 old.
 
 To enable a full backtrace and other debugging features in binman, pass
-BINMAN_DEBUG=1 to your build:
+BINMAN_DEBUG=1 to your build::
 
    make qemu-x86_defconfig
    make BINMAN_DEBUG=1
 
 To enable verbose logging from binman, base BINMAN_VERBOSE to your build, which
-adds a -v<level> option to the call to binman:
+adds a -v<level> option to the call to binman::
 
    make qemu-x86_defconfig
    make BINMAN_VERBOSE=5
@@ -1045,8 +1152,10 @@ To do
 -----
 
 Some ideas:
+
 - Use of-platdata to make the information available to code that is unable
-  to use device tree (such as a very small SPL image)
+  to use device tree (such as a very small SPL image). For now, limited info is
+  available via linker symbols
 - Allow easy building of images by specifying just the board name
 - Support building an image for a board (-b) more completely, with a
   configurable build directory
index c007d0a..95f9ba2 100644 (file)
@@ -56,6 +56,9 @@ controlled by a description in the board device tree.'''
         default=False, help='Output a map file for each image')
     build_parser.add_argument('-M', '--allow-missing', action='store_true',
         default=False, help='Allow external blobs to be missing')
+    build_parser.add_argument('-n', '--no-expanded', action='store_true',
+            help="Don't use 'expanded' versions of entries where available; "
+                 "normally 'u-boot' becomes 'u-boot-expanded', for example")
     build_parser.add_argument('-O', '--outdir', type=str,
         action='store', help='Path to directory to use for intermediate and '
         'output files')
@@ -66,7 +69,7 @@ controlled by a description in the board device tree.'''
         default=False, help='Update the binman node with offset/size info')
 
     entry_parser = subparsers.add_parser('entry-docs',
-        help='Write out entry documentation (see README.entries)')
+        help='Write out entry documentation (see entries.rst)')
 
     list_parser = subparsers.add_parser('ls', help='List files in an image')
     list_parser.add_argument('-i', '--image', type=str, required=True,
index 1952b2a..f57e34d 100644 (file)
@@ -28,7 +28,7 @@ images = OrderedDict()
 #    value: Text for the help
 missing_blob_help = {}
 
-def _ReadImageDesc(binman_node):
+def _ReadImageDesc(binman_node, use_expanded):
     """Read the image descriptions from the /binman node
 
     This normally produces a single Image object called 'image'. But if
@@ -36,15 +36,17 @@ def _ReadImageDesc(binman_node):
 
     Args:
         binman_node: Node object of the /binman node
+        use_expanded: True if the FDT will be updated with the entry information
     Returns:
         OrderedDict of Image objects, each of which describes an image
     """
     images = OrderedDict()
     if 'multiple-images' in binman_node.props:
         for node in binman_node.subnodes:
-            images[node.name] = Image(node.name, node)
+            images[node.name] = Image(node.name, node,
+                                      use_expanded=use_expanded)
     else:
-        images['image'] = Image('image', binman_node)
+        images['image'] = Image('image', binman_node, use_expanded=use_expanded)
     return images
 
 def _FindBinmanNode(dtb):
@@ -241,7 +243,7 @@ def ExtractEntries(image_fname, output_fname, outdir, entry_paths,
         # If this entry has children, create a directory for it and put its
         # data in a file called 'root' in that directory
         if entry.GetEntries():
-            if not os.path.exists(fname):
+            if fname and not os.path.exists(fname):
                 os.makedirs(fname)
             fname = os.path.join(fname, 'root')
         tout.Notice("Write entry '%s' size %x to '%s'" %
@@ -399,7 +401,7 @@ def ReplaceEntries(image_fname, input_fname, indir, entry_paths,
     return image
 
 
-def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt):
+def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded):
     """Prepare the images to be processed and select the device tree
 
     This function:
@@ -413,6 +415,9 @@ def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt):
         dtb_fname: Filename of the device tree file to use (.dts or .dtb)
         selected_images: List of images to output, or None for all
         update_fdt: True to update the FDT wth entry offsets, etc.
+        use_expanded: True to use expanded versions of entries, if available.
+            So if 'u-boot' is called for, we use 'u-boot-expanded' instead. This
+            is needed if update_fdt is True (although tests may disable it)
 
     Returns:
         OrderedDict of images:
@@ -438,7 +443,7 @@ def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt):
         raise ValueError("Device tree '%s' does not have a 'binman' "
                             "node" % dtb_fname)
 
-    images = _ReadImageDesc(node)
+    images = _ReadImageDesc(node, use_expanded)
 
     if select_images:
         skip = []
@@ -564,7 +569,7 @@ def Binman(args):
         if not pager:
             pager = 'more'
         fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
-                            'README')
+                            'README.rst')
         command.Run(pager, fname)
         return 0
 
@@ -611,6 +616,13 @@ def Binman(args):
         elf.debug = args.debug
         cbfs_util.VERBOSE = args.verbosity > 2
         state.use_fake_dtb = args.fake_dtb
+
+        # Normally we replace the 'u-boot' etype with 'u-boot-expanded', etc.
+        # When running tests this can be disabled using this flag. When not
+        # updating the FDT in image, it is not needed by binman, but we use it
+        # for consistency, so that the images look the same to U-Boot at
+        # runtime.
+        use_expanded = not args.no_expanded
         try:
             tools.SetInputDirs(args.indir)
             tools.PrepareOutputDir(args.outdir, args.preserve)
@@ -618,7 +630,7 @@ def Binman(args):
             state.SetEntryArgs(args.entry_arg)
 
             images = PrepareImagesAndDtbs(dtb_fname, args.image,
-                                          args.update_fdt)
+                                          args.update_fdt, use_expanded)
             missing = False
             for image in images.values():
                 missing |= ProcessImage(image, args.update_fdt, args.map,
similarity index 80%
rename from tools/binman/README.entries
rename to tools/binman/entries.rst
index 999b776..a91211e 100644 (file)
@@ -11,8 +11,8 @@ features to produce new behaviours.
 
 
 
-Entry: atf-bl31: Entry containing an ARM Trusted Firmware (ATF) BL31 blob
--------------------------------------------------------------------------
+Entry: atf-bl31: ARM Trusted Firmware (ATF) BL31 blob
+-----------------------------------------------------
 
 Properties / Entry arguments:
     - atf-bl31-path: Filename of file to read into entry. This is typically
@@ -25,8 +25,8 @@ about ATF.
 
 
 
-Entry: blob: Entry containing an arbitrary binary blob
-------------------------------------------------------
+Entry: blob: Arbitrary binary blob
+----------------------------------
 
 Note: This should not be used by itself. It is normally used as a parent
 class by other entry types.
@@ -39,7 +39,7 @@ Properties / Entry arguments:
 
 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'.
+example the 'u-boot' entry which provides the filename 'u-boot.bin'.
 
 If compression is enabled, an extra 'uncomp-size' property is written to
 the node (if enabled with -u) which provides the uncompressed size of the
@@ -56,8 +56,8 @@ obtained from the list of available device-tree files, managed by the
 
 
 
-Entry: blob-ext: Entry containing an externally built binary blob
------------------------------------------------------------------
+Entry: blob-ext: Externally built binary blob
+---------------------------------------------
 
 Note: This should not be used by itself. It is normally used as a parent
 class by other entry types.
@@ -87,8 +87,17 @@ See cros_ec_rw for an example of this.
 
 
 
-Entry: cbfs: Entry containing a Coreboot Filesystem (CBFS)
-----------------------------------------------------------
+Entry: blob-phase: Section that holds a phase binary
+----------------------------------------------------
+
+This is a base class that should not normally be used directly. It is used
+when converting a 'u-boot' entry automatically into a 'u-boot-expanded'
+entry; similarly for SPL.
+
+
+
+Entry: cbfs: Coreboot Filesystem (CBFS)
+---------------------------------------
 
 A CBFS provides a way to group files into a group. It has a simple directory
 structure and allows the position of individual files to be set, since it is
@@ -97,7 +106,7 @@ is not used, it supports compression and storing ELF files.
 
 CBFS is used by coreboot as its way of orgnanising SPI-flash contents.
 
-The contents of the CBFS are defined by subnodes of the cbfs entry, e.g.:
+The contents of the CBFS are defined by subnodes of the cbfs entry, e.g.::
 
     cbfs {
         size = <0x100000>;
@@ -113,7 +122,7 @@ This creates a CBFS 1MB in size two files in it: u-boot.bin and u-boot.dtb.
 Note that the size is required since binman does not support calculating it.
 The contents of each entry is just what binman would normally provide if it
 were not a CBFS node. A blob type can be used to import arbitrary files as
-with the second subnode below:
+with the second subnode below::
 
     cbfs {
         size = <0x100000>;
@@ -159,7 +168,7 @@ cbfs-type:
         This is an ELF file that has been loaded (i.e. mapped to memory), so
         appears in the CBFS as a flat binary. The input file must be an ELF
         image, for example this puts "u-boot" (the ELF image) into a 'stage'
-        entry:
+        entry::
 
             cbfs {
                 size = <0x100000>;
@@ -169,7 +178,7 @@ cbfs-type:
                 };
             };
 
-        You can use your own ELF file with something like:
+        You can use your own ELF file with something like::
 
             cbfs {
                 size = <0x100000>;
@@ -202,7 +211,7 @@ not support other file types (e.g. payload), adding multiple files (like the
 particular offset in the CBFS and a few other things.
 
 Of course binman can create images containing multiple CBFSs, simply by
-defining these in the binman config:
+defining these in the binman config::
 
 
     binman {
@@ -239,6 +248,19 @@ both of size 1MB.
 
 
 
+Entry: collection: An entry which contains a collection of other entries
+------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - content: List of phandles to entries to include
+
+This allows reusing the contents of other entries. The contents of the
+listed entries are combined to form this entry. This serves as a useful
+base class for entry types which need to process data from elsewhere in
+the image, not necessarily child entries.
+
+
+
 Entry: cros-ec-rw: A blob entry which contains a Chromium OS read-write EC image
 --------------------------------------------------------------------------------
 
@@ -270,38 +292,39 @@ sizes are included.
 Note that the -u option must be provided to ensure that binman updates the
 FDT with the position of each entry.
 
-Example output for a simple image with U-Boot and an FDT map:
+Example output for a simple image with U-Boot and an FDT map::
 
-/ {
-    image-name = "binman";
-    size = <0x00000112>;
-    image-pos = <0x00000000>;
-    offset = <0x00000000>;
-    u-boot {
-        size = <0x00000004>;
+    / {
+        image-name = "binman";
+        size = <0x00000112>;
         image-pos = <0x00000000>;
         offset = <0x00000000>;
+        u-boot {
+            size = <0x00000004>;
+            image-pos = <0x00000000>;
+            offset = <0x00000000>;
+        };
+        fdtmap {
+            size = <0x0000010e>;
+            image-pos = <0x00000004>;
+            offset = <0x00000004>;
+        };
     };
-    fdtmap {
-        size = <0x0000010e>;
-        image-pos = <0x00000004>;
-        offset = <0x00000004>;
-    };
-};
 
 If allow-repack is used then 'orig-offset' and 'orig-size' properties are
 added as necessary. See the binman README.
 
 
 
-Entry: files: Entry containing a set of files
----------------------------------------------
+Entry: files: A set of files arranged in a section
+--------------------------------------------------
 
 Properties / Entry arguments:
     - pattern: Filename pattern to match the files to include
     - files-compress: Compression algorithm to use:
         none: No compression
         lz4: Use lz4 compression (via 'lz4' command-line utility)
+    - files-align: Align each file to the given alignment
 
 This entry reads a number of files and places each in a separate sub-entry
 within this entry. To access these you need to enable device-tree updates
@@ -325,8 +348,8 @@ byte value of a region.
 
 
 
-Entry: fit: Entry containing a FIT
-----------------------------------
+Entry: fit: Flat Image Tree (FIT)
+---------------------------------
 
 This calls mkimage to create a FIT (U-Boot Flat Image Tree) based on the
 input provided.
@@ -334,7 +357,7 @@ input provided.
 Nodes for the FIT should be written out in the binman configuration just as
 they would be in a file passed to mkimage.
 
-For example, this creates an image containing a FIT with U-Boot SPL:
+For example, this creates an image containing a FIT with U-Boot SPL::
 
     binman {
         fit {
@@ -364,7 +387,7 @@ that you want to generates nodes for two files: file1.dtb and file2.dtb
 The fit,fdt-list property (see above) indicates that of-list should be used.
 If the property is missing you will get an error.
 
-Then add a 'generator node', a node with a name starting with '@':
+Then add a 'generator node', a node with a name starting with '@'::
 
     images {
         @fdt-SEQ {
@@ -379,7 +402,7 @@ files. All the properties you specify will be included in the node. This
 node acts like a template to generate the nodes. The generator node itself
 does not appear in the output - it is replaced with what binman generates.
 
-You can create config nodes in a similar way:
+You can create config nodes in a similar way::
 
     configurations {
         default = "@config-DEFAULT-SEQ";
@@ -396,8 +419,10 @@ each of your two files.
 
 Available substitutions for '@' nodes are:
 
-    SEQ    Sequence number of the generated fdt (1, 2, ...)
-    NAME   Name of the dtb as provided (i.e. without adding '.dtb')
+SEQ:
+    Sequence number of the generated fdt (1, 2, ...)
+NAME
+    Name of the dtb as provided (i.e. without adding '.dtb')
 
 Note that if no devicetree files are provided (with '-a of-list' as above)
 then no nodes will be generated.
@@ -406,10 +431,11 @@ The 'default' property, if present, will be automatically set to the name
 if of configuration whose devicetree matches the 'default-dt' entry
 argument, e.g. with '-a default-dt=sun50i-a64-pine64-lts'.
 
-Available substitutions for '@' property values are:
+Available substitutions for '@' property values are
 
-    DEFAULT-SEQ  Sequence number of the default fdt,as provided by the
-                 'default-dt' entry argument
+DEFAULT-SEQ:
+    Sequence number of the default fdt,as provided by the 'default-dt' entry
+    argument
 
 Properties (in the 'fit' node itself):
     fit,external-offset: Indicates that the contents of the FIT are external
@@ -478,8 +504,8 @@ first/last in the entry list.
 
 
 
-Entry: intel-cmc: Entry containing an Intel Chipset Micro Code (CMC) file
--------------------------------------------------------------------------
+Entry: intel-cmc: Intel Chipset Micro Code (CMC) file
+-----------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -531,8 +557,8 @@ This entry contains a pointer to the FIT. It is required to be at address
 
 
 
-Entry: intel-fsp: Entry containing an Intel Firmware Support Package (FSP) file
--------------------------------------------------------------------------------
+Entry: intel-fsp: Intel Firmware Support Package (FSP) file
+-----------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -548,8 +574,8 @@ See README.x86 for information about x86 binary blobs.
 
 
 
-Entry: intel-fsp-m: Entry containing Intel Firmware Support Package (FSP) memory init
--------------------------------------------------------------------------------------
+Entry: intel-fsp-m: Intel Firmware Support Package (FSP) memory init
+--------------------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -565,8 +591,8 @@ See README.x86 for information about x86 binary blobs.
 
 
 
-Entry: intel-fsp-s: Entry containing Intel Firmware Support Package (FSP) silicon init
---------------------------------------------------------------------------------------
+Entry: intel-fsp-s: Intel Firmware Support Package (FSP) silicon init
+---------------------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -582,8 +608,8 @@ See README.x86 for information about x86 binary blobs.
 
 
 
-Entry: intel-fsp-t: Entry containing Intel Firmware Support Package (FSP) temp ram init
----------------------------------------------------------------------------------------
+Entry: intel-fsp-t: Intel Firmware Support Package (FSP) temp ram init
+----------------------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -598,8 +624,8 @@ See README.x86 for information about x86 binary blobs.
 
 
 
-Entry: intel-ifwi: Entry containing an Intel Integrated Firmware Image (IFWI) file
-----------------------------------------------------------------------------------
+Entry: intel-ifwi: Intel Integrated Firmware Image (IFWI) file
+--------------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry. This is either the
@@ -623,17 +649,17 @@ Each subnode describes an entry which is placed into the IFWFI with a given
 sub-partition (and optional entry name).
 
 Properties for subnodes:
-    ifwi-subpart - sub-parition to put this entry into, e.g. "IBBP"
-    ifwi-entry - entry name t use, e.g. "IBBL"
-    ifwi-replace - if present, indicates that the item should be replaced
-        in the IFWI. Otherwise it is added.
+    - ifwi-subpart: sub-parition to put this entry into, e.g. "IBBP"
+    - ifwi-entry: entry name t use, e.g. "IBBL"
+    - ifwi-replace: if present, indicates that the item should be replaced
+      in the IFWI. Otherwise it is added.
 
 See README.x86 for information about x86 binary blobs.
 
 
 
-Entry: intel-me: Entry containing an Intel Management Engine (ME) file
-----------------------------------------------------------------------
+Entry: intel-me: Intel Management Engine (ME) file
+--------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -652,8 +678,8 @@ See README.x86 for information about x86 binary blobs.
 
 
 
-Entry: intel-mrc: Entry containing an Intel Memory Reference Code (MRC) file
-----------------------------------------------------------------------------
+Entry: intel-mrc: Intel Memory Reference Code (MRC) file
+--------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -666,8 +692,8 @@ See README.x86 for information about x86 binary blobs.
 
 
 
-Entry: intel-refcode: Entry containing an Intel Reference Code file
--------------------------------------------------------------------
+Entry: intel-refcode: Intel Reference Code file
+-----------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -680,8 +706,8 @@ See README.x86 for information about x86 binary blobs.
 
 
 
-Entry: intel-vbt: Entry containing an Intel Video BIOS Table (VBT) file
------------------------------------------------------------------------
+Entry: intel-vbt: Intel Video BIOS Table (VBT) file
+---------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -693,8 +719,8 @@ See README.x86 for information about Intel binary blobs.
 
 
 
-Entry: intel-vga: Entry containing an Intel Video Graphics Adaptor (VGA) file
------------------------------------------------------------------------------
+Entry: intel-vga: Intel Video Graphics Adaptor (VGA) file
+---------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -708,15 +734,15 @@ See README.x86 for information about Intel binary blobs.
 
 
 
-Entry: mkimage: Entry containing a binary produced by mkimage
--------------------------------------------------------------
+Entry: mkimage: Binary produced by mkimage
+------------------------------------------
 
 Properties / Entry arguments:
     - datafile: Filename for -d argument
     - args: Other arguments to pass
 
 The data passed to mkimage is collected from subnodes of the mkimage node,
-e.g.:
+e.g.::
 
     mkimage {
         args = "-n test -T imximage";
@@ -743,8 +769,8 @@ placed at offset 'RESET_VECTOR_ADDRESS - 0xffc'.
 
 
 
-Entry: scp: Entry containing a System Control Processor (SCP) firmware blob
----------------------------------------------------------------------------
+Entry: scp: System Control Processor (SCP) firmware blob
+--------------------------------------------------------
 
 Properties / Entry arguments:
     - scp-path: Filename of file to read into the entry, typically scp.bin
@@ -756,11 +782,13 @@ This entry holds firmware for an external platform-specific coprocessor.
 Entry: section: Entry that contains other entries
 -------------------------------------------------
 
-Properties / Entry arguments: (see binman README for more information)
+Properties / Entry arguments: (see binman README for more information):
     pad-byte: Pad byte to use when padding
     sort-by-offset: True if entries should be sorted by offset, False if
-        they must be in-order in the device tree description
+    they must be in-order in the device tree description
+
     end-at-4gb: Used to build an x86 ROM which ends at 4GB (2^32)
+
     skip-at-start: Number of bytes before the first entry starts. These
         effectively adjust the starting offset of entries. For example,
         if this is 16, then the first entry would start at 16. An entry
@@ -768,6 +796,8 @@ Properties / Entry arguments: (see binman README for more information)
         file, since the first 16 bytes are skipped when writing.
     name-prefix: Adds a prefix to the name of every entry in the section
         when writing out the map
+    align_default: Default alignment for this section, if no alignment is
+        given in the entry
 
 Properties:
     allow_missing: True if this section permits external blobs to be
@@ -798,7 +828,7 @@ Properties / Entry arguments:
     <text>: The text to place in the entry (overrides the above mechanism).
         This is useful when the text is constant.
 
-Example node:
+Example node::
 
     text {
         size = <50>;
@@ -811,7 +841,7 @@ You can then use:
 
 and binman will insert that string into the entry.
 
-It is also possible to put the string directly in the node:
+It is also possible to put the string directly in the node::
 
     text {
         size = <8>;
@@ -819,7 +849,7 @@ It is also possible to put the string directly in the node:
         message = "a message directly in the node"
     };
 
-or just:
+or just::
 
     text {
         size = <8>;
@@ -839,8 +869,7 @@ Properties / Entry arguments:
 
 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.
+blob at the end of it.
 
 U-Boot can access binman symbols at runtime. See:
 
@@ -848,6 +877,9 @@ U-Boot can access binman symbols at runtime. See:
 
 in the binman README for more information.
 
+Note that this entry is automatically replaced with u-boot-expanded unless
+--no-expanded is used or the node has a 'no-expanded' property.
+
 
 
 Entry: u-boot-dtb: U-Boot device tree
@@ -875,9 +907,9 @@ 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
+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.
+it available to u-boot-ucode.
 
 
 
@@ -901,6 +933,21 @@ Properties / Entry arguments:
 
 
 
+Entry: u-boot-expanded: U-Boot flat binary broken out into its component parts
+------------------------------------------------------------------------------
+
+This is a section containing the U-Boot binary and a devicetree. Using this
+entry type automatically creates this section, with the following entries
+in it:
+
+   u-boot-nodtb
+   u-boot-dtb
+
+Having the devicetree separate allows binman to update it in the final
+image, so that the entries positions are provided to the running U-Boot.
+
+
+
 Entry: u-boot-img: U-Boot legacy image
 --------------------------------------
 
@@ -919,13 +966,13 @@ 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')
+    - filename: Filename to include (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).
+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, normally expands to a
+section containing u-boot and u-boot-dtb
 
 
 
@@ -951,6 +998,9 @@ 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.
 
+Note that this entry is automatically replaced with u-boot-spl-expanded
+unless --no-expanded is used or the node has a 'no-expanded' property.
+
 
 
 Entry: u-boot-spl-bss-pad: U-Boot SPL binary padded with a BSS region
@@ -959,13 +1009,16 @@ 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.
+This holds the padding added after the SPL binary to cover the BSS (Block
+Started by Symbol) region. This region holds the various variables 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 contents of this entry will a certain number of zero bytes, determined
+by __bss_size
 
 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.
@@ -995,18 +1048,50 @@ be relocated to any address for execution.
 
 
 
+Entry: u-boot-spl-expanded: U-Boot SPL flat binary broken out into its component parts
+--------------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - spl-dtb: Controls whether this entry is selected (set to 'y' or '1' to
+        select)
+
+This is a section containing the U-Boot binary, BSS padding if needed and a
+devicetree. Using this entry type automatically creates this section, with
+the following entries in it:
+
+   u-boot-spl-nodtb
+   u-boot-spl-bss-pad
+   u-boot-dtb
+
+Having the devicetree separate allows binman to update it in the final
+image, so that the entries positions are provided to the running U-Boot.
+
+This entry is selected based on the value of the 'spl-dtb' entryarg. If
+this is non-empty (and not 'n' or '0') then this expanded entry is selected.
+
+
+
 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')
+    - filename: Filename to include (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).
+a device tree to operate on your platform. You can add a u-boot-spl-dtb
+entry after this one, or use a u-boot-spl entry instead' which normally
+expands to a section containing u-boot-spl-dtb, u-boot-spl-bss-pad and
+u-boot-spl-dtb
+
+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.
 
 
 
@@ -1042,6 +1127,31 @@ 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.
 
+Note that this entry is automatically replaced with u-boot-tpl-expanded
+unless --no-expanded is used or the node has a 'no-expanded' property.
+
+
+
+Entry: u-boot-tpl-bss-pad: U-Boot TPL binary padded with a BSS region
+---------------------------------------------------------------------
+
+Properties / Entry arguments:
+    None
+
+This holds the padding added after the TPL binary to cover the BSS (Block
+Started by Symbol) region. This region holds the various variables used by
+TPL. It is set to 0 by TPL when it starts up. If you want to append data to
+the TPL 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 contents of this entry will a certain number of zero bytes, determined
+by __bss_size
+
+The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+binman uses that to look up the BSS address.
+
 
 
 Entry: u-boot-tpl-dtb: U-Boot TPL device tree
@@ -1077,6 +1187,53 @@ be relocated to any address for execution.
 
 
 
+Entry: u-boot-tpl-expanded: U-Boot TPL flat binary broken out into its component parts
+--------------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - tpl-dtb: Controls whether this entry is selected (set to 'y' or '1' to
+        select)
+
+This is a section containing the U-Boot binary, BSS padding if needed and a
+devicetree. Using this entry type automatically creates this section, with
+the following entries in it:
+
+   u-boot-tpl-nodtb
+   u-boot-tpl-bss-pad
+   u-boot-dtb
+
+Having the devicetree separate allows binman to update it in the final
+image, so that the entries positions are provided to the running U-Boot.
+
+This entry is selected based on the value of the 'tpl-dtb' entryarg. If
+this is non-empty (and not 'n' or '0') then this expanded entry is selected.
+
+
+
+Entry: u-boot-tpl-nodtb: TPL binary without device tree appended
+----------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename to include (default 'tpl/u-boot-tpl-nodtb.bin')
+
+This is the U-Boot TPL binary, It does not include a device tree blob at
+the end of it so may not be able to work without it, assuming TPL needs
+a device tree to operate on your platform. You can add a u-boot-tpl-dtb
+entry after this one, or use a u-boot-tpl entry instead, which normally
+expands to a section containing u-boot-tpl-dtb, u-boot-tpl-bss-pad and
+u-boot-tpl-dtb
+
+TPL 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-with-ucode-ptr: U-Boot TPL with embedded microcode pointer
 ----------------------------------------------------------------------------
 
@@ -1147,7 +1304,7 @@ Properties / Entry arguments:
 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.
+complicated. Otherwise it is the same as the u-boot entry.
 
 
 
index d58a730..7022271 100644 (file)
@@ -102,22 +102,30 @@ class Entry(object):
         self.allow_missing = False
 
     @staticmethod
-    def Lookup(node_path, etype):
+    def Lookup(node_path, etype, expanded):
         """Look up the entry class for a node.
 
         Args:
             node_node: Path name of Node object containing information about
                        the entry to create (used for errors)
             etype:   Entry type to use
+            expanded: Use the expanded version of etype
 
         Returns:
-            The entry class object if found, else None
+            The entry class object if found, else None if not found and expanded
+                is True
+
+        Raise:
+            ValueError if expanded is False and the class is not found
         """
         # Convert something like 'u-boot@0' to 'u_boot' since we are only
         # interested in the type.
         module_name = etype.replace('-', '_')
+
         if '@' in module_name:
             module_name = module_name.split('@')[0]
+        if expanded:
+            module_name += '_expanded'
         module = modules.get(module_name)
 
         # Also allow entry-type modules to be brought in from the etype directory.
@@ -127,6 +135,8 @@ class Entry(object):
             try:
                 module = importlib.import_module('binman.etype.' + module_name)
             except ImportError as e:
+                if expanded:
+                    return None
                 raise ValueError("Unknown entry type '%s' in node '%s' (expected etype/%s.py, error '%s'" %
                                  (etype, node_path, module_name, e))
             modules[module_name] = module
@@ -135,21 +145,32 @@ class Entry(object):
         return getattr(module, 'Entry_%s' % module_name)
 
     @staticmethod
-    def Create(section, node, etype=None):
+    def Create(section, node, etype=None, expanded=False):
         """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)
+            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)
+            expanded: True to use expanded versions of entries, where available
 
         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(node.path, etype)
+        obj = Entry.Lookup(node.path, etype, expanded)
+        if obj and expanded:
+            # Check whether to use the expanded entry
+            new_etype = etype + '-expanded'
+            can_expand = not fdt_util.GetBool(node, 'no-expanded')
+            if can_expand and obj.UseExpanded(node, etype, new_etype):
+                etype = new_etype
+            else:
+                obj = None
+        if not obj:
+            obj = Entry.Lookup(node.path, etype, False)
 
         # Call its constructor to get the object we want.
         return obj(section, etype, node)
@@ -180,6 +201,8 @@ class Entry(object):
         if tools.NotPowerOfTwo(self.align):
             raise ValueError("Node '%s': Alignment %s must be a power of two" %
                              (self._node.path, self.align))
+        if self.section and self.align is None:
+            self.align = self.section.align_default
         self.pad_before = fdt_util.GetInt(self._node, 'pad-before', 0)
         self.pad_after = fdt_util.GetInt(self._node, 'pad-after', 0)
         self.align_size = fdt_util.GetInt(self._node, 'align-size')
@@ -205,12 +228,23 @@ class Entry(object):
             Dict:
                 key: Filename from this entry (without the path)
                 value: Tuple:
-                    Fdt object for this dtb, or None if not available
+                    Entry object for this dtb
                     Filename of file containing this dtb
         """
         return {}
 
     def ExpandEntries(self):
+        """Expand out entries which produce other entries
+
+        Some entries generate subnodes automatically, from which sub-entries
+        are then created. This method allows those to be added to the binman
+        definition for the current image. An entry which implements this method
+        should call state.AddSubnode() to add a subnode and can add properties
+        with state.AddString(), etc.
+
+        An example is 'files', which produces a section containing a list of
+        files.
+        """
         pass
 
     def AddMissingProperties(self, have_image_pos):
@@ -406,6 +440,11 @@ class Entry(object):
         """Convenience function to raise an error referencing a node"""
         raise ValueError("Node '%s': %s" % (self._node.path, msg))
 
+    def Info(self, msg):
+        """Convenience function to log info referencing a node"""
+        tag = "Info '%s'" % self._node.path
+        tout.Detail('%30s: %s' % (tag, msg))
+
     def Detail(self, msg):
         """Convenience function to log detail referencing a node"""
         tag = "Node '%s'" % self._node.path
@@ -445,9 +484,13 @@ class Entry(object):
         """
         return self._node.path
 
-    def GetData(self):
+    def GetData(self, required=True):
         """Get the contents of an entry
 
+        Args:
+            required: True if the data must be present, False if it is OK to
+                return None
+
         Returns:
             bytes content of the entry, excluding any padding. If the entry is
                 compressed, the compressed data is returned
@@ -637,7 +680,7 @@ features to produce new behaviours.
             modules.remove('_testing')
         missing = []
         for name in modules:
-            module = Entry.Lookup('WriteDocs', name)
+            module = Entry.Lookup('WriteDocs', name, False)
             docs = getattr(module, '__doc__')
             if test_missing == name:
                 docs = None
@@ -896,3 +939,25 @@ features to produce new behaviours.
             self.uncomp_size = len(indata)
         data = tools.Compress(indata, self.compress)
         return data
+
+    @classmethod
+    def UseExpanded(cls, node, etype, new_etype):
+        """Check whether to use an expanded entry type
+
+        This is called by Entry.Create() when it finds an expanded version of
+        an entry type (e.g. 'u-boot-expanded'). If this method returns True then
+        it will be used (e.g. in place of 'u-boot'). If it returns False, it is
+        ignored.
+
+        Args:
+            node:     Node object containing information about the entry to
+                      create
+            etype:    Original entry type being used
+            new_etype: New entry type proposed
+
+        Returns:
+            True to use this entry type, False to use the original one
+        """
+        tout.Info("Node '%s': etype '%s': %s selected" %
+                  (node.path, etype, new_etype))
+        return True
index 80802f3..c3d5f3e 100644 (file)
@@ -87,6 +87,18 @@ class TestEntry(unittest.TestCase):
         base = entry.Entry.Create(None, self.GetNode(), 'blob-dtb')
         self.assertIsNone(base.ReadChildData(base))
 
+    def testExpandedEntry(self):
+        """Test use of an expanded entry when available"""
+        base = entry.Entry.Create(None, self.GetNode())
+        self.assertEqual('u-boot', base.etype)
+
+        expanded = entry.Entry.Create(None, self.GetNode(), expanded=True)
+        self.assertEqual('u-boot-expanded', expanded.etype)
+
+        with self.assertRaises(ValueError) as e:
+            entry.Entry.Create(None, self.GetNode(), 'missing', expanded=True)
+        self.assertIn("Unknown entry type 'missing' in node '/binman/u-boot'",
+                      str(e.exception))
 
 if __name__ == "__main__":
     unittest.main()
index 195adc7..163d714 100644 (file)
@@ -8,7 +8,7 @@
 from binman.etype.blob_named_by_arg import Entry_blob_named_by_arg
 
 class Entry_atf_bl31(Entry_blob_named_by_arg):
-    """Entry containing an ARM Trusted Firmware (ATF) BL31 blob
+    """ARM Trusted Firmware (ATF) BL31 blob
 
     Properties / Entry arguments:
         - atf-bl31-path: Filename of file to read into entry. This is typically
index 81756c3..018f8c9 100644 (file)
@@ -11,7 +11,7 @@ from patman import tools
 from patman import tout
 
 class Entry_blob(Entry):
-    """Entry containing an arbitrary binary blob
+    """Arbitrary binary blob
 
     Note: This should not be used by itself. It is normally used as a parent
     class by other entry types.
@@ -24,7 +24,7 @@ class Entry_blob(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'.
+    example the 'u-boot' entry which provides the filename 'u-boot.bin'.
 
     If compression is enabled, an extra 'uncomp-size' property is written to
     the node (if enabled with -u) which provides the uncompressed size of the
index 724647a..3ce7511 100644 (file)
@@ -44,15 +44,6 @@ class Entry_blob_dtb(Entry_blob):
         return None
 
     def GetFdts(self):
-        """Get the device trees used by this entry
-
-        Returns:
-            Dict:
-                key: Filename from this entry (without the path)
-                value: Tuple:
-                    Fdt object for this dtb, or None if not available
-                    Filename of file containing this dtb
-        """
         fname = self.GetDefaultFilename()
         return {self.GetFdtEtype(): [self, fname]}
 
index e372445..d6b0ca1 100644 (file)
@@ -13,7 +13,7 @@ from patman import tools
 from patman import tout
 
 class Entry_blob_ext(Entry_blob):
-    """Entry containing an externally built binary blob
+    """Externally built binary blob
 
     Note: This should not be used by itself. It is normally used as a parent
     class by other entry types.
diff --git a/tools/binman/etype/blob_phase.py b/tools/binman/etype/blob_phase.py
new file mode 100644 (file)
index 0000000..54ca54c
--- /dev/null
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type base class for U-Boot or SPL binary with devicetree
+#
+
+from binman.etype.section import Entry_section
+
+class Entry_blob_phase(Entry_section):
+    """Section that holds a phase binary
+
+    This is a base class that should not normally be used directly. It is used
+    when converting a 'u-boot' entry automatically into a 'u-boot-expanded'
+    entry; similarly for SPL.
+    """
+    def __init__(self, section, etype, node, root_fname, dtb_file, bss_pad):
+        """Set up a new blob for a phase
+
+        This holds an executable for a U-Boot phase, optional BSS padding and
+        a devicetree
+
+        Args:
+            section: entry_Section object for this entry's parent
+            etype: Type of object
+            node: Node defining this entry
+            root_fname: Root filename for the binary ('u-boot',
+                'spl/u-boot-spl', etc.)
+            dtb_file: Name of devicetree file ('u-boot.dtb', u-boot-spl.dtb',
+                etc.)
+            bss_pad: True to add BSS padding before the devicetree
+        """
+        # Put this here to allow entry-docs and help to work without libfdt
+        global state
+        from binman import state
+
+        super().__init__(section, etype, node)
+        self.root_fname = root_fname
+        self.dtb_file = dtb_file
+        self.bss_pad = bss_pad
+
+    def ExpandEntries(self):
+        """Create the subnodes"""
+        names = [self.root_fname + '-nodtb', self.root_fname + '-dtb']
+        if self.bss_pad:
+            names.insert(1, self.root_fname + '-bss-pad')
+        for name in names:
+            subnode = state.AddSubnode(self._node, name)
+
+        # Read entries again, now that we have some
+        self._ReadEntries()
index 6cdbaa0..44db7b9 100644 (file)
@@ -13,7 +13,7 @@ from binman.entry import Entry
 from dtoc import fdt_util
 
 class Entry_cbfs(Entry):
-    """Entry containing a Coreboot Filesystem (CBFS)
+    """Coreboot Filesystem (CBFS)
 
     A CBFS provides a way to group files into a group. It has a simple directory
     structure and allows the position of individual files to be set, since it is
@@ -22,7 +22,7 @@ class Entry_cbfs(Entry):
 
     CBFS is used by coreboot as its way of orgnanising SPI-flash contents.
 
-    The contents of the CBFS are defined by subnodes of the cbfs entry, e.g.:
+    The contents of the CBFS are defined by subnodes of the cbfs entry, e.g.::
 
         cbfs {
             size = <0x100000>;
@@ -38,7 +38,7 @@ class Entry_cbfs(Entry):
     Note that the size is required since binman does not support calculating it.
     The contents of each entry is just what binman would normally provide if it
     were not a CBFS node. A blob type can be used to import arbitrary files as
-    with the second subnode below:
+    with the second subnode below::
 
         cbfs {
             size = <0x100000>;
@@ -84,7 +84,7 @@ class Entry_cbfs(Entry):
             This is an ELF file that has been loaded (i.e. mapped to memory), so
             appears in the CBFS as a flat binary. The input file must be an ELF
             image, for example this puts "u-boot" (the ELF image) into a 'stage'
-            entry:
+            entry::
 
                 cbfs {
                     size = <0x100000>;
@@ -94,7 +94,7 @@ class Entry_cbfs(Entry):
                     };
                 };
 
-            You can use your own ELF file with something like:
+            You can use your own ELF file with something like::
 
                 cbfs {
                     size = <0x100000>;
@@ -127,7 +127,7 @@ class Entry_cbfs(Entry):
     particular offset in the CBFS and a few other things.
 
     Of course binman can create images containing multiple CBFSs, simply by
-    defining these in the binman config:
+    defining these in the binman config::
 
 
         binman {
@@ -169,6 +169,7 @@ class Entry_cbfs(Entry):
 
         super().__init__(section, etype, node)
         self._cbfs_arg = fdt_util.GetString(node, 'cbfs-arch', 'x86')
+        self.align_default = None
         self._cbfs_entries = OrderedDict()
         self._ReadSubnodes()
         self.reader = None
diff --git a/tools/binman/etype/collection.py b/tools/binman/etype/collection.py
new file mode 100644 (file)
index 0000000..1625575
--- /dev/null
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+# Support for a collection of entries from other parts of an image
+
+from collections import OrderedDict
+import os
+
+from binman.entry import Entry
+from dtoc import fdt_util
+
+class Entry_collection(Entry):
+    """An entry which contains a collection of other entries
+
+    Properties / Entry arguments:
+        - content: List of phandles to entries to include
+
+    This allows reusing the contents of other entries. The contents of the
+    listed entries are combined to form this entry. This serves as a useful
+    base class for entry types which need to process data from elsewhere in
+    the image, not necessarily child entries.
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node)
+        self.content = fdt_util.GetPhandleList(self._node, 'content')
+        if not self.content:
+            self.Raise("Collection must have a 'content' property")
+
+    def GetContents(self, required):
+        """Get the contents of this entry
+
+        Args:
+            required: True if the data must be present, False if it is OK to
+                return None
+
+        Returns:
+            bytes content of the entry
+        """
+        # Join up all the data
+        self.Info('Getting contents, required=%s' % required)
+        data = b''
+        for entry_phandle in self.content:
+            entry_data = self.section.GetContentsByPhandle(entry_phandle, self,
+                                                           required)
+            if not required and entry_data is None:
+                self.Info('Contents not available yet')
+                # Data not available yet
+                return None
+            data += entry_data
+
+        self.Info('Returning contents size %x' % len(data))
+
+        return data
+
+    def ObtainContents(self):
+        data = self.GetContents(False)
+        if data is None:
+            return False
+        self.SetContents(data)
+        return True
+
+    def ProcessContents(self):
+        # The blob may have changed due to WriteSymbols()
+        data = self.GetContents(True)
+        return self.ProcessContentsUpdate(data)
index 6ca88a1..2339fee 100644 (file)
@@ -53,24 +53,24 @@ class Entry_fdtmap(Entry):
     Note that the -u option must be provided to ensure that binman updates the
     FDT with the position of each entry.
 
-    Example output for a simple image with U-Boot and an FDT map:
-
-    / {
-        image-name = "binman";
-        size = <0x00000112>;
-        image-pos = <0x00000000>;
-        offset = <0x00000000>;
-        u-boot {
-            size = <0x00000004>;
+    Example output for a simple image with U-Boot and an FDT map::
+
+        / {
+            image-name = "binman";
+            size = <0x00000112>;
             image-pos = <0x00000000>;
             offset = <0x00000000>;
+            u-boot {
+                size = <0x00000004>;
+                image-pos = <0x00000000>;
+                offset = <0x00000000>;
+            };
+            fdtmap {
+                size = <0x0000010e>;
+                image-pos = <0x00000004>;
+                offset = <0x00000004>;
+            };
         };
-        fdtmap {
-            size = <0x0000010e>;
-            image-pos = <0x00000004>;
-            offset = <0x00000004>;
-        };
-    };
 
     If allow-repack is used then 'orig-offset' and 'orig-size' properties are
     added as necessary. See the binman README.
index 1feebd0..5db36ab 100644 (file)
@@ -15,7 +15,7 @@ from patman import tools
 
 
 class Entry_files(Entry_section):
-    """Entry containing a set of files
+    """A set of files arranged in a section
 
     Properties / Entry arguments:
         - pattern: Filename pattern to match the files to include
index 1a7cbd7..6936f57 100644 (file)
@@ -14,7 +14,7 @@ from dtoc.fdt import Fdt
 from patman import tools
 
 class Entry_fit(Entry):
-    """Entry containing a FIT
+    """Flat Image Tree (FIT)
 
     This calls mkimage to create a FIT (U-Boot Flat Image Tree) based on the
     input provided.
@@ -22,7 +22,7 @@ class Entry_fit(Entry):
     Nodes for the FIT should be written out in the binman configuration just as
     they would be in a file passed to mkimage.
 
-    For example, this creates an image containing a FIT with U-Boot SPL:
+    For example, this creates an image containing a FIT with U-Boot SPL::
 
         binman {
             fit {
@@ -52,7 +52,7 @@ class Entry_fit(Entry):
     The fit,fdt-list property (see above) indicates that of-list should be used.
     If the property is missing you will get an error.
 
-    Then add a 'generator node', a node with a name starting with '@':
+    Then add a 'generator node', a node with a name starting with '@'::
 
         images {
             @fdt-SEQ {
@@ -67,7 +67,7 @@ class Entry_fit(Entry):
     node acts like a template to generate the nodes. The generator node itself
     does not appear in the output - it is replaced with what binman generates.
 
-    You can create config nodes in a similar way:
+    You can create config nodes in a similar way::
 
         configurations {
             default = "@config-DEFAULT-SEQ";
@@ -84,8 +84,10 @@ class Entry_fit(Entry):
 
     Available substitutions for '@' nodes are:
 
-        SEQ    Sequence number of the generated fdt (1, 2, ...)
-        NAME   Name of the dtb as provided (i.e. without adding '.dtb')
+    SEQ:
+        Sequence number of the generated fdt (1, 2, ...)
+    NAME
+        Name of the dtb as provided (i.e. without adding '.dtb')
 
     Note that if no devicetree files are provided (with '-a of-list' as above)
     then no nodes will be generated.
@@ -94,10 +96,11 @@ class Entry_fit(Entry):
     if of configuration whose devicetree matches the 'default-dt' entry
     argument, e.g. with '-a default-dt=sun50i-a64-pine64-lts'.
 
-    Available substitutions for '@' property values are:
+    Available substitutions for '@' property values are
 
-        DEFAULT-SEQ  Sequence number of the default fdt,as provided by the
-                     'default-dt' entry argument
+    DEFAULT-SEQ:
+        Sequence number of the default fdt,as provided by the 'default-dt' entry
+        argument
 
     Properties (in the 'fit' node itself):
         fit,external-offset: Indicates that the contents of the FIT are external
index 644fa42..494d43c 100644 (file)
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_cmc(Entry_blob_ext):
-    """Entry containing an Intel Chipset Micro Code (CMC) file
+    """Intel Chipset Micro Code (CMC) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
index 2ac012b..326cb7d 100644 (file)
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_fsp(Entry_blob_ext):
-    """Entry containing an Intel Firmware Support Package (FSP) file
+    """Intel Firmware Support Package (FSP) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
index 434b0f1..9bcac79 100644 (file)
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_fsp_m(Entry_blob_ext):
-    """Entry containing Intel Firmware Support Package (FSP) memory init
+    """Intel Firmware Support Package (FSP) memory init
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
index 564e122..1d5046d 100644 (file)
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_fsp_s(Entry_blob_ext):
-    """Entry containing Intel Firmware Support Package (FSP) silicon init
+    """Intel Firmware Support Package (FSP) silicon init
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
index df0c5fb..80d95cc 100644 (file)
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_fsp_t(Entry_blob_ext):
-    """Entry containing Intel Firmware Support Package (FSP) temp ram init
+    """Intel Firmware Support Package (FSP) temp ram init
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
index 1a0e481..903d39b 100644 (file)
@@ -13,7 +13,7 @@ from dtoc import fdt_util
 from patman import tools
 
 class Entry_intel_ifwi(Entry_blob_ext):
-    """Entry containing an Intel Integrated Firmware Image (IFWI) file
+    """Intel Integrated Firmware Image (IFWI) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry. This is either the
@@ -37,10 +37,10 @@ class Entry_intel_ifwi(Entry_blob_ext):
     sub-partition (and optional entry name).
 
     Properties for subnodes:
-        ifwi-subpart - sub-parition to put this entry into, e.g. "IBBP"
-        ifwi-entry - entry name t use, e.g. "IBBL"
-        ifwi-replace - if present, indicates that the item should be replaced
-            in the IFWI. Otherwise it is added.
+        - ifwi-subpart: sub-parition to put this entry into, e.g. "IBBP"
+        - ifwi-entry: entry name t use, e.g. "IBBL"
+        - ifwi-replace: if present, indicates that the item should be replaced
+          in the IFWI. Otherwise it is added.
 
     See README.x86 for information about x86 binary blobs.
     """
index a6fe542..b93ebab 100644 (file)
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_me(Entry_blob_ext):
-    """Entry containing an Intel Management Engine (ME) file
+    """Intel Management Engine (ME) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
index ccbb046..bb8b26f 100644 (file)
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_mrc(Entry_blob_ext):
-    """Entry containing an Intel Memory Reference Code (MRC) file
+    """Intel Memory Reference Code (MRC) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
index 5ead08b..9112730 100644 (file)
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_refcode(Entry_blob_ext):
-    """Entry containing an Intel Reference Code file
+    """Intel Reference Code file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
index 2a98c12..8afd576 100644 (file)
@@ -7,7 +7,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_vbt(Entry_blob_ext):
-    """Entry containing an Intel Video BIOS Table (VBT) file
+    """Intel Video BIOS Table (VBT) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
index a103f1c..51e6465 100644 (file)
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_vga(Entry_blob_ext):
-    """Entry containing an Intel Video Graphics Adaptor (VGA) file
+    """Intel Video Graphics Adaptor (VGA) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
index 8fddc88..e499775 100644 (file)
@@ -12,14 +12,14 @@ from dtoc import fdt_util
 from patman import tools
 
 class Entry_mkimage(Entry):
-    """Entry containing a binary produced by mkimage
+    """Binary produced by mkimage
 
     Properties / Entry arguments:
         - datafile: Filename for -d argument
         - args: Other arguments to pass
 
     The data passed to mkimage is collected from subnodes of the mkimage node,
-    e.g.:
+    e.g.::
 
         mkimage {
             args = "-n test -T imximage";
@@ -36,6 +36,7 @@ class Entry_mkimage(Entry):
         super().__init__(section, etype, node)
         self._args = fdt_util.GetString(self._node, 'args').split(' ')
         self._mkimage_entries = OrderedDict()
+        self.align_default = None
         self._ReadSubnodes()
 
     def ObtainContents(self):
index 93f8787..a9bee3c 100644 (file)
@@ -7,7 +7,7 @@
 from binman.etype.blob_named_by_arg import Entry_blob_named_by_arg
 
 class Entry_scp(Entry_blob_named_by_arg):
-    """Entry containing a System Control Processor (SCP) firmware blob
+    """System Control Processor (SCP) firmware blob
 
     Properties / Entry arguments:
         - scp-path: Filename of file to read into the entry, typically scp.bin
index 1ceadef..c3bac02 100644 (file)
@@ -22,11 +22,13 @@ from patman.tools import ToHexSize
 class Entry_section(Entry):
     """Entry that contains other entries
 
-    Properties / Entry arguments: (see binman README for more information)
+    Properties / Entry arguments: (see binman README for more information):
         pad-byte: Pad byte to use when padding
         sort-by-offset: True if entries should be sorted by offset, False if
-            they must be in-order in the device tree description
+        they must be in-order in the device tree description
+
         end-at-4gb: Used to build an x86 ROM which ends at 4GB (2^32)
+
         skip-at-start: Number of bytes before the first entry starts. These
             effectively adjust the starting offset of entries. For example,
             if this is 16, then the first entry would start at 16. An entry
@@ -34,6 +36,8 @@ class Entry_section(Entry):
             file, since the first 16 bytes are skipped when writing.
         name-prefix: Adds a prefix to the name of every entry in the section
             when writing out the map
+        align_default: Default alignment for this section, if no alignment is
+            given in the entry
 
     Properties:
         allow_missing: True if this section permits external blobs to be
@@ -74,6 +78,7 @@ class Entry_section(Entry):
             if self._skip_at_start is None:
                 self._skip_at_start = 0
         self._name_prefix = fdt_util.GetString(self._node, 'name-prefix')
+        self.align_default = fdt_util.GetInt(self._node, 'align-default', 0)
         filename = fdt_util.GetString(self._node, 'filename')
         if filename:
             self._filename = filename
@@ -84,7 +89,8 @@ class Entry_section(Entry):
         for node in self._node.subnodes:
             if node.name.startswith('hash') or node.name.startswith('signature'):
                 continue
-            entry = Entry.Create(self, node)
+            entry = Entry.Create(self, node,
+                                 expanded=self.GetImage().use_expanded)
             entry.ReadNode()
             entry.SetPrefix(self._name_prefix)
             self._entries[node.name] = entry
@@ -126,12 +132,6 @@ class Entry_section(Entry):
         return True
 
     def ExpandEntries(self):
-        """Expand out any entries which have calculated sub-entries
-
-        Some entries are expanded out at runtime, e.g. 'files', which produces
-        a section containing a list of files. Process these entries so that
-        this information is added to the device tree.
-        """
         super().ExpandEntries()
         for entry in self._entries.values():
             entry.ExpandEntries()
@@ -183,7 +183,7 @@ class Entry_section(Entry):
 
         return data
 
-    def _BuildSectionData(self):
+    def _BuildSectionData(self, required):
         """Build the contents of a section
 
         This places all entries at the right place, dealing with padding before
@@ -191,13 +191,20 @@ class Entry_section(Entry):
         pad-before and pad-after properties in the section items) since that is
         handled by the parent section.
 
+        Args:
+            required: True if the data must be present, False if it is OK to
+                return None
+
         Returns:
             Contents of the section (bytes)
         """
         section_data = b''
 
         for entry in self._entries.values():
-            data = self.GetPaddedDataForEntry(entry, entry.GetData())
+            entry_data = entry.GetData(required)
+            if not required and entry_data is None:
+                return None
+            data = self.GetPaddedDataForEntry(entry, entry_data)
             # Handle empty space before the entry
             pad = (entry.offset or 0) - self._skip_at_start - len(section_data)
             if pad > 0:
@@ -229,18 +236,24 @@ class Entry_section(Entry):
             data = self.GetData()
         return section.GetPaddedDataForEntry(self, data)
 
-    def GetData(self):
+    def GetData(self, required=True):
         """Get the contents of an entry
 
         This builds the contents of the section, stores this as the contents of
         the section and returns it
 
+        Args:
+            required: True if the data must be present, False if it is OK to
+                return None
+
         Returns:
             bytes content of the section, made up for all all of its subentries.
             This excludes any padding. If the section is compressed, the
             compressed data is returned
         """
-        data = self._BuildSectionData()
+        data = self._BuildSectionData(required)
+        if data is None:
+            return None
         self.SetContents(data)
         return data
 
@@ -266,7 +279,7 @@ class Entry_section(Entry):
             self._SortEntries()
         self._ExpandEntries()
 
-        data = self._BuildSectionData()
+        data = self._BuildSectionData(True)
         self.SetContents(data)
 
         self.CheckSize()
@@ -363,16 +376,20 @@ class Entry_section(Entry):
     def GetEntries(self):
         return self._entries
 
-    def GetContentsByPhandle(self, phandle, source_entry):
+    def GetContentsByPhandle(self, phandle, source_entry, required):
         """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.
+        associated with it. Then it returns the contents of that entry.
+
+        The node must be a direct subnode of this section.
 
         Args:
             phandle: Phandle to look up (integer)
             source_entry: Entry containing that phandle (used for error
                 reporting)
+            required: True if the data must be present, False if it is OK to
+                return None
 
         Returns:
             data from associated entry (as a string), or None if not found
@@ -382,7 +399,7 @@ class Entry_section(Entry):
             source_entry.Raise("Cannot find node for phandle %d" % phandle)
         for entry in self._entries.values():
             if entry._node == node:
-                return entry.GetData()
+                return entry.GetData(required)
         source_entry.Raise("Cannot find entry for node '%s'" % node.name)
 
     def LookupSymbol(self, sym_name, optional, msg, base_addr, entries=None):
index a69c2a4..45dfcc4 100644 (file)
@@ -25,7 +25,7 @@ class Entry_text(Entry):
         <text>: The text to place in the entry (overrides the above mechanism).
             This is useful when the text is constant.
 
-    Example node:
+    Example node::
 
         text {
             size = <50>;
@@ -38,7 +38,7 @@ class Entry_text(Entry):
 
     and binman will insert that string into the entry.
 
-    It is also possible to put the string directly in the node:
+    It is also possible to put the string directly in the node::
 
         text {
             size = <8>;
@@ -46,7 +46,7 @@ class Entry_text(Entry):
             message = "a message directly in the node"
         };
 
-    or just:
+    or just::
 
         text {
             size = <8>;
index 4767197..e8d180a 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright (c) 2016 Google, Inc
 # Written by Simon Glass <sjg@chromium.org>
 #
-# Entry-type module for U-Boot binary
+# Entry-type module for the expanded U-Boot binary
 #
 
 from binman.entry import Entry
@@ -16,14 +16,16 @@ class Entry_u_boot(Entry_blob):
 
     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.
+    blob at the end of it.
 
     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.
+
+    Note that this entry is automatically replaced with u-boot-expanded unless
+    --no-expanded is used or the node has a 'no-expanded' property.
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
index 66a9db5..554b3b2 100644 (file)
@@ -19,9 +19,9 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob_dtb):
     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
+    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.
+    it available to u-boot-ucode.
     """
     def __init__(self, section, etype, node):
         # Put this here to allow entry-docs and help to work without libfdt
diff --git a/tools/binman/etype/u_boot_expanded.py b/tools/binman/etype/u_boot_expanded.py
new file mode 100644 (file)
index 0000000..8797824
--- /dev/null
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for U-Boot binary
+#
+
+from binman.etype.blob_phase import Entry_blob_phase
+
+class Entry_u_boot_expanded(Entry_blob_phase):
+    """U-Boot flat binary broken out into its component parts
+
+    This is a section containing the U-Boot binary and a devicetree. Using this
+    entry type automatically creates this section, with the following entries
+    in it:
+
+       u-boot-nodtb
+       u-boot-dtb
+
+    Having the devicetree separate allows binman to update it in the final
+    image, so that the entries positions are provided to the running U-Boot.
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node, 'u-boot', 'u-boot-dtb', False)
index e84df49..347ba7d 100644 (file)
@@ -12,13 +12,13 @@ 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')
+        - filename: Filename to include (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).
+    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, normally expands to a
+    section containing u-boot and u-boot-dtb
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
index d66e461..6f79bf5 100644 (file)
@@ -30,6 +30,9 @@ class Entry_u_boot_spl(Entry_blob):
 
     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.
+
+    Note that this entry is automatically replaced with u-boot-spl-expanded
+    unless --no-expanded is used or the node has a 'no-expanded' property.
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
index df15cd2..18c5596 100644 (file)
@@ -18,13 +18,16 @@ class Entry_u_boot_spl_bss_pad(Entry_blob):
     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.
+    This holds the padding added after the SPL binary to cover the BSS (Block
+    Started by Symbol) region. This region holds the various variables 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 contents of this entry will a certain number of zero bytes, determined
+    by __bss_size
 
     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.
diff --git a/tools/binman/etype/u_boot_spl_expanded.py b/tools/binman/etype/u_boot_spl_expanded.py
new file mode 100644 (file)
index 0000000..8e138e6
--- /dev/null
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for expanded U-Boot SPL binary
+#
+
+from patman import tout
+
+from binman import state
+from binman.etype.blob_phase import Entry_blob_phase
+
+class Entry_u_boot_spl_expanded(Entry_blob_phase):
+    """U-Boot SPL flat binary broken out into its component parts
+
+    Properties / Entry arguments:
+        - spl-dtb: Controls whether this entry is selected (set to 'y' or '1' to
+            select)
+
+    This is a section containing the U-Boot binary, BSS padding if needed and a
+    devicetree. Using this entry type automatically creates this section, with
+    the following entries in it:
+
+       u-boot-spl-nodtb
+       u-boot-spl-bss-pad
+       u-boot-dtb
+
+    Having the devicetree separate allows binman to update it in the final
+    image, so that the entries positions are provided to the running U-Boot.
+
+    This entry is selected based on the value of the 'spl-dtb' entryarg. If
+    this is non-empty (and not 'n' or '0') then this expanded entry is selected.
+    """
+    def __init__(self, section, etype, node):
+        bss_pad = state.GetEntryArgBool('spl-bss-pad')
+        super().__init__(section, etype, node, 'u-boot-spl', 'u-boot-spl-dtb',
+                         bss_pad)
+
+    @classmethod
+    def UseExpanded(cls, node, etype, new_etype):
+        val = state.GetEntryArgBool('spl-dtb')
+        tout.DoOutput(tout.INFO if val else tout.DETAIL,
+                      "Node '%s': etype '%s': %s %sselected" %
+                      (node.path, etype, new_etype, '' if val else 'not '))
+        return val
index c154cfd..316b381 100644 (file)
@@ -5,6 +5,7 @@
 # Entry-type module for 'u-boot-spl-nodtb.bin'
 #
 
+from binman import elf
 from binman.entry import Entry
 from binman.etype.blob import Entry_blob
 
@@ -12,17 +13,30 @@ 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')
+        - filename: Filename to include (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).
+    a device tree to operate on your platform. You can add a u-boot-spl-dtb
+    entry after this one, or use a u-boot-spl entry instead' which normally
+    expands to a section containing u-boot-spl-dtb, u-boot-spl-bss-pad and
+    u-boot-spl-dtb
+
+    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):
         super().__init__(section, etype, node)
+        self.elf_fname = 'spl/u-boot-spl'
 
     def GetDefaultFilename(self):
         return 'spl/u-boot-spl-nodtb.bin'
+
+    def WriteSymbols(self, section):
+        elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage())
index 02287ab..0c575df 100644 (file)
@@ -30,6 +30,9 @@ class Entry_u_boot_tpl(Entry_blob):
 
     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.
+
+    Note that this entry is automatically replaced with u-boot-tpl-expanded
+    unless --no-expanded is used or the node has a 'no-expanded' property.
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
diff --git a/tools/binman/etype/u_boot_tpl_bss_pad.py b/tools/binman/etype/u_boot_tpl_bss_pad.py
new file mode 100644 (file)
index 0000000..521b24a
--- /dev/null
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for BSS padding for tpl/u-boot-tpl.bin. This padding
+# can be added after the TPL binary to ensure that anything concatenated
+# to it will appear to TPL to be at the end of BSS rather than the start.
+#
+
+from binman import elf
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
+from patman import tools
+
+class Entry_u_boot_tpl_bss_pad(Entry_blob):
+    """U-Boot TPL binary padded with a BSS region
+
+    Properties / Entry arguments:
+        None
+
+    This holds the padding added after the TPL binary to cover the BSS (Block
+    Started by Symbol) region. This region holds the various variables used by
+    TPL. It is set to 0 by TPL when it starts up. If you want to append data to
+    the TPL 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 contents of this entry will a certain number of zero bytes, determined
+    by __bss_size
+
+    The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+    binman uses that to look up the BSS address.
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node)
+
+    def ObtainContents(self):
+        fname = tools.GetInputFilename('tpl/u-boot-tpl')
+        bss_size = elf.GetSymbolAddress(fname, '__bss_size')
+        if not bss_size:
+            self.Raise('Expected __bss_size symbol in tpl/u-boot-tpl')
+        self.SetContents(tools.GetBytes(0, bss_size))
+        return True
diff --git a/tools/binman/etype/u_boot_tpl_expanded.py b/tools/binman/etype/u_boot_tpl_expanded.py
new file mode 100644 (file)
index 0000000..15cdac4
--- /dev/null
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for expanded U-Boot TPL binary
+#
+
+from patman import tout
+
+from binman import state
+from binman.etype.blob_phase import Entry_blob_phase
+
+class Entry_u_boot_tpl_expanded(Entry_blob_phase):
+    """U-Boot TPL flat binary broken out into its component parts
+
+    Properties / Entry arguments:
+        - tpl-dtb: Controls whether this entry is selected (set to 'y' or '1' to
+            select)
+
+    This is a section containing the U-Boot binary, BSS padding if needed and a
+    devicetree. Using this entry type automatically creates this section, with
+    the following entries in it:
+
+       u-boot-tpl-nodtb
+       u-boot-tpl-bss-pad
+       u-boot-dtb
+
+    Having the devicetree separate allows binman to update it in the final
+    image, so that the entries positions are provided to the running U-Boot.
+
+    This entry is selected based on the value of the 'tpl-dtb' entryarg. If
+    this is non-empty (and not 'n' or '0') then this expanded entry is selected.
+    """
+    def __init__(self, section, etype, node):
+        bss_pad = state.GetEntryArgBool('tpl-bss-pad')
+        super().__init__(section, etype, node, 'u-boot-tpl', 'u-boot-tpl-dtb',
+                         bss_pad)
+
+    @classmethod
+    def UseExpanded(cls, node, etype, new_etype):
+        val = state.GetEntryArgBool('tpl-dtb')
+        tout.DoOutput(tout.INFO if val else tout.DETAIL,
+                      "Node '%s': etype '%s': %s %sselected" %
+                      (node.path, etype, new_etype, '' if val else 'not '))
+        return val
diff --git a/tools/binman/etype/u_boot_tpl_nodtb.py b/tools/binman/etype/u_boot_tpl_nodtb.py
new file mode 100644 (file)
index 0000000..98f3853
--- /dev/null
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for 'u-boot-tpl-nodtb.bin'
+#
+
+from binman import elf
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
+
+class Entry_u_boot_tpl_nodtb(Entry_blob):
+    """TPL binary without device tree appended
+
+    Properties / Entry arguments:
+        - filename: Filename to include (default 'tpl/u-boot-tpl-nodtb.bin')
+
+    This is the U-Boot TPL binary, It does not include a device tree blob at
+    the end of it so may not be able to work without it, assuming TPL needs
+    a device tree to operate on your platform. You can add a u-boot-tpl-dtb
+    entry after this one, or use a u-boot-tpl entry instead, which normally
+    expands to a section containing u-boot-tpl-dtb, u-boot-tpl-bss-pad and
+    u-boot-tpl-dtb
+
+    TPL 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):
+        super().__init__(section, etype, node)
+        self.elf_fname = 'tpl/u-boot-tpl'
+
+    def GetDefaultFilename(self):
+        return 'tpl/u-boot-tpl-nodtb.bin'
+
+    def WriteSymbols(self, section):
+        elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage())
index 92d2fc6..20be22a 100644 (file)
@@ -26,7 +26,7 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob):
     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.
+    complicated. Otherwise it is the same as the u-boot entry.
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
index eba5351..c0a6a28 100644 (file)
@@ -9,12 +9,13 @@
 from collections import OrderedDict
 import os
 
-from binman.entry import Entry, EntryArg
+from binman.entry import EntryArg
+from binman.etype.collection import Entry_collection
 
 from dtoc import fdt_util
 from patman import tools
 
-class Entry_vblock(Entry):
+class Entry_vblock(Entry_collection):
     """An entry which contains a Chromium OS verified boot block
 
     Properties / Entry arguments:
@@ -37,9 +38,6 @@ class Entry_vblock(Entry):
     """
     def __init__(self, section, etype, node):
         super().__init__(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),
@@ -49,15 +47,21 @@ class Entry_vblock(Entry):
             EntryArg('kernelkey', str),
             EntryArg('preamble-flags', int)])
 
-    def GetVblock(self):
+    def GetVblock(self, required):
+        """Get the contents of this entry
+
+        Args:
+            required: True if the data must be present, False if it is OK to
+                return None
+
+        Returns:
+            bytes content of the entry, which is the signed vblock for the
+                provided data
+        """
         # Join up the data files to be signed
-        input_data = b''
-        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
+        input_data = self.GetContents(required)
+        if input_data is None:
+            return None
 
         uniq = self.GetUniqueName()
         output_fname = tools.GetOutputFilename('vblock.%s' % uniq)
@@ -79,13 +83,13 @@ class Entry_vblock(Entry):
         return tools.ReadFile(output_fname)
 
     def ObtainContents(self):
-        data = self.GetVblock()
-        if data is False:
+        data = self.GetVblock(False)
+        if data is None:
             return False
         self.SetContents(data)
         return True
 
     def ProcessContents(self):
         # The blob may have changed due to WriteSymbols()
-        data = self.GetVblock()
+        data = self.GetVblock(True)
         return self.ProcessContentsUpdate(data)
index 814e91d..89fe661 100644 (file)
@@ -305,7 +305,8 @@ class TestFunctional(unittest.TestCase):
 
     def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
                     entry_args=None, images=None, use_real_dtb=False,
-                    verbosity=None, allow_missing=False, extra_indirs=None):
+                    use_expanded=False, verbosity=None, allow_missing=False,
+                    extra_indirs=None):
         """Run binman with a given test file
 
         Args:
@@ -322,6 +323,8 @@ 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.
+            use_expanded: True to use expanded entries where available, e.g.
+                'u-boot-expanded' instead of 'u-boot'
             verbosity: Verbosity level to use (0-3, None=don't set it)
             allow_missing: Set the '--allow-missing' flag so that missing
                 external binaries just produce a warning instead of an error
@@ -344,6 +347,8 @@ class TestFunctional(unittest.TestCase):
             args.append('-u')
         if not use_real_dtb:
             args.append('--fake-dtb')
+        if not use_expanded:
+            args.append('--no-expanded')
         if entry_args:
             for arg, value in entry_args.items():
                 args.append('-a%s=%s' % (arg, value))
@@ -403,9 +408,9 @@ class TestFunctional(unittest.TestCase):
         dtb.Pack()
         return dtb.GetContents()
 
-    def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
-                       update_dtb=False, entry_args=None, reset_dtbs=True,
-                       extra_indirs=None):
+    def _DoReadFileDtb(self, fname, use_real_dtb=False, use_expanded=False,
+                       map=False, update_dtb=False, entry_args=None,
+                       reset_dtbs=True, extra_indirs=None):
         """Run binman and return the resulting image
 
         This runs binman with a given test file and then reads the resulting
@@ -420,6 +425,8 @@ 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.
+            use_expanded: True to use expanded entries where available, e.g.
+                'u-boot-expanded' instead of 'u-boot'
             map: True to output map files for the images
             update_dtb: Update the offset and size of each entry in the device
                 tree before packing it into the image
@@ -454,7 +461,7 @@ class TestFunctional(unittest.TestCase):
         try:
             retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
                     entry_args=entry_args, use_real_dtb=use_real_dtb,
-                    extra_indirs=extra_indirs)
+                    use_expanded=use_expanded, extra_indirs=extra_indirs)
             self.assertEqual(0, retcode)
             out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
 
@@ -624,7 +631,7 @@ class TestFunctional(unittest.TestCase):
     def testFullHelp(self):
         """Test that the full help is displayed with -H"""
         result = self._RunBinman('-H')
-        help_file = os.path.join(self._binman_dir, 'README')
+        help_file = os.path.join(self._binman_dir, 'README.rst')
         # Remove possible extraneous strings
         extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
         gothelp = result.stdout.replace(extra, '')
@@ -637,7 +644,7 @@ class TestFunctional(unittest.TestCase):
         try:
             command.test_result = command.CommandResult()
             result = self._DoBinman('-H')
-            help_file = os.path.join(self._binman_dir, 'README')
+            help_file = os.path.join(self._binman_dir, 'README.rst')
         finally:
             command.test_result = None
 
@@ -652,7 +659,7 @@ class TestFunctional(unittest.TestCase):
         """Test that we can run it with a specific board"""
         self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
         TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
-        result = self._DoBinman('build', '-b', 'sandbox')
+        result = self._DoBinman('build', '-n', '-b', 'sandbox')
         self.assertEqual(0, result)
 
     def testNeedBoard(self):
@@ -1337,21 +1344,50 @@ class TestFunctional(unittest.TestCase):
         data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
         self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
 
-    def testSymbols(self):
-        """Test binman can assign symbols embedded in U-Boot"""
+    def checkSymbols(self, dts, base_data, u_boot_offset, entry_args=None,
+                     use_expanded=False):
+        """Check the image contains the expected symbol values
+
+        Args:
+            dts: Device tree file to use for test
+            base_data: Data before and after 'u-boot' section
+            u_boot_offset: Offset of 'u-boot' section in image
+            entry_args: Dict of entry args to supply to binman
+                key: arg name
+                value: value of that arg
+            use_expanded: True to use expanded entries where available, e.g.
+                'u-boot-expanded' instead of 'u-boot'
+        """
         elf_fname = self.ElfTestFile('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_offset'].address, addr)
+        self.assertEqual(syms['_binman_u_boot_spl_any_prop_offset'].address,
+                         addr)
 
         self._SetupSplElf('u_boot_binman_syms')
-        data = self._DoReadFile('053_symbols.dts')
-        sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
-        expected = (sym_values + U_BOOT_SPL_DATA[20:] +
+        data = self._DoReadFileDtb(dts, entry_args=entry_args,
+                                   use_expanded=use_expanded)[0]
+        # The image should contain the symbols from u_boot_binman_syms.c
+        # Note that image_pos is adjusted by the base address of the image,
+        # which is 0x10 in our test image
+        sym_values = struct.pack('<LQLL', 0x00,
+                                 u_boot_offset + len(U_BOOT_DATA),
+                                 0x10 + u_boot_offset, 0x04)
+        expected = (sym_values + base_data[20:] +
                     tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
-                    U_BOOT_SPL_DATA[20:])
+                    base_data[20:])
         self.assertEqual(expected, data)
 
+    def testSymbols(self):
+        """Test binman can assign symbols embedded in U-Boot"""
+        self.checkSymbols('053_symbols.dts', U_BOOT_SPL_DATA, 0x18)
+
+    def testSymbolsNoDtb(self):
+        """Test binman can assign symbols embedded in U-Boot SPL"""
+        self.checkSymbols('196_symbols_nodtb.dts',
+                          U_BOOT_SPL_NODTB_DATA + U_BOOT_SPL_DTB_DATA,
+                          0x38)
+
     def testPackUnitAddress(self):
         """Test that we support multiple binaries with the same name"""
         data = self._DoReadFile('054_unit_address.dts')
@@ -1682,7 +1718,7 @@ class TestFunctional(unittest.TestCase):
         """Test we detect a vblock which has no content to sign"""
         with self.assertRaises(ValueError) as e:
             self._DoReadFile('075_vblock_no_content.dts')
-        self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
+        self.assertIn("Node '/binman/vblock': Collection must have a 'content' "
                       'property', str(e.exception))
 
     def testVblockBadPhandle(self):
@@ -4186,18 +4222,7 @@ class TestFunctional(unittest.TestCase):
 
     def testSymbolsSubsection(self):
         """Test binman can assign symbols from a subsection"""
-        elf_fname = self.ElfTestFile('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_offset'].address, addr)
-
-        self._SetupSplElf('u_boot_binman_syms')
-        data = self._DoReadFile('187_symbols_sub.dts')
-        sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
-        expected = (sym_values + U_BOOT_SPL_DATA[20:] +
-                    tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
-                    U_BOOT_SPL_DATA[20:])
-        self.assertEqual(expected, data)
+        self.checkSymbols('187_symbols_sub.dts', U_BOOT_SPL_DATA, 0x18)
 
     def testReadImageEntryArg(self):
         """Test reading an image that would need an entry arg to generate"""
@@ -4245,6 +4270,244 @@ class TestFunctional(unittest.TestCase):
 
         self.assertEquals(U_BOOT_DATA, u_boot.ReadData())
 
+    def testTplNoDtb(self):
+        """Test that an image with tpl/u-boot-tpl-nodtb.bin can be created"""
+        data = self._DoReadFile('192_u_boot_tpl_nodtb.dts')
+        self.assertEqual(U_BOOT_TPL_NODTB_DATA,
+                         data[:len(U_BOOT_TPL_NODTB_DATA)])
+
+    def testTplBssPad(self):
+        """Test that we can pad TPL's BSS with zeros"""
+        # ELF file with a '__bss_size' symbol
+        self._SetupTplElf()
+        data = self._DoReadFile('193_tpl_bss_pad.dts')
+        self.assertEqual(U_BOOT_TPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
+                         data)
+
+    def testTplBssPadMissing(self):
+        """Test that a missing symbol is detected"""
+        self._SetupTplElf('u_boot_ucode_ptr')
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('193_tpl_bss_pad.dts')
+        self.assertIn('Expected __bss_size symbol in tpl/u-boot-tpl',
+                      str(e.exception))
+
+    def checkDtbSizes(self, data, pad_len, start):
+        """Check the size arguments in a dtb embedded in an image
+
+        Args:
+            data: The image data
+            pad_len: Length of the pad section in the image, in bytes
+            start: Start offset of the devicetree to examine, within the image
+
+        Returns:
+            Size of the devicetree in bytes
+        """
+        dtb_data = data[start:]
+        dtb = fdt.Fdt.FromData(dtb_data)
+        fdt_size = dtb.GetFdtObj().totalsize()
+        dtb.Scan()
+        props = self._GetPropTree(dtb, 'size')
+        self.assertEqual({
+            'size': len(data),
+            'u-boot-spl/u-boot-spl-bss-pad:size': pad_len,
+            'u-boot-spl/u-boot-spl-dtb:size': 801,
+            'u-boot-spl/u-boot-spl-nodtb:size': len(U_BOOT_SPL_NODTB_DATA),
+            'u-boot-spl:size': 860,
+            'u-boot-tpl:size': len(U_BOOT_TPL_DATA),
+            'u-boot/u-boot-dtb:size': 781,
+            'u-boot/u-boot-nodtb:size': len(U_BOOT_NODTB_DATA),
+            'u-boot:size': 827,
+            }, props)
+        return fdt_size
+
+    def testExpanded(self):
+        """Test that an expanded entry type is selected when needed"""
+        self._SetupSplElf()
+        self._SetupTplElf()
+
+        # SPL has a devicetree, TPL does not
+        entry_args = {
+            'spl-dtb': '1',
+            'spl-bss-pad': 'y',
+            'tpl-dtb': '',
+        }
+        self._DoReadFileDtb('194_fdt_incl.dts', use_expanded=True,
+                            entry_args=entry_args)
+        image = control.images['image']
+        entries = image.GetEntries()
+        self.assertEqual(3, len(entries))
+
+        # First, u-boot, which should be expanded into u-boot-nodtb and dtb
+        self.assertIn('u-boot', entries)
+        entry = entries['u-boot']
+        self.assertEqual('u-boot-expanded', entry.etype)
+        subent = entry.GetEntries()
+        self.assertEqual(2, len(subent))
+        self.assertIn('u-boot-nodtb', subent)
+        self.assertIn('u-boot-dtb', subent)
+
+        # Second, u-boot-spl, which should be expanded into three parts
+        self.assertIn('u-boot-spl', entries)
+        entry = entries['u-boot-spl']
+        self.assertEqual('u-boot-spl-expanded', entry.etype)
+        subent = entry.GetEntries()
+        self.assertEqual(3, len(subent))
+        self.assertIn('u-boot-spl-nodtb', subent)
+        self.assertIn('u-boot-spl-bss-pad', subent)
+        self.assertIn('u-boot-spl-dtb', subent)
+
+        # Third, u-boot-tpl, which should be not be expanded, since TPL has no
+        # devicetree
+        self.assertIn('u-boot-tpl', entries)
+        entry = entries['u-boot-tpl']
+        self.assertEqual('u-boot-tpl', entry.etype)
+        self.assertEqual(None, entry.GetEntries())
+
+    def testExpandedTpl(self):
+        """Test that an expanded entry type is selected for TPL when needed"""
+        self._SetupTplElf()
+
+        entry_args = {
+            'tpl-bss-pad': 'y',
+            'tpl-dtb': 'y',
+        }
+        self._DoReadFileDtb('195_fdt_incl_tpl.dts', use_expanded=True,
+                            entry_args=entry_args)
+        image = control.images['image']
+        entries = image.GetEntries()
+        self.assertEqual(1, len(entries))
+
+        # We only have u-boot-tpl, which be expanded
+        self.assertIn('u-boot-tpl', entries)
+        entry = entries['u-boot-tpl']
+        self.assertEqual('u-boot-tpl-expanded', entry.etype)
+        subent = entry.GetEntries()
+        self.assertEqual(3, len(subent))
+        self.assertIn('u-boot-tpl-nodtb', subent)
+        self.assertIn('u-boot-tpl-bss-pad', subent)
+        self.assertIn('u-boot-tpl-dtb', subent)
+
+    def testExpandedNoPad(self):
+        """Test an expanded entry without BSS pad enabled"""
+        self._SetupSplElf()
+        self._SetupTplElf()
+
+        # SPL has a devicetree, TPL does not
+        entry_args = {
+            'spl-dtb': 'something',
+            'spl-bss-pad': 'n',
+            'tpl-dtb': '',
+        }
+        self._DoReadFileDtb('194_fdt_incl.dts', use_expanded=True,
+                            entry_args=entry_args)
+        image = control.images['image']
+        entries = image.GetEntries()
+
+        # Just check u-boot-spl, which should be expanded into two parts
+        self.assertIn('u-boot-spl', entries)
+        entry = entries['u-boot-spl']
+        self.assertEqual('u-boot-spl-expanded', entry.etype)
+        subent = entry.GetEntries()
+        self.assertEqual(2, len(subent))
+        self.assertIn('u-boot-spl-nodtb', subent)
+        self.assertIn('u-boot-spl-dtb', subent)
+
+    def testExpandedTplNoPad(self):
+        """Test that an expanded entry type with padding disabled in TPL"""
+        self._SetupTplElf()
+
+        entry_args = {
+            'tpl-bss-pad': '',
+            'tpl-dtb': 'y',
+        }
+        self._DoReadFileDtb('195_fdt_incl_tpl.dts', use_expanded=True,
+                            entry_args=entry_args)
+        image = control.images['image']
+        entries = image.GetEntries()
+        self.assertEqual(1, len(entries))
+
+        # We only have u-boot-tpl, which be expanded
+        self.assertIn('u-boot-tpl', entries)
+        entry = entries['u-boot-tpl']
+        self.assertEqual('u-boot-tpl-expanded', entry.etype)
+        subent = entry.GetEntries()
+        self.assertEqual(2, len(subent))
+        self.assertIn('u-boot-tpl-nodtb', subent)
+        self.assertIn('u-boot-tpl-dtb', subent)
+
+    def testFdtInclude(self):
+        """Test that an Fdt is update within all binaries"""
+        self._SetupSplElf()
+        self._SetupTplElf()
+
+        # SPL has a devicetree, TPL does not
+        self.maxDiff = None
+        entry_args = {
+            'spl-dtb': '1',
+            'spl-bss-pad': 'y',
+            'tpl-dtb': '',
+        }
+        # Build the image. It includes two separate devicetree binaries, each
+        # with their own contents, but all contain the binman definition.
+        data = self._DoReadFileDtb(
+            '194_fdt_incl.dts', use_real_dtb=True, use_expanded=True,
+            update_dtb=True, entry_args=entry_args)[0]
+        pad_len = 10
+
+        # Check the U-Boot dtb
+        start = len(U_BOOT_NODTB_DATA)
+        fdt_size = self.checkDtbSizes(data, pad_len, start)
+
+        # Now check SPL
+        start += fdt_size + len(U_BOOT_SPL_NODTB_DATA) + pad_len
+        fdt_size = self.checkDtbSizes(data, pad_len, start)
+
+        # TPL has no devicetree
+        start += fdt_size + len(U_BOOT_TPL_DATA)
+        self.assertEqual(len(data), start)
+
+    def testSymbolsExpanded(self):
+        """Test binman can assign symbols in expanded entries"""
+        entry_args = {
+            'spl-dtb': '1',
+        }
+        self.checkSymbols('197_symbols_expand.dts', U_BOOT_SPL_NODTB_DATA +
+                          U_BOOT_SPL_DTB_DATA, 0x38,
+                          entry_args=entry_args, use_expanded=True)
+
+    def testCollection(self):
+        """Test a collection"""
+        data = self._DoReadFile('198_collection.dts')
+        self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA +
+                         tools.GetBytes(0xff, 2) + U_BOOT_NODTB_DATA +
+                         tools.GetBytes(0xfe, 3) + U_BOOT_DTB_DATA,
+                         data)
+
+    def testCollectionSection(self):
+        """Test a collection where a section must be built first"""
+        # Sections never have their contents when GetData() is called, but when
+        # _BuildSectionData() is called with required=True, a section will force
+        # building the contents, producing an error is anything is still
+        # missing.
+        data = self._DoReadFile('199_collection_section.dts')
+        section = U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA
+        self.assertEqual(section + U_BOOT_DATA + tools.GetBytes(0xff, 2) +
+                         section + tools.GetBytes(0xfe, 3) + U_BOOT_DATA,
+                         data)
+
+    def testAlignDefault(self):
+        """Test that default alignment works on sections"""
+        data = self._DoReadFile('200_align_default.dts')
+        expected = (U_BOOT_DATA + tools.GetBytes(0, 8 - len(U_BOOT_DATA)) +
+                    U_BOOT_DATA)
+        # Special alignment for section
+        expected += tools.GetBytes(0, 32 - len(expected))
+        # No alignment within the nested section
+        expected += U_BOOT_DATA + U_BOOT_NODTB_DATA;
+        # Now the final piece, which should be default-aligned
+        expected += tools.GetBytes(0, 88 - len(expected)) + U_BOOT_NODTB_DATA
+        self.assertEqual(expected, data)
 
 if __name__ == "__main__":
     unittest.main()
index e949435..10778f4 100644 (file)
@@ -47,9 +47,23 @@ class Image(section.Entry_section):
             exception). This should be used if the Image is being loaded from
             a file rather than generated. In that case we obviously don't need
             the entry arguments since the contents already exists.
+        use_expanded: True if we are updating the FDT wth entry offsets, etc.
+            and should use the expanded versions of the U-Boot entries.
+            Any entry type that includes a devicetree must put it in a
+            separate entry so that it will be updated. For example. 'u-boot'
+            normally just picks up 'u-boot.bin' which includes the
+            devicetree, but this is not updateable, since it comes into
+            binman as one piece and binman doesn't know that it is actually
+            an executable followed by a devicetree. Of course it could be
+            taught this, but then when reading an image (e.g. 'binman ls')
+            it may need to be able to split the devicetree out of the image
+            in order to determine the location of things. Instead we choose
+            to ignore 'u-boot-bin' in this case, and build it ourselves in
+            binman with 'u-boot-dtb.bin' and 'u-boot.dtb'. See
+            Entry_u_boot_expanded and Entry_blob_phase for details.
     """
     def __init__(self, name, node, copy_to_orig=True, test=False,
-                 ignore_missing=False):
+                 ignore_missing=False, use_expanded=False):
         super().__init__(None, 'section', node, test=test)
         self.copy_to_orig = copy_to_orig
         self.name = 'main-section'
@@ -59,6 +73,7 @@ class Image(section.Entry_section):
         self.fdtmap_data = None
         self.allow_repack = False
         self._ignore_missing = ignore_missing
+        self.use_expanded = use_expanded
         if not test:
             self.ReadNode()
 
diff --git a/tools/binman/index.rst b/tools/binman/index.rst
new file mode 100644 (file)
index 0000000..6eef7b5
--- /dev/null
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Binman
+======
+
+.. toctree::
+   :maxdepth: 2
+
+   README
index fe408ed..5ed94ab 100644 (file)
@@ -7,6 +7,6 @@ setup(name='binman',
       scripts=['binman'],
       packages=['binman', 'binman.etype'],
       package_dir={'binman': ''},
-      package_data={'binman': ['README', 'README.entries']},
+      package_data={'binman': ['README.rst', 'entries.rst']},
       classifiers=['Environment :: Console',
                    'Topic :: Software Development :: Embedded Systems'])
index bb3e36e..dfb1760 100644 (file)
@@ -13,15 +13,20 @@ import os
 from patman import tools
 from patman import tout
 
+# Map an dtb etype to its expected filename
+DTB_TYPE_FNAME = {
+    'u-boot-spl-dtb': 'spl/u-boot-spl.dtb',
+    'u-boot-tpl-dtb': 'tpl/u-boot-tpl.dtb',
+    }
+
 # Records the device-tree files known to binman, keyed by entry type (e.g.
 # 'u-boot-spl-dtb'). These are the output FDT files, which can be updated by
 # binman. They have been copied to <xxx>.out files.
 #
-#   key: entry type
+#   key: entry type (e.g. 'u-boot-dtb)
 #   value: tuple:
 #       Fdt object
 #       Filename
-#       Entry object, or None if not known
 output_fdt_info = {}
 
 # Prefix to add to an fdtmap path to turn it into a path to the /binman node
@@ -118,11 +123,11 @@ def UpdateFdtContents(etype, data):
         etype: Entry type (e.g. 'u-boot-dtb')
         data: Data to replace the DTB with
     """
-    dtb, fname, entry = output_fdt_info[etype]
+    dtb, fname = output_fdt_info[etype]
     dtb_fname = dtb.GetFilename()
     tools.WriteFile(dtb_fname, data)
     dtb = fdt.FdtScan(dtb_fname)
-    output_fdt_info[etype] = [dtb, fname, entry]
+    output_fdt_info[etype] = [dtb, fname]
 
 def SetEntryArgs(args):
     """Set the value of the entry args
@@ -136,12 +141,16 @@ def SetEntryArgs(args):
     global entry_args
 
     entry_args = {}
+    tout.Debug('Processing 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)
+            name, value = m.groups()
+            tout.Debug('   %20s = %s' % (name, value))
+            entry_args[name] = value
+    tout.Debug('Processing entry args done')
 
 def GetEntryArg(name):
     """Get the value of an entry argument
@@ -154,6 +163,19 @@ def GetEntryArg(name):
     """
     return entry_args.get(name)
 
+def GetEntryArgBool(name):
+    """Get the value of an entry argument as a boolean
+
+    Args:
+        name: Name of argument to retrieve
+
+    Returns:
+        False if the entry argument is consider False (empty, '0' or 'n'), else
+            True
+    """
+    val = GetEntryArg(name)
+    return val and val not in ['n', '0']
+
 def Prepare(images, dtb):
     """Get device tree files ready for use
 
@@ -177,22 +199,22 @@ def Prepare(images, dtb):
     main_dtb = dtb
     output_fdt_info.clear()
     fdt_path_prefix = ''
-    output_fdt_info['u-boot-dtb'] = [dtb, 'u-boot.dtb', None]
-    output_fdt_info['u-boot-spl-dtb'] = [dtb, 'spl/u-boot-spl.dtb', None]
-    output_fdt_info['u-boot-tpl-dtb'] = [dtb, 'tpl/u-boot-tpl.dtb', None]
-    if not use_fake_dtb:
+    output_fdt_info['u-boot-dtb'] = [dtb, 'u-boot.dtb']
+    if use_fake_dtb:
+        for etype, fname in DTB_TYPE_FNAME.items():
+            output_fdt_info[etype] = [dtb, fname]
+    else:
         fdt_set = {}
-        for image in images.values():
-            fdt_set.update(image.GetFdts())
-        for etype, other in fdt_set.items():
-            entry, other_fname = other
-            infile = tools.GetInputFilename(other_fname)
-            other_fname_dtb = fdt_util.EnsureCompiled(infile)
-            out_fname = tools.GetOutputFilename('%s.out' %
-                    os.path.split(other_fname)[1])
-            tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb))
-            other_dtb = fdt.FdtScan(out_fname)
-            output_fdt_info[etype] = [other_dtb, out_fname, entry]
+        for etype, fname in DTB_TYPE_FNAME.items():
+            infile = tools.GetInputFilename(fname, allow_missing=True)
+            if infile and os.path.exists(infile):
+                fname_dtb = fdt_util.EnsureCompiled(infile)
+                out_fname = tools.GetOutputFilename('%s.out' %
+                        os.path.split(fname)[1])
+                tools.WriteFile(out_fname, tools.ReadFile(fname_dtb))
+                other_dtb = fdt.FdtScan(out_fname)
+                output_fdt_info[etype] = [other_dtb, out_fname]
+
 
 def PrepareFromLoadedData(image):
     """Get device tree files ready for use with a loaded image
@@ -215,7 +237,7 @@ def PrepareFromLoadedData(image):
     tout.Info('Preparing device trees')
     output_fdt_info.clear()
     fdt_path_prefix = ''
-    output_fdt_info['fdtmap'] = [image.fdtmap_dtb, 'u-boot.dtb', None]
+    output_fdt_info['fdtmap'] = [image.fdtmap_dtb, 'u-boot.dtb']
     main_dtb = None
     tout.Info("   Found device tree type 'fdtmap' '%s'" % image.fdtmap_dtb.name)
     for etype, value in image.GetFdts().items():
@@ -233,7 +255,7 @@ def PrepareFromLoadedData(image):
         if 'multiple-images' in image_node.props:
             image_node = dtb.GetNode('/binman/%s' % image.image_node)
         fdt_path_prefix = image_node.path
-        output_fdt_info[etype] = [dtb, None, entry]
+        output_fdt_info[etype] = [dtb, None]
     tout.Info("   FDT path prefix '%s'" % fdt_path_prefix)
 
 
@@ -268,12 +290,11 @@ def GetUpdateNodes(node, for_repack=False):
             is node, SPL and TPL)
     """
     yield node
-    for dtb, fname, entry in output_fdt_info.values():
+    for entry_type, (dtb, fname) in output_fdt_info.items():
         if dtb != node.GetFdt():
-            if for_repack and entry.etype != 'u-boot-dtb':
+            if for_repack and entry_type != 'u-boot-dtb':
                 continue
             other_node = dtb.GetNode(fdt_path_prefix + node.path)
-            #print('   try', fdt_path_prefix + node.path, other_node)
             if other_node:
                 yield other_node
 
index 8af5751..2965809 100644 (file)
@@ -10,7 +10,7 @@
                };
 
                u-boot {
-                       offset = <24>;
+                       offset = <0x18>;
                };
 
                u-boot-spl2 {
index dfc84af..0a4ab3f 100644 (file)
@@ -21,7 +21,6 @@
 
                section {
                        u-boot-tpl {
-                               type = "u-boot-tpl";
                        };
                };
        };
index 72ca447..9d7dc51 100644 (file)
@@ -24,7 +24,6 @@
 
                section {
                        u-boot-tpl {
-                               type = "u-boot-tpl";
                        };
                };
        };
diff --git a/tools/binman/test/192_u_boot_tpl_nodtb.dts b/tools/binman/test/192_u_boot_tpl_nodtb.dts
new file mode 100644 (file)
index 0000000..94cef39
--- /dev/null
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u-boot-tpl-nodtb {
+               };
+       };
+};
diff --git a/tools/binman/test/193_tpl_bss_pad.dts b/tools/binman/test/193_tpl_bss_pad.dts
new file mode 100644 (file)
index 0000000..f5c2db0
--- /dev/null
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u-boot-tpl {
+               };
+
+               u-boot-tpl-bss-pad {
+               };
+
+               u-boot {
+               };
+       };
+};
diff --git a/tools/binman/test/194_fdt_incl.dts b/tools/binman/test/194_fdt_incl.dts
new file mode 100644 (file)
index 0000000..b14c8ff
--- /dev/null
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u-boot {
+               };
+               u-boot-spl {
+               };
+               u-boot-tpl {
+               };
+       };
+};
diff --git a/tools/binman/test/195_fdt_incl_tpl.dts b/tools/binman/test/195_fdt_incl_tpl.dts
new file mode 100644 (file)
index 0000000..3756ac4
--- /dev/null
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u-boot-tpl {
+               };
+       };
+};
diff --git a/tools/binman/test/196_symbols_nodtb.dts b/tools/binman/test/196_symbols_nodtb.dts
new file mode 100644 (file)
index 0000000..5c900d6
--- /dev/null
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               pad-byte = <0xff>;
+               u-boot-spl-nodtb {
+               };
+               u-boot-spl-dtb {
+               };
+
+               u-boot {
+                       offset = <0x38>;
+               };
+
+               u-boot-spl2 {
+                       type = "u-boot-spl-nodtb";
+               };
+               u-boot-spl-dtb2 {
+                       type = "u-boot-spl-dtb";
+               };
+       };
+};
diff --git a/tools/binman/test/197_symbols_expand.dts b/tools/binman/test/197_symbols_expand.dts
new file mode 100644 (file)
index 0000000..8aee76d
--- /dev/null
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               pad-byte = <0xff>;
+               u-boot-spl {
+               };
+
+               u-boot {
+                       offset = <0x38>;
+                       no-expanded;
+               };
+
+               u-boot-spl2 {
+                       type = "u-boot-spl";
+               };
+       };
+};
diff --git a/tools/binman/test/198_collection.dts b/tools/binman/test/198_collection.dts
new file mode 100644 (file)
index 0000000..484a1b0
--- /dev/null
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               collection {
+                       content = <&u_boot_nodtb &dtb>;
+               };
+               fill {
+                       size = <2>;
+                       fill-byte = [ff];
+               };
+               u_boot_nodtb: u-boot-nodtb {
+               };
+               fill2 {
+                       type = "fill";
+                       size = <3>;
+                       fill-byte = [fe];
+               };
+               dtb: u-boot-dtb {
+               };
+       };
+};
diff --git a/tools/binman/test/199_collection_section.dts b/tools/binman/test/199_collection_section.dts
new file mode 100644 (file)
index 0000000..03a7319
--- /dev/null
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               collection {
+                       content = <&section &u_boot>;
+               };
+               fill {
+                       size = <2>;
+                       fill-byte = [ff];
+               };
+               section: section {
+                       u-boot-nodtb {
+                       };
+                       u-boot-dtb {
+                       };
+               };
+               fill2 {
+                       type = "fill";
+                       size = <3>;
+                       fill-byte = [fe];
+               };
+               u_boot: u-boot {
+                       no-expanded;
+               };
+       };
+};
diff --git a/tools/binman/test/200_align_default.dts b/tools/binman/test/200_align_default.dts
new file mode 100644 (file)
index 0000000..1b15577
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               align-default = <8>;
+               u-boot {
+               };
+
+               u-boot-align {
+                       type = "u-boot";
+               };
+
+               section {
+                       align = <32>;
+                       u-boot {
+                       };
+
+                       u-boot-nodtb {
+                       };
+               };
+
+               u-boot-nodtb {
+               };
+       };
+};
index 4520b31..37fc339 100644 (file)
@@ -8,7 +8,7 @@
 #define CONFIG_BINMAN
 #include <binman_sym.h>
 
-binman_sym_declare(unsigned long, u_boot_spl, offset);
+binman_sym_declare(unsigned long, u_boot_spl_any, offset);
 binman_sym_declare(unsigned long long, u_boot_spl2, offset);
 binman_sym_declare(unsigned long, u_boot_any, image_pos);
 binman_sym_declare(unsigned long, u_boot_any, size);
index b7abaed..c9c657c 100644 (file)
@@ -52,6 +52,20 @@ TYPE_NAMES = {
 STRUCT_PREFIX = 'dtd_'
 VAL_PREFIX = 'dtv_'
 
+# Properties which are considered to be phandles
+#    key: property name
+#    value: name of associated #cells property in the target node
+#
+# New phandle properties must be added here; otherwise they will come through as
+# simple integers and finding devices by phandle will not work.
+# Any property that ends with one of these (e.g. 'cd-gpios') will be considered
+# a phandle property.
+PHANDLE_PROPS = {
+    'clocks': '#clock-cells',
+    'gpios': '#gpio-cells',
+    'sandbox,emul': '#emul-cells',
+    }
+
 class Ftype(IntEnum):
     SOURCE, HEADER = range(2)
 
@@ -136,8 +150,10 @@ class DtbPlatdata():
             from the U-Boot source code
         _fdt: Fdt object, referencing the device tree
         _dtb_fname: Filename of the input device tree binary file
-        _valid_nodes: A list of Node object with compatible strings. The list
-            is ordered by conv_name_to_c(node.name)
+        _valid_nodes_unsorted: A list of Node object with compatible strings,
+            ordered by devicetree node order
+        _valid_nodes: A list of Node object with compatible strings, ordered by
+            conv_name_to_c(node.name)
         _include_disabled: true to include nodes marked status = "disabled"
         _outfile: The current output file (sys.stdout or a real file)
         _lines: Stashed list of output lines for outputting in the future
@@ -149,18 +165,25 @@ class DtbPlatdata():
                         key (str): Field name
                         value: Prop object with field information
         _basedir (str): Base directory of source tree
+        _valid_uclasses (list of src_scan.Uclass): List of uclasses needed for
+            the selected devices (see _valid_node), in alphabetical order
+        _instantiate: Instantiate devices so they don't need to be bound at
+            run-time
     """
-    def __init__(self, scan, dtb_fname, include_disabled):
+    def __init__(self, scan, dtb_fname, include_disabled, instantiate=False):
         self._scan = scan
         self._fdt = None
         self._dtb_fname = dtb_fname
         self._valid_nodes = None
+        self._valid_nodes_unsorted = None
         self._include_disabled = include_disabled
         self._outfile = None
         self._lines = []
         self._dirnames = [None] * len(Ftype)
         self._struct_data = collections.OrderedDict()
         self._basedir = None
+        self._valid_uclasses = None
+        self._instantiate = instantiate
 
     def setup_output_dirs(self, output_dirs):
         """Set up the output directories
@@ -223,6 +246,7 @@ class DtbPlatdata():
         """
         if self._outfile != sys.stdout:
             self._outfile.close()
+            self._outfile = None
 
     def out(self, line):
         """Output a string to the output file
@@ -281,7 +305,11 @@ class DtbPlatdata():
             ValueError: if the phandle cannot be parsed or the required property
                 is not present
         """
-        if prop.name in ['clocks', 'cd-gpios']:
+        cells_prop = None
+        for name, cprop in PHANDLE_PROPS.items():
+            if prop.name.endswith(name):
+                cells_prop = cprop
+        if cells_prop:
             if not isinstance(prop.value, list):
                 prop.value = [prop.value]
             val = prop.value
@@ -301,14 +329,10 @@ class DtbPlatdata():
                 if not target:
                     raise ValueError("Cannot parse '%s' in node '%s'" %
                                      (prop.name, node_name))
-                cells = None
-                for prop_name in ['#clock-cells', '#gpio-cells']:
-                    cells = target.props.get(prop_name)
-                    if cells:
-                        break
+                cells = target.props.get(cells_prop)
                 if not cells:
                     raise ValueError("Node '%s' has no cells property" %
-                                     (target.name))
+                                     target.name)
                 num_args = fdt_util.fdt32_to_cpu(cells.value)
                 max_args = max(max_args, num_args)
                 args.append(num_args)
@@ -324,38 +348,84 @@ class DtbPlatdata():
         """
         self._fdt = fdt.FdtScan(self._dtb_fname)
 
-    def scan_node(self, root, valid_nodes):
+    def scan_node(self, node, valid_nodes):
         """Scan a node and subnodes to build a tree of node and phandle info
 
-        This adds each node to self._valid_nodes.
+        This adds each subnode to self._valid_nodes if it is enabled and has a
+        compatible string.
 
         Args:
-            root (Node): Root node for scan
+            node (Node): Node for scan for subnodes
             valid_nodes (list of Node): List of Node objects to add to
         """
-        for node in root.subnodes:
-            if 'compatible' in node.props:
-                status = node.props.get('status')
+        for subnode in node.subnodes:
+            if 'compatible' in subnode.props:
+                status = subnode.props.get('status')
                 if (not self._include_disabled and not status or
                         status.value != 'disabled'):
-                    valid_nodes.append(node)
+                    valid_nodes.append(subnode)
 
             # recurse to handle any subnodes
-            self.scan_node(node, valid_nodes)
+            self.scan_node(subnode, valid_nodes)
 
-    def scan_tree(self):
+    def scan_tree(self, add_root):
         """Scan the device tree for useful information
 
         This fills in the following properties:
-            _valid_nodes: A list of nodes we wish to consider include in the
-                platform data
+            _valid_nodes_unsorted: A list of nodes we wish to consider include
+                in the platform data (in devicetree node order)
+            _valid_nodes: Sorted version of _valid_nodes_unsorted
+
+        Args:
+            add_root: True to add the root node also (which wouldn't normally
+                be added as it may not have a compatible string)
         """
+        root = self._fdt.GetRoot()
         valid_nodes = []
-        self.scan_node(self._fdt.GetRoot(), valid_nodes)
+        if add_root:
+            valid_nodes.append(root)
+        self.scan_node(root, valid_nodes)
+        self._valid_nodes_unsorted = valid_nodes
         self._valid_nodes = sorted(valid_nodes,
                                    key=lambda x: conv_name_to_c(x.name))
+
+    def prepare_nodes(self):
+        """Add extra properties to the nodes we are using
+
+        The following properties are added for use by dtoc:
+            idx: Index number of this node (0=first, etc.)
+            struct_name: Name of the struct dtd used by this node
+            var_name: C name for this node
+            child_devs: List of child devices for this node, each a None
+            child_refs: Dict of references for each child:
+                key: Position in child list (-1=head, 0=first, 1=second, ...
+                                             n-1=last, n=head)
+            seq: Sequence number of the device (unique within its uclass), or
+                -1 not not known yet
+            dev_ref: Reference to this device, e.g. 'DM_DEVICE_REF(serial)'
+            driver: Driver record for this node, or None if not known
+            uclass: Uclass record for this node, or None if not known
+            uclass_seq: Position of this device within the uclass list (0=first,
+                n-1=last)
+            parent_seq: Position of this device within it siblings (0=first,
+                n-1=last)
+            parent_driver: Driver record of the node's parent, or None if none.
+                We don't use node.parent.driver since node.parent may not be in
+                the list of valid nodes
+        """
         for idx, node in enumerate(self._valid_nodes):
             node.idx = idx
+            node.struct_name, _ = self._scan.get_normalized_compat_name(node)
+            node.var_name = conv_name_to_c(node.name)
+            node.child_devs = []
+            node.child_refs = {}
+            node.seq = -1
+            node.dev_ref = None
+            node.driver = None
+            node.uclass = None
+            node.uclass_seq = None
+            node.parent_seq = None
+            node.parent_driver = None
 
     @staticmethod
     def get_num_cells(node):
@@ -434,7 +504,6 @@ class DtbPlatdata():
         """
         structs = self._struct_data
         for node in self._valid_nodes:
-            node_name, _ = self._scan.get_normalized_compat_name(node)
             fields = {}
 
             # Get a list of all the valid properties in this node.
@@ -442,9 +511,9 @@ class DtbPlatdata():
                 if name not in PROP_IGNORE_LIST and name[0] != '#':
                     fields[name] = copy.deepcopy(prop)
 
-            # If we've seen this node_name before, update the existing struct.
-            if node_name in structs:
-                struct = structs[node_name]
+            # If we've seen this struct_name before, update the existing struct
+            if node.struct_name in structs:
+                struct = structs[node.struct_name]
                 for name, prop in fields.items():
                     oldprop = struct.get(name)
                     if oldprop:
@@ -454,11 +523,10 @@ class DtbPlatdata():
 
             # Otherwise store this as a new struct.
             else:
-                structs[node_name] = fields
+                structs[node.struct_name] = fields
 
         for node in self._valid_nodes:
-            node_name, _ = self._scan.get_normalized_compat_name(node)
-            struct = structs[node_name]
+            struct = structs[node.struct_name]
             for name, prop in node.props.items():
                 if name not in PROP_IGNORE_LIST and name[0] != '#':
                     prop.Widen(struct[name])
@@ -562,28 +630,145 @@ class DtbPlatdata():
                 self.buf(', '.join(vals[i:i + 8]))
         self.buf('}')
 
-    def _declare_device(self, var_name, struct_name, node_parent):
+    def _declare_device(self, node):
         """Add a device declaration to the output
 
         This declares a U_BOOT_DRVINFO() for the device being processed
 
         Args:
-            var_name (str): C name for the node
-            struct_name (str): Name for the dt struct associated with the node
-            node_parent (Node): Parent of the node (or None if none)
+            node: Node to process
         """
-        self.buf('U_BOOT_DRVINFO(%s) = {\n' % var_name)
-        self.buf('\t.name\t\t= "%s",\n' % struct_name)
-        self.buf('\t.plat\t= &%s%s,\n' % (VAL_PREFIX, var_name))
-        self.buf('\t.plat_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name))
+        self.buf('U_BOOT_DRVINFO(%s) = {\n' % node.var_name)
+        self.buf('\t.name\t\t= "%s",\n' % node.struct_name)
+        self.buf('\t.plat\t\t= &%s%s,\n' % (VAL_PREFIX, node.var_name))
+        self.buf('\t.plat_size\t= sizeof(%s%s),\n' %
+                 (VAL_PREFIX, node.var_name))
         idx = -1
-        if node_parent and node_parent in self._valid_nodes:
-            idx = node_parent.idx
+        if node.parent and node.parent in self._valid_nodes:
+            idx = node.parent.idx
         self.buf('\t.parent_idx\t= %d,\n' % idx)
         self.buf('};\n')
         self.buf('\n')
 
-    def _output_prop(self, node, prop):
+    def prep_priv(self, struc, name, suffix, section='.priv_data'):
+        if not struc:
+            return None
+        var_name = '_%s%s' % (name, suffix)
+        hdr = self._scan._structs.get(struc)
+        if hdr:
+            self.buf('#include <%s>\n' % hdr.fname)
+        else:
+            print('Warning: Cannot find header file for struct %s' % struc)
+        attr = '__attribute__ ((section ("%s")))' % section
+        return var_name, struc, attr
+
+    def alloc_priv(self, info, name, extra, suffix='_priv'):
+        result = self.prep_priv(info, name, suffix)
+        if not result:
+            return None
+        var_name, struc, section = result
+        self.buf('u8 %s_%s[sizeof(struct %s)]\n\t%s;\n' %
+                 (var_name, extra, struc.strip(), section))
+        return '%s_%s' % (var_name, extra)
+
+    def alloc_plat(self, info, name, extra, node):
+        result = self.prep_priv(info, name, '_plat')
+        if not result:
+            return None
+        var_name, struc, section = result
+        self.buf('struct %s %s\n\t%s_%s = {\n' %
+                 (struc.strip(), section, var_name, extra))
+        self.buf('\t.dtplat = {\n')
+        for pname in sorted(node.props):
+            self._output_prop(node, node.props[pname], 2)
+        self.buf('\t},\n')
+        self.buf('};\n')
+        return '&%s_%s' % (var_name, extra)
+
+    def _declare_device_inst(self, node, parent_driver):
+        """Add a device instance declaration to the output
+
+        This declares a DM_DEVICE_INST() for the device being processed
+
+        Args:
+            node: Node to output
+        """
+        driver = node.driver
+        uclass = node.uclass
+        self.buf('\n')
+        num_lines = len(self._lines)
+        plat_name = self.alloc_plat(driver.plat, driver.name, node.var_name,
+                                    node)
+        priv_name = self.alloc_priv(driver.priv, driver.name, node.var_name)
+        parent_plat_name = None
+        parent_priv_name = None
+        if parent_driver:
+            # TODO: deal with uclass providing these values
+            parent_plat_name = self.alloc_priv(
+                parent_driver.child_plat, driver.name, node.var_name,
+                '_parent_plat')
+            parent_priv_name = self.alloc_priv(
+                parent_driver.child_priv, driver.name, node.var_name,
+                '_parent_priv')
+        uclass_plat_name = self.alloc_priv(
+            uclass.per_dev_plat, driver.name + '_uc', node.var_name, 'plat')
+        uclass_priv_name = self.alloc_priv(uclass.per_dev_priv,
+                                           driver.name + '_uc', node.var_name)
+        for hdr in driver.headers:
+            self.buf('#include %s\n' % hdr)
+
+        # Add a blank line if we emitted any stuff above, for readability
+        if num_lines != len(self._lines):
+            self.buf('\n')
+
+        self.buf('DM_DEVICE_INST(%s) = {\n' % node.var_name)
+        self.buf('\t.driver\t\t= DM_DRIVER_REF(%s),\n' % node.struct_name)
+        self.buf('\t.name\t\t= "%s",\n' % node.struct_name)
+        if plat_name:
+            self.buf('\t.plat_\t\t= %s,\n' % plat_name)
+        else:
+            self.buf('\t.plat_\t\t= &%s%s,\n' % (VAL_PREFIX, node.var_name))
+        if parent_plat_name:
+            self.buf('\t.parent_plat_\t= %s,\n' % parent_plat_name)
+        if uclass_plat_name:
+            self.buf('\t.uclass_plat_\t= %s,\n' % uclass_plat_name)
+        driver_date = None
+
+        if node != self._fdt.GetRoot():
+            compat_list = node.props['compatible'].value
+            if not isinstance(compat_list, list):
+                compat_list = [compat_list]
+            for compat in compat_list:
+                driver_data = driver.compat.get(compat)
+                if driver_data:
+                    self.buf('\t.driver_data\t= %s,\n' % driver_data)
+                    break
+
+        if node.parent and node.parent.parent:
+            self.buf('\t.parent\t\t= DM_DEVICE_REF(%s),\n' %
+                     node.parent.var_name)
+        if priv_name:
+            self.buf('\t.priv_\t\t= %s,\n' % priv_name)
+        self.buf('\t.uclass\t\t= DM_UCLASS_REF(%s),\n' % uclass.name)
+
+        if uclass_priv_name:
+            self.buf('\t.uclass_priv_ = %s,\n' % uclass_priv_name)
+        if parent_priv_name:
+            self.buf('\t.parent_priv_\t= %s,\n' % parent_priv_name)
+        self.list_node('uclass_node', uclass.node_refs, node.uclass_seq)
+        self.list_head('child_head', 'sibling_node', node.child_devs, node.var_name)
+        if node.parent in self._valid_nodes:
+            self.list_node('sibling_node', node.parent.child_refs,
+                           node.parent_seq)
+        # flags is left as 0
+
+        self.buf('\t.seq_ = %d,\n' % node.seq)
+
+        self.buf('};\n')
+        self.buf('\n')
+        return parent_plat_name
+
+    def _output_prop(self, node, prop, tabs=1):
         """Output a line containing the value of a struct member
 
         Args:
@@ -593,7 +778,7 @@ class DtbPlatdata():
         if prop.name in PROP_IGNORE_LIST or prop.name[0] == '#':
             return
         member_name = conv_name_to_c(prop.name)
-        self.buf('\t%s= ' % tab_to(3, '.' + member_name))
+        self.buf('%s%s= ' % ('\t' * tabs, tab_to(3, '.' + member_name)))
 
         # Special handling for lists
         if isinstance(prop.value, list):
@@ -602,35 +787,269 @@ class DtbPlatdata():
             self.buf(get_value(prop.type, prop.value))
         self.buf(',\n')
 
-    def _output_values(self, var_name, struct_name, node):
+    def _output_values(self, node):
         """Output the definition of a device's struct values
 
         Args:
-            var_name (str): C name for the node
-            struct_name (str): Name for the dt struct associated with the node
-            node (Node): Node being output
+            node (Node): Node to output
         """
         self.buf('static struct %s%s %s%s = {\n' %
-                 (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
+                 (STRUCT_PREFIX, node.struct_name, VAL_PREFIX, node.var_name))
         for pname in sorted(node.props):
             self._output_prop(node, node.props[pname])
         self.buf('};\n')
 
-    def output_node(self, node):
+    def list_head(self, head_member, node_member, node_refs, var_name):
+        self.buf('\t.%s\t= {\n' % head_member)
+        if node_refs:
+            last = node_refs[-1].dev_ref
+            first = node_refs[0].dev_ref
+            member = node_member
+        else:
+            last = 'DM_DEVICE_REF(%s)' % var_name
+            first = last
+            member = head_member
+        self.buf('\t\t.prev = &%s->%s,\n' % (last, member))
+        self.buf('\t\t.next = &%s->%s,\n' % (first, member))
+        self.buf('\t},\n')
+
+    def list_node(self, member, node_refs, seq):
+        self.buf('\t.%s\t= {\n' % member)
+        self.buf('\t\t.prev = %s,\n' % node_refs[seq - 1])
+        self.buf('\t\t.next = %s,\n' % node_refs[seq + 1])
+        self.buf('\t},\n')
+
+    def generate_uclasses(self):
+        if not self.check_instantiate(True):
+            return
+        self.out('\n')
+        self.out('#include <common.h>\n')
+        self.out('#include <dm.h>\n')
+        self.out('#include <dt-structs.h>\n')
+        self.out('\n')
+        self.buf('/*\n')
+        self.buf(
+            " * uclass declarations, ordered by 'struct uclass' linker_list idx:\n")
+        uclass_list = self._valid_uclasses
+        for seq, uclass in enumerate(uclass_list):
+            self.buf(' * %3d: %s\n' % (seq, uclass.name))
+        self.buf(' *\n')
+        self.buf(' * Sequence numbers allocated in each uclass:\n')
+        for uclass in uclass_list:
+            if uclass.alias_num_to_node:
+                self.buf(' * %s: %s\n' % (uclass.name, uclass.uclass_id))
+                for seq, node in uclass.alias_num_to_node.items():
+                    self.buf(' *    %d: %s\n' % (seq, node.path))
+        self.buf(' */\n')
+
+        uclass_node = {}
+        for seq, uclass in enumerate(uclass_list):
+            uclass_node[seq] = ('&DM_UCLASS_REF(%s)->sibling_node' %
+                                uclass.name)
+        uclass_node[-1] = '&uclass_head'
+        uclass_node[len(uclass_list)] = '&uclass_head'
+        self.buf('\n')
+        self.buf('struct list_head %s = {\n' % 'uclass_head')
+        self.buf('\t.prev = %s,\n' % uclass_node[len(uclass_list) -1])
+        self.buf('\t.next = %s,\n' % uclass_node[0])
+        self.buf('};\n')
+        self.buf('\n')
+
+        for seq, uclass in enumerate(uclass_list):
+            uc_drv = self._scan._uclass.get(uclass.uclass_id)
+
+            priv_name = self.alloc_priv(uc_drv.priv, uc_drv.name, '')
+
+            self.buf('DM_UCLASS_INST(%s) = {\n' % uclass.name)
+            if priv_name:
+                self.buf('\t.priv_\t\t= %s,\n' % priv_name)
+            self.buf('\t.uc_drv\t\t= DM_UCLASS_DRIVER_REF(%s),\n' % uclass.name)
+            self.list_node('sibling_node', uclass_node, seq)
+            self.list_head('dev_head', 'uclass_node', uc_drv.devs, None)
+            self.buf('};\n')
+            self.buf('\n')
+        self.out(''.join(self.get_buf()))
+
+    def read_aliases(self):
+        """Read the aliases and attach the information to self._alias
+
+        Raises:
+            ValueError: The alias path is not found
+        """
+        alias_node = self._fdt.GetNode('/aliases')
+        if not alias_node:
+            return
+        re_num = re.compile('(^[a-z0-9-]+[a-z]+)([0-9]+)$')
+        for prop in alias_node.props.values():
+            m_alias = re_num.match(prop.name)
+            if not m_alias:
+                raise ValueError("Cannot decode alias '%s'" % prop.name)
+            name, num = m_alias.groups()
+            node = self._fdt.GetNode(prop.value)
+            result = self._scan.add_uclass_alias(name, num, node)
+            if result is None:
+                raise ValueError("Alias '%s' path '%s' not found" %
+                                 (prop.name, prop.value))
+            elif result is False:
+                print("Could not find uclass for alias '%s'" % prop.name)
+
+    def generate_decl(self):
+        nodes_to_output = list(self._valid_nodes)
+
+        self.buf('#include <dm/device-internal.h>\n')
+        self.buf('#include <dm/uclass-internal.h>\n')
+        self.buf('\n')
+        self.buf(
+            '/* driver declarations - these allow DM_DRIVER_GET() to be used */\n')
+        for node in nodes_to_output:
+            self.buf('extern U_BOOT_DRIVER(%s);\n' % node.struct_name);
+        self.buf('\n')
+
+        if self._instantiate:
+            self.buf(
+                '/* device declarations - these allow DM_DEVICE_REF() to be used */\n')
+            for node in nodes_to_output:
+                self.buf('extern DM_DEVICE_INST(%s);\n' % node.var_name)
+            self.buf('\n')
+
+        uclass_list = self._valid_uclasses
+
+        self.buf(
+            '/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */\n')
+        for uclass in uclass_list:
+            self.buf('extern UCLASS_DRIVER(%s);\n' % uclass.name)
+
+        if self._instantiate:
+            self.buf('\n')
+            self.buf('/* uclass declarations - needed for DM_UCLASS_REF() */\n')
+            for uclass in uclass_list:
+                self.buf('extern DM_UCLASS_INST(%s);\n' % uclass.name)
+        self.out(''.join(self.get_buf()))
+
+    def assign_seqs(self):
+        """Assign a sequence number to each node"""
+        for node in self._valid_nodes_unsorted:
+            seq = self._scan.assign_seq(node)
+            if seq is not None:
+                node.seq = seq
+
+    def process_nodes(self, need_drivers):
+        nodes_to_output = list(self._valid_nodes)
+
+        # Figure out which drivers we actually use
+        self._scan.mark_used(nodes_to_output)
+
+        for node in nodes_to_output:
+            node.dev_ref = 'DM_DEVICE_REF(%s)' % node.var_name
+            driver = self._scan.get_driver(node.struct_name)
+            if not driver:
+                if not need_drivers:
+                    continue
+                raise ValueError("Cannot parse/find driver for '%s'" %
+                                 node.struct_name)
+            node.driver = driver
+            uclass = self._scan._uclass.get(driver.uclass_id)
+            if not uclass:
+                raise ValueError("Cannot parse/find uclass '%s' for driver '%s'" %
+                                (driver.uclass_id, node.struct_name))
+            node.uclass = uclass
+            node.uclass_seq = len(node.uclass.devs)
+            node.uclass.devs.append(node)
+            uclass.node_refs[node.uclass_seq] = \
+                '&%s->uclass_node' % node.dev_ref
+
+            parent_driver = None
+            if node.parent in self._valid_nodes:
+                parent_driver = self._scan.get_driver(node.parent.struct_name)
+                if not parent_driver:
+                    if not need_drivers:
+                        continue
+                    raise ValueError(
+                        "Cannot parse/find parent driver '%s' for '%s'" %
+                        (node.parent.struct_name, node.struct_name))
+                node.parent_seq = len(node.parent.child_devs)
+                node.parent.child_devs.append(node)
+                node.parent.child_refs[node.parent_seq] = \
+                    '&%s->sibling_node' % node.dev_ref
+                node.parent_driver = parent_driver
+
+        for node in nodes_to_output:
+            ref = '&%s->child_head' % node.dev_ref
+            node.child_refs[-1] = ref
+            node.child_refs[len(node.child_devs)] = ref
+
+        uclass_set = set()
+        for driver in self._scan._drivers.values():
+            if driver.used and driver.uclass:
+                uclass_set.add(driver.uclass)
+        self._valid_uclasses = sorted(list(uclass_set),
+                                      key=lambda uc: uc.uclass_id)
+
+        for seq, uclass in enumerate(uclass_set):
+            ref = '&DM_UCLASS_REF(%s)->dev_head' % uclass.name
+            uclass.node_refs[-1] = ref
+            uclass.node_refs[len(uclass.devs)] = ref
+
+    def output_node_plat(self, node):
         """Output the C code for a node
 
         Args:
             node (fdt.Node): node to output
         """
-        struct_name, _ = self._scan.get_normalized_compat_name(node)
-        var_name = conv_name_to_c(node.name)
-        self.buf('/* Node %s index %d */\n' % (node.path, node.idx))
+        driver = node.driver
+        parent_driver = node.parent_driver
+
+        line1 = 'Node %s index %d' % (node.path, node.idx)
+        if driver:
+            self.buf('/*\n')
+            self.buf(' * %s\n' % line1)
+            self.buf(' * driver %s parent %s\n' % (driver.name,
+                parent_driver.name if parent_driver else 'None'))
+            self.buf(' */\n')
+        else:
+            self.buf('/* %s */\n' % line1)
 
-        self._output_values(var_name, struct_name, node)
-        self._declare_device(var_name, struct_name, node.parent)
+        self._output_values(node)
+        self._declare_device(node)
 
         self.out(''.join(self.get_buf()))
 
+    def output_node_instance(self, node):
+        """Output the C code for a node
+
+        Args:
+            node (fdt.Node): node to output
+        """
+        parent_driver = node.parent_driver
+
+        self.buf('/*\n')
+        self.buf(' * Node %s index %d\n' % (node.path, node.idx))
+        self.buf(' * driver %s parent %s\n' % (node.driver.name,
+                 parent_driver.name if parent_driver else 'None'))
+        self.buf('*/\n')
+
+        if not node.driver.plat:
+            self._output_values(node)
+        self._declare_device_inst(node, parent_driver)
+
+        self.out(''.join(self.get_buf()))
+
+    def check_instantiate(self, require):
+        """Check if self._instantiate is set to the required value
+
+        If not, this outputs a message into the current file
+
+        Args:
+            require: True to require --instantiate, False to require that it not
+                be enabled
+        """
+        if require != self._instantiate:
+            self.out(
+                '/* This file is not used: --instantiate was %senabled */\n' %
+                ('not ' if require else ''))
+            return False
+        return True
+
     def generate_plat(self):
         """Generate device defintions for the platform data
 
@@ -641,6 +1060,8 @@ class DtbPlatdata():
         See the documentation in doc/driver-model/of-plat.rst for more
         information.
         """
+        if not self.check_instantiate(False):
+            return
         self.out('/* Allow use of U_BOOT_DRVINFO() in this file */\n')
         self.out('#define DT_PLAT_C\n')
         self.out('\n')
@@ -649,8 +1070,57 @@ class DtbPlatdata():
         self.out('#include <dt-structs.h>\n')
         self.out('\n')
 
-        for node in self._valid_nodes:
-            self.output_node(node)
+        if self._valid_nodes:
+            self.out('/*\n')
+            self.out(
+                " * driver_info declarations, ordered by 'struct driver_info' linker_list idx:\n")
+            self.out(' *\n')
+            self.out(' * idx  %-20s %-s\n' % ('driver_info', 'driver'))
+            self.out(' * ---  %-20s %-s\n' % ('-' * 20, '-' * 20))
+            for node in self._valid_nodes:
+                self.out(' * %3d: %-20s %-s\n' %
+                        (node.idx, node.var_name, node.struct_name))
+            self.out(' * ---  %-20s %-s\n' % ('-' * 20, '-' * 20))
+            self.out(' */\n')
+            self.out('\n')
+
+            for node in self._valid_nodes:
+                self.output_node_plat(node)
+
+        self.out(''.join(self.get_buf()))
+
+    def generate_device(self):
+        """Generate device instances
+
+        This writes out DM_DEVICE_INST() records for each device in the
+        build.
+
+        See the documentation in doc/driver-model/of-plat.rst for more
+        information.
+        """
+        if not self.check_instantiate(True):
+            return
+        self.out('#include <common.h>\n')
+        self.out('#include <dm.h>\n')
+        self.out('#include <dt-structs.h>\n')
+        self.out('\n')
+
+        if self._valid_nodes:
+            self.out('/*\n')
+            self.out(
+                " * udevice declarations, ordered by 'struct udevice' linker_list position:\n")
+            self.out(' *\n')
+            self.out(' * idx  %-20s %-s\n' % ('udevice', 'driver'))
+            self.out(' * ---  %-20s %-s\n' % ('-' * 20, '-' * 20))
+            for node in self._valid_nodes:
+                self.out(' * %3d: %-20s %-s\n' %
+                        (node.idx, node.var_name, node.struct_name))
+            self.out(' * ---  %-20s %-s\n' % ('-' * 20, '-' * 20))
+            self.out(' */\n')
+            self.out('\n')
+
+            for node in self._valid_nodes:
+                self.output_node_instance(node)
 
         self.out(''.join(self.get_buf()))
 
@@ -658,19 +1128,37 @@ class DtbPlatdata():
 # Types of output file we understand
 # key: Command used to generate this file
 # value: OutputFile for this command
-OUTPUT_FILES = {
+OUTPUT_FILES_COMMON = {
+    'decl':
+        OutputFile(Ftype.HEADER, 'dt-decl.h', DtbPlatdata.generate_decl,
+                   'Declares externs for all device/uclass instances'),
     'struct':
         OutputFile(Ftype.HEADER, 'dt-structs-gen.h',
                    DtbPlatdata.generate_structs,
                    'Defines the structs used to hold devicetree data'),
+    }
+
+# File generated without instantiate
+OUTPUT_FILES_NOINST = {
     'platdata':
         OutputFile(Ftype.SOURCE, 'dt-plat.c', DtbPlatdata.generate_plat,
                    'Declares the U_BOOT_DRIVER() records and platform data'),
     }
 
+# File generated with instantiate
+OUTPUT_FILES_INST = {
+    'device':
+        OutputFile(Ftype.SOURCE, 'dt-device.c', DtbPlatdata.generate_device,
+                   'Declares the DM_DEVICE_INST() records'),
+    'uclass':
+        OutputFile(Ftype.SOURCE, 'dt-uclass.c', DtbPlatdata.generate_uclasses,
+                   'Declares the uclass instances (struct uclass)'),
+    }
 
-def run_steps(args, dtb_file, include_disabled, output, output_dirs,
-              warning_disabled=False, drivers_additional=None, basedir=None):
+
+def run_steps(args, dtb_file, include_disabled, output, output_dirs, phase,
+              instantiate, warning_disabled=False, drivers_additional=None,
+              basedir=None, scan=None):
     """Run all the steps of the dtoc tool
 
     Args:
@@ -681,12 +1169,22 @@ def run_steps(args, dtb_file, include_disabled, output, output_dirs,
         output_dirs (tuple of str):
             Directory to put C output files
             Directory to put H output files
+        phase: The phase of U-Boot that we are generating data for, e.g. 'spl'
+             or 'tpl'. None if not known
+        instantiate: Instantiate devices so they don't need to be bound at
+            run-time
         warning_disabled (bool): True to avoid showing warnings about missing
             drivers
         drivers_additional (list): List of additional drivers to use during
             scanning
         basedir (str): Base directory of U-Boot source code. Defaults to the
             grandparent of this file's directory
+        scan (src_src.Scanner): Scanner from a previous run. This can help speed
+            up tests. Use None for normal operation
+
+    Returns:
+        DtbPlatdata object
+
     Raises:
         ValueError: if args has no command, or an unknown command
     """
@@ -695,26 +1193,43 @@ def run_steps(args, dtb_file, include_disabled, output, output_dirs,
     if output and output_dirs and any(output_dirs):
         raise ValueError('Must specify either output or output_dirs, not both')
 
-    scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional)
-    plat = DtbPlatdata(scan, dtb_file, include_disabled)
-    scan.scan_drivers()
+    if not scan:
+        scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional,
+                                phase)
+        scan.scan_drivers()
+        do_process = True
+    else:
+        do_process = False
+    plat = DtbPlatdata(scan, dtb_file, include_disabled, instantiate)
     plat.scan_dtb()
-    plat.scan_tree()
+    plat.scan_tree(add_root=instantiate)
+    plat.prepare_nodes()
     plat.scan_reg_sizes()
     plat.setup_output_dirs(output_dirs)
     plat.scan_structs()
     plat.scan_phandles()
+    plat.process_nodes(instantiate)
+    plat.read_aliases()
+    plat.assign_seqs()
+
+    # Figure out what output files we plan to generate
+    output_files = OUTPUT_FILES_COMMON
+    if instantiate:
+        output_files.update(OUTPUT_FILES_INST)
+    else:
+        output_files.update(OUTPUT_FILES_NOINST)
 
     cmds = args[0].split(',')
     if 'all' in cmds:
-        cmds = sorted(OUTPUT_FILES.keys())
+        cmds = sorted(output_files.keys())
     for cmd in cmds:
-        outfile = OUTPUT_FILES.get(cmd)
+        outfile = output_files.get(cmd)
         if not outfile:
             raise ValueError("Unknown command '%s': (use: %s)" %
-                             (cmd, ', '.join(sorted(OUTPUT_FILES.keys()))))
+                             (cmd, ', '.join(sorted(output_files.keys()))))
         plat.setup_output(outfile.ftype,
                           outfile.fname if output_dirs else output)
         plat.out_header(outfile)
         outfile.method(plat)
     plat.finish_output()
+    return plat
diff --git a/tools/dtoc/dtoc_test_scan_drivers.cxx b/tools/dtoc/dtoc_test_scan_drivers.cxx
deleted file mode 100644 (file)
index f448767..0000000
+++ /dev/null
@@ -1 +0,0 @@
-DM_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias2)
index 25ce513..3996971 100644 (file)
@@ -103,6 +103,8 @@ class Prop:
     """A device tree property
 
     Properties:
+        node: Node containing this property
+        offset: Offset of the property (None if still to be synced)
         name: Property name (as per the device tree)
         value: Property value as a string of bytes, or a list of strings of
             bytes
@@ -114,7 +116,7 @@ class Prop:
         self.name = name
         self.value = None
         self.bytes = bytes(data)
-        self.dirty = False
+        self.dirty = offset is None
         if not data:
             self.type = Type.BOOL
             self.value = True
@@ -228,9 +230,14 @@ class Prop:
         Raises:
             FdtException if auto_resize is False and there is not enough space
         """
-        if self._offset is None or self.dirty:
+        if self.dirty:
             node = self._node
             fdt_obj = node._fdt._fdt_obj
+            node_name = fdt_obj.get_name(node._offset)
+            if node_name and node_name != node.name:
+                raise ValueError("Internal error, node '%s' name mismatch '%s'" %
+                                 (node.path, node_name))
+
             if auto_resize:
                 while fdt_obj.setprop(node.Offset(), self.name, self.bytes,
                                     (libfdt.NOSPACE,)) == -libfdt.NOSPACE:
@@ -239,13 +246,15 @@ class Prop:
                     fdt_obj.setprop(node.Offset(), self.name, self.bytes)
             else:
                 fdt_obj.setprop(node.Offset(), self.name, self.bytes)
+            self.dirty = False
 
 
 class Node:
     """A device tree node
 
     Properties:
-        offset: Integer offset in the device tree
+        parent: Parent Node
+        offset: Integer offset in the device tree (None if to be synced)
         name: Device tree node tname
         path: Full path to node, along with the node name itself
         _fdt: Device tree object
@@ -324,6 +333,11 @@ class Node:
         fdt_obj = self._fdt._fdt_obj
         if self._offset != my_offset:
             self._offset = my_offset
+        name = fdt_obj.get_name(self._offset)
+        if name and self.name != name:
+            raise ValueError("Internal error, node '%s' name mismatch '%s'" %
+                             (self.path, name))
+
         offset = fdt_obj.first_subnode(self._offset, QUIET_NOTFOUND)
         for subnode in self.subnodes:
             if subnode.name != fdt_obj.get_name(offset):
@@ -339,8 +353,8 @@ class Node:
             p = fdt_obj.get_property_by_offset(poffset)
             prop = self.props.get(p.name)
             if not prop:
-                raise ValueError("Internal error, property '%s' missing, "
-                                 'offset %d' % (p.name, poffset))
+                raise ValueError("Internal error, node '%s' property '%s' missing, "
+                                 'offset %d' % (self.path, p.name, poffset))
             prop.RefreshOffset(poffset)
             poffset = fdt_obj.next_property_offset(poffset, QUIET_NOTFOUND)
 
@@ -447,8 +461,13 @@ class Node:
         Args:
             prop_name: Name of property to add
             val: Bytes value of property
+
+        Returns:
+            Prop added
         """
-        self.props[prop_name] = Prop(self, None, prop_name, val)
+        prop = Prop(self, None, prop_name, val)
+        self.props[prop_name] = prop
+        return prop
 
     def AddString(self, prop_name, val):
         """Add a new string property to a node
@@ -459,9 +478,12 @@ class Node:
         Args:
             prop_name: Name of property to add
             val: String value of property
+
+        Returns:
+            Prop added
         """
         val = bytes(val, 'utf-8')
-        self.AddData(prop_name, val + b'\0')
+        return self.AddData(prop_name, val + b'\0')
 
     def AddInt(self, prop_name, val):
         """Add a new integer property to a node
@@ -472,8 +494,11 @@ class Node:
         Args:
             prop_name: Name of property to add
             val: Integer value of property
+
+        Returns:
+            Prop added
         """
-        self.AddData(prop_name, struct.pack('>I', val))
+        return self.AddData(prop_name, struct.pack('>I', val))
 
     def AddSubnode(self, name):
         """Add a new subnode to the node
@@ -499,9 +524,13 @@ class Node:
             auto_resize: Resize the device tree automatically if it does not
                 have enough space for the update
 
+        Returns:
+            True if the node had to be added, False if it already existed
+
         Raises:
             FdtException if auto_resize is False and there is not enough space
         """
+        added = False
         if self._offset is None:
             # The subnode doesn't exist yet, so add it
             fdt_obj = self._fdt._fdt_obj
@@ -515,23 +544,45 @@ class Node:
             else:
                 offset = fdt_obj.add_subnode(self.parent._offset, self.name)
             self._offset = offset
+            added = True
 
-        # Sync subnodes in reverse so that we don't disturb node offsets for
-        # nodes that are earlier in the DT. This avoids an O(n^2) rescan of
-        # node offsets.
+        # Sync the existing subnodes first, so that we can rely on the offsets
+        # being correct. As soon as we add new subnodes, it pushes all the
+        # existing subnodes up.
         for node in reversed(self.subnodes):
-            node.Sync(auto_resize)
+            if node._offset is not None:
+                node.Sync(auto_resize)
 
-        # Sync properties now, whose offsets should not have been disturbed.
-        # We do this after subnodes, since this disturbs the offsets of these
-        # properties. Note that new properties will have an offset of None here,
-        # which Python 3 cannot sort against int. So use a large value instead
-        # to ensure that the new properties are added first.
+        # Sync subnodes in reverse so that we get the expected order. Each
+        # new node goes at the start of the subnode list. This avoids an O(n^2)
+        # rescan of node offsets.
+        num_added = 0
+        for node in reversed(self.subnodes):
+            if node.Sync(auto_resize):
+                num_added += 1
+        if num_added:
+            # Reorder our list of nodes to put the new ones first, since that's
+            # what libfdt does
+            old_count = len(self.subnodes) - num_added
+            subnodes = self.subnodes[old_count:] + self.subnodes[:old_count]
+            self.subnodes = subnodes
+
+        # Sync properties now, whose offsets should not have been disturbed,
+        # since properties come before subnodes. This is done after all the
+        # subnode processing above, since updating properties can disturb the
+        # offsets of those subnodes.
+        # Properties are synced in reverse order, with new properties added
+        # before existing properties are synced. This ensures that the offsets
+        # of earlier properties are not disturbed.
+        # Note that new properties will have an offset of None here, which
+        # Python cannot sort against int. So use a large value instead so that
+        # new properties are added first.
         prop_list = sorted(self.props.values(),
                            key=lambda prop: prop._offset or 1 << 31,
                            reverse=True)
         for prop in prop_list:
             prop.Sync(auto_resize)
+        return added
 
 
 class Fdt:
@@ -642,8 +693,9 @@ class Fdt:
         Raises:
             FdtException if auto_resize is False and there is not enough space
         """
+        self.CheckCache()
         self._root.Sync(auto_resize)
-        self.Invalidate()
+        self.Refresh()
 
     def Pack(self):
         """Pack the device tree down to its minimum size
@@ -652,7 +704,7 @@ class Fdt:
         build up in the device tree binary.
         """
         CheckErr(self._fdt_obj.pack(), 'pack')
-        self.Invalidate()
+        self.Refresh()
 
     def GetContents(self):
         """Get the contents of the FDT
@@ -704,11 +756,11 @@ class Fdt:
         if self._cached_offsets:
             return
         self.Refresh()
-        self._cached_offsets = True
 
     def Refresh(self):
         """Refresh the offset cache"""
         self._root.Refresh(0)
+        self._cached_offsets = True
 
     def GetStructOffset(self, offset):
         """Get the file offset of a given struct offset
index b0ad0f3..93706de 100755 (executable)
@@ -53,6 +53,8 @@ def run_tests(processes, args):
     sys.argv = [sys.argv[0]]
     test_name = args and args[0] or None
 
+    test_dtoc.setup()
+
     test_util.RunTestSuites(
         result, debug=True, verbosity=1, test_preserve_dirs=False,
         processes=processes, test_name=test_name, toolpath=[],
@@ -79,10 +81,14 @@ parser.add_option('-C', '--h-output-dir', action='store',
                   help='Select output directory for H files (defaults to --c-output-di)')
 parser.add_option('-d', '--dtb-file', action='store',
                   help='Specify the .dtb input file')
+parser.add_option('-i', '--instantiate', action='store_true', default=False,
+                  help='Instantiate devices to avoid needing device_bind()')
 parser.add_option('--include-disabled', action='store_true',
                   help='Include disabled nodes')
 parser.add_option('-o', '--output', action='store',
                   help='Select output filename')
+parser.add_option('-p', '--phase', type=str,
+                  help='set phase of U-Boot this invocation is for (spl/tpl)')
 parser.add_option('-P', '--processes', type=int,
                   help='set number of processes to use for running tests')
 parser.add_option('-t', '--test', action='store_true', dest='test',
@@ -102,4 +108,5 @@ elif options.test_coverage:
 else:
     dtb_platdata.run_steps(args, options.dtb_file, options.include_disabled,
                            options.output,
-                           [options.c_output_dir, options.h_output_dir])
+                           [options.c_output_dir, options.h_output_dir],
+                           options.phase, instantiate=options.instantiate)
index f63c9fc..114212c 100644 (file)
@@ -33,6 +33,8 @@ def conv_name_to_c(name):
     new = new.replace('-', '_')
     new = new.replace(',', '_')
     new = new.replace('.', '_')
+    if new == '/':
+        return 'root'
     return new
 
 def get_compat_name(node):
@@ -54,15 +56,123 @@ class Driver:
 
     Attributes:
         name: Name of driver. For U_BOOT_DRIVER(x) this is 'x'
+        fname: Filename where the driver was found
+        uclass_id: Name of uclass, e.g. 'UCLASS_I2C'
+        compat: Driver data for each compatible string:
+            key: Compatible string, e.g. 'rockchip,rk3288-grf'
+            value: Driver data, e,g, 'ROCKCHIP_SYSCON_GRF', or None
+        fname: Filename where the driver was found
+        priv (str): struct name of the priv_auto member, e.g. 'serial_priv'
+        plat (str): struct name of the plat_auto member, e.g. 'serial_plat'
+        child_priv (str): struct name of the per_child_auto member,
+            e.g. 'pci_child_priv'
+        child_plat (str): struct name of the per_child_plat_auto member,
+            e.g. 'pci_child_plat'
+        used (bool): True if the driver is used by the structs being output
+        phase (str): Which phase of U-Boot to use this driver
+        headers (list): List of header files needed for this driver (each a str)
+            e.g. ['<asm/cpu.h>']
+        dups (list): Driver objects with the same name as this one, that were
+            found after this one
+        warn_dups (bool): True if the duplicates are not distinguisble using
+            the phase
+        uclass (Uclass): uclass for this driver
+    """
+    def __init__(self, name, fname):
+        self.name = name
+        self.fname = fname
+        self.uclass_id = None
+        self.compat = None
+        self.priv = ''
+        self.plat = ''
+        self.child_priv = ''
+        self.child_plat = ''
+        self.used = False
+        self.phase = ''
+        self.headers = []
+        self.dups = []
+        self.warn_dups = False
+        self.uclass = None
+
+    def __eq__(self, other):
+        return (self.name == other.name and
+                self.uclass_id == other.uclass_id and
+                self.compat == other.compat and
+                self.priv == other.priv and
+                self.plat == other.plat and
+                self.used == other.used)
+
+    def __repr__(self):
+        return ("Driver(name='%s', used=%s, uclass_id='%s', compat=%s, priv=%s)" %
+                (self.name, self.used, self.uclass_id, self.compat, self.priv))
+
+
+class UclassDriver:
+    """Holds information about a uclass driver
+
+    Attributes:
+        name: Uclass name, e.g. 'i2c' if the driver is for UCLASS_I2C
+        uclass_id: Uclass ID, e.g. 'UCLASS_I2C'
+        priv: struct name of the private data, e.g. 'i2c_priv'
+        per_dev_priv (str): struct name of the priv_auto member, e.g. 'spi_info'
+        per_dev_plat (str): struct name of the plat_auto member, e.g. 'i2c_chip'
+        per_child_priv (str): struct name of the per_child_auto member,
+            e.g. 'pci_child_priv'
+        per_child_plat (str): struct name of the per_child_plat_auto member,
+            e.g. 'pci_child_plat'
+        alias_num_to_node (dict): Aliases for this uclasses (for sequence
+                numbers)
+            key (int): Alias number, e.g. 2 for "pci2"
+            value (str): Node the alias points to
+        alias_path_to_num (dict): Convert a path to an alias number
+            key (str): Full path to node (e.g. '/soc/pci')
+            seq (int): Alias number, e.g. 2 for "pci2"
+        devs (list): List of devices in this uclass, each a Node
+        node_refs (dict): References in the linked list of devices:
+            key (int): Sequence number (0=first, n-1=last, -1=head, n=tail)
+            value (str): Reference to the device at that position
     """
     def __init__(self, name):
         self.name = name
+        self.uclass_id = None
+        self.priv = ''
+        self.per_dev_priv = ''
+        self.per_dev_plat = ''
+        self.per_child_priv = ''
+        self.per_child_plat = ''
+        self.alias_num_to_node = {}
+        self.alias_path_to_num = {}
+        self.devs = []
+        self.node_refs = {}
 
     def __eq__(self, other):
-        return self.name == other.name
+        return (self.name == other.name and
+                self.uclass_id == other.uclass_id and
+                self.priv == other.priv)
 
     def __repr__(self):
-        return "Driver(name='%s')" % self.name
+        return ("UclassDriver(name='%s', uclass_id='%s')" %
+                (self.name, self.uclass_id))
+
+    def __hash__(self):
+        # We can use the uclass ID since it is unique among uclasses
+        return hash(self.uclass_id)
+
+
+class Struct:
+    """Holds information about a struct definition
+
+    Attributes:
+        name: Struct name, e.g. 'fred' if the struct is 'struct fred'
+        fname: Filename containing the struct, in a format that C files can
+            include, e.g. 'asm/clk.h'
+    """
+    def __init__(self, name, fname):
+        self.name = name
+        self.fname =fname
+
+    def __repr__(self):
+        return ("Struct(name='%s', fname='%s')" % (self.name, self.fname))
 
 
 class Scanner:
@@ -81,8 +191,22 @@ class Scanner:
         _warning_disabled: true to disable warnings about driver names not found
         _drivers_additional (list or str): List of additional drivers to use
             during scanning
+        _of_match: Dict holding information about compatible strings
+            key: Name of struct udevice_id variable
+            value: Dict of compatible info in that variable:
+               key: Compatible string, e.g. 'rockchip,rk3288-grf'
+               value: Driver data, e,g, 'ROCKCHIP_SYSCON_GRF', or None
+        _compat_to_driver: Maps compatible strings to Driver
+        _uclass: Dict of uclass information
+            key: uclass name, e.g. 'UCLASS_I2C'
+            value: UClassDriver
+        _structs: Dict of all structs found in U-Boot:
+            key: Name of struct
+            value: Struct object
+        _phase: The phase of U-Boot that we are generating data for, e.g. 'spl'
+             or 'tpl'. None if not known
     """
-    def __init__(self, basedir, warning_disabled, drivers_additional):
+    def __init__(self, basedir, warning_disabled, drivers_additional, phase=''):
         """Set up a new Scanner
         """
         if not basedir:
@@ -94,6 +218,22 @@ class Scanner:
         self._driver_aliases = {}
         self._drivers_additional = drivers_additional or []
         self._warning_disabled = warning_disabled
+        self._of_match = {}
+        self._compat_to_driver = {}
+        self._uclass = {}
+        self._structs = {}
+        self._phase = phase
+
+    def get_driver(self, name):
+        """Get a driver given its name
+
+        Args:
+            name (str): Driver name
+
+        Returns:
+            Driver: Driver or None if not found
+        """
+        return self._drivers.get(name)
 
     def get_normalized_compat_name(self, node):
         """Get a node's normalized compat name
@@ -112,7 +252,10 @@ class Scanner:
                 In case of no match found, the return will be the same as
                 get_compat_name()
         """
-        compat_list_c = get_compat_name(node)
+        if not node.parent:
+            compat_list_c = ['root_driver']
+        else:
+            compat_list_c = get_compat_name(node)
 
         for compat_c in compat_list_c:
             if not compat_c in self._drivers.keys():
@@ -131,10 +274,319 @@ class Scanner:
 
         return compat_list_c[0], compat_list_c[1:]
 
+    def _parse_structs(self, fname, buff):
+        """Parse a H file to extract struct definitions contained within
+
+        This parses 'struct xx {' definitions to figure out what structs this
+        header defines.
+
+        Args:
+            buff (str): Contents of file
+            fname (str): Filename (to use when printing errors)
+        """
+        structs = {}
+
+        re_struct = re.compile('^struct ([a-z0-9_]+) {$')
+        re_asm = re.compile('../arch/[a-z0-9]+/include/asm/(.*)')
+        prefix = ''
+        for line in buff.splitlines():
+            # Handle line continuation
+            if prefix:
+                line = prefix + line
+                prefix = ''
+            if line.endswith('\\'):
+                prefix = line[:-1]
+                continue
+
+            m_struct = re_struct.match(line)
+            if m_struct:
+                name = m_struct.group(1)
+                include_dir = os.path.join(self._basedir, 'include')
+                rel_fname = os.path.relpath(fname, include_dir)
+                m_asm = re_asm.match(rel_fname)
+                if m_asm:
+                    rel_fname = 'asm/' + m_asm.group(1)
+                structs[name] = Struct(name, rel_fname)
+        self._structs.update(structs)
+
+    @classmethod
+    def _get_re_for_member(cls, member):
+        """_get_re_for_member: Get a compiled regular expression
+
+        Args:
+            member (str): Struct member name, e.g. 'priv_auto'
+
+        Returns:
+            re.Pattern: Compiled regular expression that parses:
+
+               .member = sizeof(struct fred),
+
+            and returns "fred" as group 1
+        """
+        return re.compile(r'^\s*.%s\s*=\s*sizeof\(struct\s+(.*)\),$' % member)
+
+    def _parse_uclass_driver(self, fname, buff):
+        """Parse a C file to extract uclass driver information contained within
+
+        This parses UCLASS_DRIVER() structs to obtain various pieces of useful
+        information.
+
+        It updates the following member:
+            _uclass: Dict of uclass information
+                key: uclass name, e.g. 'UCLASS_I2C'
+                value: UClassDriver
+
+        Args:
+            fname (str): Filename being parsed (used for warnings)
+            buff (str): Contents of file
+        """
+        uc_drivers = {}
+
+        # Collect the driver name and associated Driver
+        driver = None
+        re_driver = re.compile(r'^UCLASS_DRIVER\((.*)\)')
+
+        # Collect the uclass ID, e.g. 'UCLASS_SPI'
+        re_id = re.compile(r'\s*\.id\s*=\s*(UCLASS_[A-Z0-9_]+)')
+
+        # Matches the header/size information for uclass-private data
+        re_priv = self._get_re_for_member('priv_auto')
+
+        # Set up parsing for the auto members
+        re_per_device_priv = self._get_re_for_member('per_device_auto')
+        re_per_device_plat = self._get_re_for_member('per_device_plat_auto')
+        re_per_child_priv = self._get_re_for_member('per_child_auto')
+        re_per_child_plat = self._get_re_for_member('per_child_plat_auto')
+
+        prefix = ''
+        for line in buff.splitlines():
+            # Handle line continuation
+            if prefix:
+                line = prefix + line
+                prefix = ''
+            if line.endswith('\\'):
+                prefix = line[:-1]
+                continue
+
+            driver_match = re_driver.search(line)
+
+            # If we have seen UCLASS_DRIVER()...
+            if driver:
+                m_id = re_id.search(line)
+                m_priv = re_priv.match(line)
+                m_per_dev_priv = re_per_device_priv.match(line)
+                m_per_dev_plat = re_per_device_plat.match(line)
+                m_per_child_priv = re_per_child_priv.match(line)
+                m_per_child_plat = re_per_child_plat.match(line)
+                if m_id:
+                    driver.uclass_id = m_id.group(1)
+                elif m_priv:
+                    driver.priv = m_priv.group(1)
+                elif m_per_dev_priv:
+                    driver.per_dev_priv = m_per_dev_priv.group(1)
+                elif m_per_dev_plat:
+                    driver.per_dev_plat = m_per_dev_plat.group(1)
+                elif m_per_child_priv:
+                    driver.per_child_priv = m_per_child_priv.group(1)
+                elif m_per_child_plat:
+                    driver.per_child_plat = m_per_child_plat.group(1)
+                elif '};' in line:
+                    if not driver.uclass_id:
+                        raise ValueError(
+                            "%s: Cannot parse uclass ID in driver '%s'" %
+                            (fname, driver.name))
+                    uc_drivers[driver.uclass_id] = driver
+                    driver = None
+
+            elif driver_match:
+                driver_name = driver_match.group(1)
+                driver = UclassDriver(driver_name)
+
+        self._uclass.update(uc_drivers)
+
+    def _parse_driver(self, fname, buff):
+        """Parse a C file to extract driver information contained within
+
+        This parses U_BOOT_DRIVER() structs to obtain various pieces of useful
+        information.
+
+        It updates the following members:
+            _drivers - updated with new Driver records for each driver found
+                in the file
+            _of_match - updated with each compatible string found in the file
+            _compat_to_driver - Maps compatible string to Driver
+            _driver_aliases - Maps alias names to driver name
+
+        Args:
+            fname (str): Filename being parsed (used for warnings)
+            buff (str): Contents of file
+
+        Raises:
+            ValueError: Compatible variable is mentioned in .of_match in
+                U_BOOT_DRIVER() but not found in the file
+        """
+        # Dict holding information about compatible strings collected in this
+        # function so far
+        #    key: Name of struct udevice_id variable
+        #    value: Dict of compatible info in that variable:
+        #       key: Compatible string, e.g. 'rockchip,rk3288-grf'
+        #       value: Driver data, e,g, 'ROCKCHIP_SYSCON_GRF', or None
+        of_match = {}
+
+        # Dict holding driver information collected in this function so far
+        #    key: Driver name (C name as in U_BOOT_DRIVER(xxx))
+        #    value: Driver
+        drivers = {}
+
+        # Collect the driver info
+        driver = None
+        re_driver = re.compile(r'^U_BOOT_DRIVER\((.*)\)')
+
+        # Collect the uclass ID, e.g. 'UCLASS_SPI'
+        re_id = re.compile(r'\s*\.id\s*=\s*(UCLASS_[A-Z0-9_]+)')
+
+        # Collect the compatible string, e.g. 'rockchip,rk3288-grf'
+        compat = None
+        re_compat = re.compile(r'{\s*.compatible\s*=\s*"(.*)"\s*'
+                               r'(,\s*.data\s*=\s*(\S*))?\s*},')
+
+        # This is a dict of compatible strings that were found:
+        #    key: Compatible string, e.g. 'rockchip,rk3288-grf'
+        #    value: Driver data, e,g, 'ROCKCHIP_SYSCON_GRF', or None
+        compat_dict = {}
+
+        # Holds the var nane of the udevice_id list, e.g.
+        # 'rk3288_syscon_ids_noc' in
+        # static const struct udevice_id rk3288_syscon_ids_noc[] = {
+        ids_name = None
+        re_ids = re.compile(r'struct udevice_id (.*)\[\]\s*=')
+
+        # Matches the references to the udevice_id list
+        re_of_match = re.compile(
+            r'\.of_match\s*=\s*(of_match_ptr\()?([a-z0-9_]+)(\))?,')
+
+        re_phase = re.compile('^\s*DM_PHASE\((.*)\).*$')
+        re_hdr = re.compile('^\s*DM_HEADER\((.*)\).*$')
+        re_alias = re.compile(r'DM_DRIVER_ALIAS\(\s*(\w+)\s*,\s*(\w+)\s*\)')
+
+        # Matches the struct name for priv, plat
+        re_priv = self._get_re_for_member('priv_auto')
+        re_plat = self._get_re_for_member('plat_auto')
+        re_child_priv = self._get_re_for_member('per_child_auto')
+        re_child_plat = self._get_re_for_member('per_child_plat_auto')
+
+        prefix = ''
+        for line in buff.splitlines():
+            # Handle line continuation
+            if prefix:
+                line = prefix + line
+                prefix = ''
+            if line.endswith('\\'):
+                prefix = line[:-1]
+                continue
+
+            driver_match = re_driver.search(line)
+
+            # If this line contains U_BOOT_DRIVER()...
+            if driver:
+                m_id = re_id.search(line)
+                m_of_match = re_of_match.search(line)
+                m_priv = re_priv.match(line)
+                m_plat = re_plat.match(line)
+                m_cplat = re_child_plat.match(line)
+                m_cpriv = re_child_priv.match(line)
+                m_phase = re_phase.match(line)
+                m_hdr = re_hdr.match(line)
+                if m_priv:
+                    driver.priv = m_priv.group(1)
+                elif m_plat:
+                    driver.plat = m_plat.group(1)
+                elif m_cplat:
+                    driver.child_plat = m_cplat.group(1)
+                elif m_cpriv:
+                    driver.child_priv = m_cpriv.group(1)
+                elif m_id:
+                    driver.uclass_id = m_id.group(1)
+                elif m_of_match:
+                    compat = m_of_match.group(2)
+                elif m_phase:
+                    driver.phase = m_phase.group(1)
+                elif m_hdr:
+                    driver.headers.append(m_hdr.group(1))
+                elif '};' in line:
+                    is_root = driver.name == 'root_driver'
+                    if driver.uclass_id and (compat or is_root):
+                        if not is_root:
+                            if compat not in of_match:
+                                raise ValueError(
+                                    "%s: Unknown compatible var '%s' (found: %s)" %
+                                    (fname, compat, ','.join(of_match.keys())))
+                            driver.compat = of_match[compat]
+
+                            # This needs to be deterministic, since a driver may
+                            # have multiple compatible strings pointing to it.
+                            # We record the one earliest in the alphabet so it
+                            # will produce the same result on all machines.
+                            for compat_id in of_match[compat]:
+                                old = self._compat_to_driver.get(compat_id)
+                                if not old or driver.name < old.name:
+                                    self._compat_to_driver[compat_id] = driver
+                        drivers[driver.name] = driver
+                    else:
+                        # The driver does not have a uclass or compat string.
+                        # The first is required but the second is not, so just
+                        # ignore this.
+                        pass
+                    driver = None
+                    ids_name = None
+                    compat = None
+                    compat_dict = {}
+
+            elif ids_name:
+                compat_m = re_compat.search(line)
+                if compat_m:
+                    compat_dict[compat_m.group(1)] = compat_m.group(3)
+                elif '};' in line:
+                    of_match[ids_name] = compat_dict
+                    ids_name = None
+            elif driver_match:
+                driver_name = driver_match.group(1)
+                driver = Driver(driver_name, fname)
+            else:
+                ids_m = re_ids.search(line)
+                m_alias = re_alias.match(line)
+                if ids_m:
+                    ids_name = ids_m.group(1)
+                elif m_alias:
+                    self._driver_aliases[m_alias[2]] = m_alias[1]
+
+        # Make the updates based on what we found
+        for driver in drivers.values():
+            if driver.name in self._drivers:
+                orig = self._drivers[driver.name]
+                if self._phase:
+                    # If the original driver matches our phase, use it
+                    if orig.phase == self._phase:
+                        orig.dups.append(driver)
+                        continue
+
+                    # Otherwise use the new driver, which is assumed to match
+                else:
+                    # We have no way of distinguishing them
+                    driver.warn_dups = True
+                driver.dups.append(orig)
+            self._drivers[driver.name] = driver
+        self._of_match.update(of_match)
+
     def scan_driver(self, fname):
         """Scan a driver file to build a list of driver names and aliases
 
-        This procedure will populate self._drivers and self._driver_aliases
+        It updates the following members:
+            _drivers - updated with new Driver records for each driver found
+                in the file
+            _of_match - updated with each compatible string found in the file
+            _compat_to_driver - Maps compatible string to Driver
+            _driver_aliases - Maps alias names to driver name
 
         Args
             fname: Driver filename to scan
@@ -147,23 +599,35 @@ class Scanner:
                 print("Skipping file '%s' due to unicode error" % fname)
                 return
 
-            # The following re will search for driver names declared as
-            # U_BOOT_DRIVER(driver_name)
-            drivers = re.findall(r'U_BOOT_DRIVER\((.*)\)', buff)
+            # If this file has any U_BOOT_DRIVER() declarations, process it to
+            # obtain driver information
+            if 'U_BOOT_DRIVER' in buff:
+                self._parse_driver(fname, buff)
+            if 'UCLASS_DRIVER' in buff:
+                self._parse_uclass_driver(fname, buff)
 
-            for driver in drivers:
-                self._drivers[driver] = Driver(driver)
+    def scan_header(self, fname):
+        """Scan a header file to build a list of struct definitions
 
-            # The following re will search for driver aliases declared as
-            # DM_DRIVER_ALIAS(alias, driver_name)
-            driver_aliases = re.findall(
-                r'DM_DRIVER_ALIAS\(\s*(\w+)\s*,\s*(\w+)\s*\)',
-                buff)
+        It updates the following members:
+            _structs - updated with new Struct records for each struct found
+                in the file
 
-            for alias in driver_aliases: # pragma: no cover
-                if len(alias) != 2:
-                    continue
-                self._driver_aliases[alias[1]] = alias[0]
+        Args
+            fname: header filename to scan
+        """
+        with open(fname, encoding='utf-8') as inf:
+            try:
+                buff = inf.read()
+            except UnicodeDecodeError:
+                # This seems to happen on older Python versions
+                print("Skipping file '%s' due to unicode error" % fname)
+                return
+
+            # If this file has any U_BOOT_DRIVER() declarations, process it to
+            # obtain driver information
+            if 'struct' in buff:
+                self._parse_structs(fname, buff)
 
     def scan_drivers(self):
         """Scan the driver folders to build a list of driver names and aliases
@@ -171,11 +635,17 @@ class Scanner:
         This procedure will populate self._drivers and self._driver_aliases
         """
         for (dirpath, _, filenames) in os.walk(self._basedir):
+            rel_path = dirpath[len(self._basedir):]
+            if rel_path.startswith('/'):
+                rel_path = rel_path[1:]
+            if rel_path.startswith('build') or rel_path.startswith('.git'):
+                continue
             for fname in filenames:
-                if not fname.endswith('.c'):
-                    continue
-                self.scan_driver(dirpath + '/' + fname)
-
+                pathname = dirpath + '/' + fname
+                if fname.endswith('.c'):
+                    self.scan_driver(pathname)
+                elif fname.endswith('.h'):
+                    self.scan_header(pathname)
         for fname in self._drivers_additional:
             if not isinstance(fname, str) or len(fname) == 0:
                 continue
@@ -183,3 +653,84 @@ class Scanner:
                 self.scan_driver(fname)
             else:
                 self.scan_driver(self._basedir + '/' + fname)
+
+        # Get the uclass for each driver
+        # TODO: Can we just get the uclass for the ones we use, e.g. in
+        # mark_used()?
+        for driver in self._drivers.values():
+            driver.uclass = self._uclass.get(driver.uclass_id)
+
+    def mark_used(self, nodes):
+        """Mark the drivers associated with a list of nodes as 'used'
+
+        This takes a list of nodes, finds the driver for each one and marks it
+        as used.
+
+        If two used drivers have the same name, issue a warning.
+
+        Args:
+            nodes (list of None): Nodes that are in use
+        """
+        # Figure out which drivers we actually use
+        for node in nodes:
+            struct_name, _ = self.get_normalized_compat_name(node)
+            driver = self._drivers.get(struct_name)
+            if driver:
+                driver.used = True
+                if driver.dups and driver.warn_dups:
+                    print("Warning: Duplicate driver name '%s' (orig=%s, dups=%s)" %
+                          (driver.name, driver.fname,
+                           ', '.join([drv.fname for drv in driver.dups])))
+
+    def add_uclass_alias(self, name, num, node):
+        """Add an alias to a uclass
+
+        Args:
+            name: Name of uclass, e.g. 'i2c'
+            num: Alias number, e.g. 2 for alias 'i2c2'
+            node: Node the alias points to, or None if None
+
+        Returns:
+            True if the node was added
+            False if the node was not added (uclass of that name not found)
+            None if the node could not be added because it was None
+        """
+        for uclass in self._uclass.values():
+            if uclass.name == name:
+                if node is None:
+                    return None
+                uclass.alias_num_to_node[int(num)] = node
+                uclass.alias_path_to_num[node.path] = int(num)
+                return True
+        return False
+
+    def assign_seq(self, node):
+        """Figure out the sequence number for a node
+
+        This looks in the node's uclass and assigns a sequence number if needed,
+        based on the aliases and other nodes in that uclass.
+
+        It updates the uclass alias_path_to_num and alias_num_to_node
+
+        Args:
+            node (Node): Node object to look up
+        """
+        if node.driver and node.seq == -1 and node.uclass:
+            uclass = node.uclass
+            num = uclass.alias_path_to_num.get(node.path)
+            if num is not None:
+                return num
+            else:
+                # Dynamically allocate the next available value after all
+                # existing ones
+                if uclass.alias_num_to_node:
+                    start = max(uclass.alias_num_to_node.keys())
+                else:
+                    start = -1
+                for seq in range(start + 1, 1000):
+                    if seq not in uclass.alias_num_to_node:
+                        break
+                uclass.alias_path_to_num[node.path] = seq
+                uclass.alias_num_to_node[seq] = node
+                return seq
+        return None
diff --git a/tools/dtoc/test/dtoc_test_alias_bad.dts b/tools/dtoc/test/dtoc_test_alias_bad.dts
new file mode 100644 (file)
index 0000000..d4f502a
--- /dev/null
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               testbus2 = &bus2;
+               testfdt1 = &testfdt_1;
+               i2c4- = &i2c;
+       };
+
+       spl-test {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,spl-test";
+               boolval;
+               intval = <1>;
+       };
+
+       i2c: i2c {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,i2c";
+               intval = <3>;
+       };
+
+       spl-test3 {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,spl-test";
+               stringarray = "one";
+               longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
+       };
+
+       bus2: some-bus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "denx,u-boot-test-bus";
+               reg = <3 1>;
+               ping-expect = <4>;
+               ping-add = <4>;
+               testfdt_1: test {
+                       compatible = "denx,u-boot-fdt-test", "google,another-fdt-test";
+                       reg = <5>;
+                       ping-expect = <5>;
+                       ping-add = <5>;
+               };
+
+               test0 {
+                       compatible = "google,another-fdt-test";
+               };
+       };
+};
diff --git a/tools/dtoc/test/dtoc_test_alias_bad_path.dts b/tools/dtoc/test/dtoc_test_alias_bad_path.dts
new file mode 100644 (file)
index 0000000..0beca4f
--- /dev/null
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               testbus2 = &bus2;
+               testfdt1 = &testfdt_1;
+               i2c4 = "/does/not/exist";
+       };
+
+       spl-test {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,spl-test";
+               boolval;
+               intval = <1>;
+       };
+
+       i2c: i2c {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,i2c";
+               intval = <3>;
+       };
+
+       spl-test3 {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,spl-test";
+               stringarray = "one";
+               longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
+       };
+
+       bus2: some-bus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "denx,u-boot-test-bus";
+               reg = <3 1>;
+               ping-expect = <4>;
+               ping-add = <4>;
+               testfdt_1: test {
+                       compatible = "denx,u-boot-fdt-test", "google,another-fdt-test";
+                       reg = <5>;
+                       ping-expect = <5>;
+                       ping-add = <5>;
+               };
+
+               test0 {
+                       compatible = "google,another-fdt-test";
+               };
+       };
+};
diff --git a/tools/dtoc/test/dtoc_test_alias_bad_uc.dts b/tools/dtoc/test/dtoc_test_alias_bad_uc.dts
new file mode 100644 (file)
index 0000000..ae64f5b
--- /dev/null
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               testbus2 = &bus2;
+               testfdt1 = &testfdt_1;
+               other1 = &testfdt_1;
+       };
+
+       spl-test {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,spl-test";
+               boolval;
+               intval = <1>;
+       };
+
+       i2c: i2c {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,i2c";
+               intval = <3>;
+       };
+
+       spl-test3 {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,spl-test";
+               stringarray = "one";
+               longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
+       };
+
+       bus2: some-bus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "denx,u-boot-test-bus";
+               reg = <3 1>;
+               ping-expect = <4>;
+               ping-add = <4>;
+               testfdt_1: test {
+                       compatible = "denx,u-boot-fdt-test", "google,another-fdt-test";
+                       reg = <5>;
+                       ping-expect = <5>;
+                       ping-add = <5>;
+               };
+
+               test0 {
+                       compatible = "google,another-fdt-test";
+               };
+       };
+};
diff --git a/tools/dtoc/test/dtoc_test_inst.dts b/tools/dtoc/test/dtoc_test_inst.dts
new file mode 100644 (file)
index 0000000..b8177fc
--- /dev/null
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               testbus2 = &bus2;
+               testfdt1 = &testfdt_1;
+               i2c4 = &i2c;
+       };
+
+       spl-test {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,spl-test";
+               boolval;
+               intval = <1>;
+       };
+
+       i2c: i2c {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,i2c";
+               intval = <3>;
+       };
+
+       spl-test3 {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,spl-test";
+               stringarray = "one";
+               longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
+       };
+
+       bus2: some-bus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "denx,u-boot-test-bus";
+               reg = <3 1>;
+               ping-expect = <4>;
+               ping-add = <4>;
+               testfdt_1: test {
+                       compatible = "denx,u-boot-fdt-test", "google,another-fdt-test";
+                       reg = <5>;
+                       ping-expect = <5>;
+                       ping-add = <5>;
+               };
+
+               test0 {
+                       compatible = "google,another-fdt-test";
+               };
+       };
+};
diff --git a/tools/dtoc/test/dtoc_test_scan_drivers.cxx b/tools/dtoc/test/dtoc_test_scan_drivers.cxx
new file mode 100644 (file)
index 0000000..f370b89
--- /dev/null
@@ -0,0 +1,5 @@
+/* Aliases must be in driver files */
+U_BOOT_DRIVER(sandbox_gpio) {
+};
+
+DM_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias2)
similarity index 91%
rename from tools/dtoc/dtoc_test_simple.dts
rename to tools/dtoc/test/dtoc_test_simple.dts
index 1c87b89..b5c1274 100644 (file)
        };
 
        i2c@0 {
-               compatible = "sandbox,i2c-test";
+               compatible = "sandbox,i2c";
                u-boot,dm-pre-reloc;
                #address-cells = <1>;
                #size-cells = <0>;
                pmic@9 {
-                       compatible = "sandbox,pmic-test";
+                       compatible = "sandbox,pmic";
                        u-boot,dm-pre-reloc;
                        reg = <9>;
                        low-power;
                };
        };
+
+       orig-node {
+               orig = <1 23 4>;
+       };
 };
index d961d67..e951283 100755 (executable)
@@ -10,16 +10,19 @@ tool.
 """
 
 import collections
+import copy
 import glob
 import os
 import struct
 import unittest
 
+from dtb_platdata import Ftype
 from dtb_platdata import get_value
 from dtb_platdata import tab_to
 from dtoc import dtb_platdata
 from dtoc import fdt
 from dtoc import fdt_util
+from dtoc import src_scan
 from dtoc.src_scan import conv_name_to_c
 from dtoc.src_scan import get_compat_name
 from patman import test_util
@@ -38,13 +41,23 @@ HEADER = '''/*
 #include <stdbool.h>
 #include <linux/libfdt.h>'''
 
-C_HEADER = '''/*
+DECL_HEADER = '''/*
+ * DO NOT MODIFY
+ *
+ * Declares externs for all device/uclass instances.
+ * This was generated by dtoc from a .dtb (device tree binary) file.
+ */
+'''
+
+C_HEADER_PRE = '''/*
  * DO NOT MODIFY
  *
  * Declares the U_BOOT_DRIVER() records and platform data.
  * This was generated by dtoc from a .dtb (device tree binary) file.
  */
+'''
 
+C_HEADER = C_HEADER_PRE + '''
 /* Allow use of U_BOOT_DRVINFO() in this file */
 #define DT_PLAT_C
 
@@ -53,6 +66,21 @@ C_HEADER = '''/*
 #include <dt-structs.h>
 '''
 
+UCLASS_HEADER_COMMON = '''/*
+ * DO NOT MODIFY
+ *
+ * Declares the uclass instances (struct uclass).
+ * This was generated by dtoc from a .dtb (device tree binary) file.
+ */
+'''
+
+UCLASS_HEADER = UCLASS_HEADER_COMMON + '''
+/* This file is not used: --instantiate was not enabled */
+'''
+
+# Scanner saved from a previous run of the tests (to speed things up)
+saved_scan = None
+
 # This is a test so is allowed to access private things in the module it is
 # testing
 # pylint: disable=W0212
@@ -67,10 +95,23 @@ def get_dtb_file(dts_fname, capture_stderr=False):
     Returns:
         str: Filename of compiled file in output directory
     """
-    return fdt_util.EnsureCompiled(os.path.join(OUR_PATH, dts_fname),
+    return fdt_util.EnsureCompiled(os.path.join(OUR_PATH, 'test', dts_fname),
                                    capture_stderr=capture_stderr)
 
 
+def setup():
+    global saved_scan
+
+    # Disable warnings so that calls to get_normalized_compat_name() will not
+    # output things.
+    saved_scan = src_scan.Scanner(None, True, False)
+    saved_scan.scan_drivers()
+
+def copy_scan():
+    """Get a copy of saved_scan so that each test can start clean"""
+    return copy.deepcopy(saved_scan)
+
+
 class TestDtoc(unittest.TestCase):
     """Tests for dtoc"""
     @classmethod
@@ -112,15 +153,22 @@ class TestDtoc(unittest.TestCase):
         self.assertEqual(expected, actual)
 
     @staticmethod
-    def run_test(args, dtb_file, output):
+    def run_test(args, dtb_file, output, instantiate=False):
         """Run a test using dtoc
 
         Args:
             args (list of str): List of arguments for dtoc
             dtb_file (str): Filename of .dtb file
             output (str): Filename of output file
+
+        Returns:
+            DtbPlatdata object
         """
-        dtb_platdata.run_steps(args, dtb_file, False, output, [], True)
+        # Make a copy of the 'scan' object, since it includes uclasses and
+        # drivers, which get updated during execution.
+        return dtb_platdata.run_steps(
+            args, dtb_file, False, output, [], None, instantiate,
+            warning_disabled=True, scan=copy_scan())
 
     def test_name(self):
         """Test conversion of device tree names to C identifiers"""
@@ -175,7 +223,10 @@ class TestDtoc(unittest.TestCase):
         """Test output from a device tree file with no nodes"""
         dtb_file = get_dtb_file('dtoc_test_empty.dts')
         output = tools.GetOutputFilename('output')
-        self.run_test(['struct'], dtb_file, output)
+
+        # Run this one without saved_scan to complete test coverage
+        dtb_platdata.run_steps(['struct'], dtb_file, False, output, [], None,
+                               False)
         with open(output) as infile:
             lines = infile.read().splitlines()
         self.assertEqual(HEADER.splitlines(), lines)
@@ -185,10 +236,62 @@ class TestDtoc(unittest.TestCase):
             lines = infile.read().splitlines()
         self.assertEqual(C_HEADER.splitlines() + [''], lines)
 
+    decl_text = DECL_HEADER + '''
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+/* driver declarations - these allow DM_DRIVER_GET() to be used */
+extern U_BOOT_DRIVER(sandbox_i2c);
+extern U_BOOT_DRIVER(sandbox_pmic);
+extern U_BOOT_DRIVER(sandbox_spl_test);
+extern U_BOOT_DRIVER(sandbox_spl_test);
+extern U_BOOT_DRIVER(sandbox_spl_test);
+
+/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */
+extern UCLASS_DRIVER(i2c);
+extern UCLASS_DRIVER(misc);
+extern UCLASS_DRIVER(pmic);
+'''
+    decl_text_inst = DECL_HEADER + '''
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+/* driver declarations - these allow DM_DRIVER_GET() to be used */
+extern U_BOOT_DRIVER(sandbox_i2c);
+extern U_BOOT_DRIVER(root_driver);
+extern U_BOOT_DRIVER(denx_u_boot_test_bus);
+extern U_BOOT_DRIVER(sandbox_spl_test);
+extern U_BOOT_DRIVER(sandbox_spl_test);
+extern U_BOOT_DRIVER(denx_u_boot_fdt_test);
+extern U_BOOT_DRIVER(denx_u_boot_fdt_test);
+
+/* device declarations - these allow DM_DEVICE_REF() to be used */
+extern DM_DEVICE_INST(i2c);
+extern DM_DEVICE_INST(root);
+extern DM_DEVICE_INST(some_bus);
+extern DM_DEVICE_INST(spl_test);
+extern DM_DEVICE_INST(spl_test3);
+extern DM_DEVICE_INST(test);
+extern DM_DEVICE_INST(test0);
+
+/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */
+extern UCLASS_DRIVER(i2c);
+extern UCLASS_DRIVER(misc);
+extern UCLASS_DRIVER(root);
+extern UCLASS_DRIVER(testbus);
+extern UCLASS_DRIVER(testfdt);
+
+/* uclass declarations - needed for DM_UCLASS_REF() */
+extern DM_UCLASS_INST(i2c);
+extern DM_UCLASS_INST(misc);
+extern DM_UCLASS_INST(root);
+extern DM_UCLASS_INST(testbus);
+extern DM_UCLASS_INST(testfdt);
+'''
     struct_text = HEADER + '''
-struct dtd_sandbox_i2c_test {
+struct dtd_sandbox_i2c {
 };
-struct dtd_sandbox_pmic_test {
+struct dtd_sandbox_pmic {
 \tbool\t\tlow_power;
 \tfdt64_t\t\treg[2];
 };
@@ -205,31 +308,52 @@ struct dtd_sandbox_spl_test {
 \tconst char *\tstringval;
 };
 '''
-
     platdata_text = C_HEADER + '''
-/* Node /i2c@0 index 0 */
-static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: i2c_at_0             sandbox_i2c
+ *   1: pmic_at_9            sandbox_pmic
+ *   2: spl_test             sandbox_spl_test
+ *   3: spl_test2            sandbox_spl_test
+ *   4: spl_test3            sandbox_spl_test
+ * ---  -------------------- --------------------
+ */
+
+/*
+ * Node /i2c@0 index 0
+ * driver sandbox_i2c parent None
+ */
+static struct dtd_sandbox_i2c dtv_i2c_at_0 = {
 };
 U_BOOT_DRVINFO(i2c_at_0) = {
-\t.name\t\t= "sandbox_i2c_test",
-\t.plat\t= &dtv_i2c_at_0,
+\t.name\t\t= "sandbox_i2c",
+\t.plat\t\t= &dtv_i2c_at_0,
 \t.plat_size\t= sizeof(dtv_i2c_at_0),
 \t.parent_idx\t= -1,
 };
 
-/* Node /i2c@0/pmic@9 index 1 */
-static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
+/*
+ * Node /i2c@0/pmic@9 index 1
+ * driver sandbox_pmic parent sandbox_i2c
+ */
+static struct dtd_sandbox_pmic dtv_pmic_at_9 = {
 \t.low_power\t\t= true,
 \t.reg\t\t\t= {0x9, 0x0},
 };
 U_BOOT_DRVINFO(pmic_at_9) = {
-\t.name\t\t= "sandbox_pmic_test",
-\t.plat\t= &dtv_pmic_at_9,
+\t.name\t\t= "sandbox_pmic",
+\t.plat\t\t= &dtv_pmic_at_9,
 \t.plat_size\t= sizeof(dtv_pmic_at_9),
 \t.parent_idx\t= 0,
 };
 
-/* Node /spl-test index 2 */
+/*
+ * Node /spl-test index 2
+ * driver sandbox_spl_test parent None
+ */
 static struct dtd_sandbox_spl_test dtv_spl_test = {
 \t.boolval\t\t= true,
 \t.bytearray\t\t= {0x6, 0x0, 0x0},
@@ -244,12 +368,15 @@ static struct dtd_sandbox_spl_test dtv_spl_test = {
 };
 U_BOOT_DRVINFO(spl_test) = {
 \t.name\t\t= "sandbox_spl_test",
-\t.plat\t= &dtv_spl_test,
+\t.plat\t\t= &dtv_spl_test,
 \t.plat_size\t= sizeof(dtv_spl_test),
 \t.parent_idx\t= -1,
 };
 
-/* Node /spl-test2 index 3 */
+/*
+ * Node /spl-test2 index 3
+ * driver sandbox_spl_test parent None
+ */
 static struct dtd_sandbox_spl_test dtv_spl_test2 = {
 \t.acpi_name\t\t= "\\\\_SB.GPO0",
 \t.bytearray\t\t= {0x1, 0x23, 0x34},
@@ -263,12 +390,15 @@ static struct dtd_sandbox_spl_test dtv_spl_test2 = {
 };
 U_BOOT_DRVINFO(spl_test2) = {
 \t.name\t\t= "sandbox_spl_test",
-\t.plat\t= &dtv_spl_test2,
+\t.plat\t\t= &dtv_spl_test2,
 \t.plat_size\t= sizeof(dtv_spl_test2),
 \t.parent_idx\t= -1,
 };
 
-/* Node /spl-test3 index 4 */
+/*
+ * Node /spl-test3 index 4
+ * driver sandbox_spl_test parent None
+ */
 static struct dtd_sandbox_spl_test dtv_spl_test3 = {
 \t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
 \t\t0x0},
@@ -276,12 +406,406 @@ static struct dtd_sandbox_spl_test dtv_spl_test3 = {
 };
 U_BOOT_DRVINFO(spl_test3) = {
 \t.name\t\t= "sandbox_spl_test",
-\t.plat\t= &dtv_spl_test3,
+\t.plat\t\t= &dtv_spl_test3,
 \t.plat_size\t= sizeof(dtv_spl_test3),
 \t.parent_idx\t= -1,
 };
 
 '''
+    uclass_text = UCLASS_HEADER
+    uclass_text_inst = '''
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+
+/*
+ * uclass declarations, ordered by 'struct uclass' linker_list idx:
+ *   0: i2c
+ *   1: misc
+ *   2: root
+ *   3: testbus
+ *   4: testfdt
+ *
+ * Sequence numbers allocated in each uclass:
+ * i2c: UCLASS_I2C
+ *    4: /i2c
+ * misc: UCLASS_MISC
+ *    0: /spl-test
+ *    1: /spl-test3
+ * root: UCLASS_ROOT
+ *    0: /
+ * testbus: UCLASS_TEST_BUS
+ *    2: /some-bus
+ * testfdt: UCLASS_TEST_FDT
+ *    1: /some-bus/test
+ *    2: /some-bus/test0
+ */
+
+struct list_head uclass_head = {
+       .prev = &DM_UCLASS_REF(testfdt)->sibling_node,
+       .next = &DM_UCLASS_REF(i2c)->sibling_node,
+};
+
+DM_UCLASS_INST(i2c) = {
+       .uc_drv         = DM_UCLASS_DRIVER_REF(i2c),
+       .sibling_node   = {
+               .prev = &uclass_head,
+               .next = &DM_UCLASS_REF(misc)->sibling_node,
+       },
+       .dev_head       = {
+               .prev = &DM_DEVICE_REF(i2c)->uclass_node,
+               .next = &DM_DEVICE_REF(i2c)->uclass_node,
+       },
+};
+
+DM_UCLASS_INST(misc) = {
+       .uc_drv         = DM_UCLASS_DRIVER_REF(misc),
+       .sibling_node   = {
+               .prev = &DM_UCLASS_REF(i2c)->sibling_node,
+               .next = &DM_UCLASS_REF(root)->sibling_node,
+       },
+       .dev_head       = {
+               .prev = &DM_DEVICE_REF(spl_test3)->uclass_node,
+               .next = &DM_DEVICE_REF(spl_test)->uclass_node,
+       },
+};
+
+DM_UCLASS_INST(root) = {
+       .uc_drv         = DM_UCLASS_DRIVER_REF(root),
+       .sibling_node   = {
+               .prev = &DM_UCLASS_REF(misc)->sibling_node,
+               .next = &DM_UCLASS_REF(testbus)->sibling_node,
+       },
+       .dev_head       = {
+               .prev = &DM_DEVICE_REF(root)->uclass_node,
+               .next = &DM_DEVICE_REF(root)->uclass_node,
+       },
+};
+
+DM_UCLASS_INST(testbus) = {
+       .uc_drv         = DM_UCLASS_DRIVER_REF(testbus),
+       .sibling_node   = {
+               .prev = &DM_UCLASS_REF(root)->sibling_node,
+               .next = &DM_UCLASS_REF(testfdt)->sibling_node,
+       },
+       .dev_head       = {
+               .prev = &DM_DEVICE_REF(some_bus)->uclass_node,
+               .next = &DM_DEVICE_REF(some_bus)->uclass_node,
+       },
+};
+
+#include <dm/test.h>
+u8 _testfdt_priv_[sizeof(struct dm_test_uc_priv)]
+       __attribute__ ((section (".priv_data")));
+DM_UCLASS_INST(testfdt) = {
+       .priv_          = _testfdt_priv_,
+       .uc_drv         = DM_UCLASS_DRIVER_REF(testfdt),
+       .sibling_node   = {
+               .prev = &DM_UCLASS_REF(testbus)->sibling_node,
+               .next = &uclass_head,
+       },
+       .dev_head       = {
+               .prev = &DM_DEVICE_REF(test0)->uclass_node,
+               .next = &DM_DEVICE_REF(test)->uclass_node,
+       },
+};
+
+'''
+    device_text = '''/*
+ * DO NOT MODIFY
+ *
+ * Declares the DM_DEVICE_INST() records.
+ * This was generated by dtoc from a .dtb (device tree binary) file.
+ */
+
+/* This file is not used: --instantiate was not enabled */
+'''
+    device_text_inst = '''/*
+ * DO NOT MODIFY
+ *
+ * Declares the DM_DEVICE_INST() records.
+ * This was generated by dtoc from a .dtb (device tree binary) file.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+
+/*
+ * udevice declarations, ordered by 'struct udevice' linker_list position:
+ *
+ * idx  udevice              driver
+ * ---  -------------------- --------------------
+ *   0: i2c                  sandbox_i2c
+ *   1: root                 root_driver
+ *   2: some_bus             denx_u_boot_test_bus
+ *   3: spl_test             sandbox_spl_test
+ *   4: spl_test3            sandbox_spl_test
+ *   5: test                 denx_u_boot_fdt_test
+ *   6: test0                denx_u_boot_fdt_test
+ * ---  -------------------- --------------------
+ */
+
+/*
+ * Node /i2c index 0
+ * driver sandbox_i2c parent root_driver
+*/
+static struct dtd_sandbox_i2c dtv_i2c = {
+\t.intval\t\t\t= 0x3,
+};
+
+#include <asm/i2c.h>
+u8 _sandbox_i2c_priv_i2c[sizeof(struct sandbox_i2c_priv)]
+\t__attribute__ ((section (".priv_data")));
+#include <i2c.h>
+u8 _sandbox_i2c_uc_priv_i2c[sizeof(struct dm_i2c_bus)]
+\t__attribute__ ((section (".priv_data")));
+
+DM_DEVICE_INST(i2c) = {
+\t.driver\t\t= DM_DRIVER_REF(sandbox_i2c),
+\t.name\t\t= "sandbox_i2c",
+\t.plat_\t\t= &dtv_i2c,
+\t.priv_\t\t= _sandbox_i2c_priv_i2c,
+\t.uclass\t\t= DM_UCLASS_REF(i2c),
+\t.uclass_priv_ = _sandbox_i2c_uc_priv_i2c,
+\t.uclass_node\t= {
+\t\t.prev = &DM_UCLASS_REF(i2c)->dev_head,
+\t\t.next = &DM_UCLASS_REF(i2c)->dev_head,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(i2c)->child_head,
+\t\t.next = &DM_DEVICE_REF(i2c)->child_head,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(root)->child_head,
+\t\t.next = &DM_DEVICE_REF(some_bus)->sibling_node,
+\t},
+\t.seq_ = 4,
+};
+
+/*
+ * Node / index 1
+ * driver root_driver parent None
+*/
+static struct dtd_root_driver dtv_root = {
+};
+
+DM_DEVICE_INST(root) = {
+\t.driver\t\t= DM_DRIVER_REF(root_driver),
+\t.name\t\t= "root_driver",
+\t.plat_\t\t= &dtv_root,
+\t.uclass\t\t= DM_UCLASS_REF(root),
+\t.uclass_node\t= {
+\t\t.prev = &DM_UCLASS_REF(root)->dev_head,
+\t\t.next = &DM_UCLASS_REF(root)->dev_head,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(spl_test3)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(i2c)->sibling_node,
+\t},
+\t.seq_ = 0,
+};
+
+/*
+ * Node /some-bus index 2
+ * driver denx_u_boot_test_bus parent root_driver
+*/
+
+#include <dm/test.h>
+struct dm_test_pdata __attribute__ ((section (".priv_data")))
+\t_denx_u_boot_test_bus_plat_some_bus = {
+\t.dtplat = {
+\t\t.ping_add\t\t= 0x4,
+\t\t.ping_expect\t\t= 0x4,
+\t\t.reg\t\t\t= {0x3, 0x1},
+\t},
+};
+#include <dm/test.h>
+u8 _denx_u_boot_test_bus_priv_some_bus[sizeof(struct dm_test_priv)]
+\t__attribute__ ((section (".priv_data")));
+#include <dm/test.h>
+u8 _denx_u_boot_test_bus_ucplat_some_bus[sizeof(struct dm_test_uclass_priv)]
+\t__attribute__ ((section (".priv_data")));
+#include <test.h>
+
+DM_DEVICE_INST(some_bus) = {
+\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_test_bus),
+\t.name\t\t= "denx_u_boot_test_bus",
+\t.plat_\t\t= &_denx_u_boot_test_bus_plat_some_bus,
+\t.uclass_plat_\t= _denx_u_boot_test_bus_ucplat_some_bus,
+\t.driver_data\t= DM_TEST_TYPE_FIRST,
+\t.priv_\t\t= _denx_u_boot_test_bus_priv_some_bus,
+\t.uclass\t\t= DM_UCLASS_REF(testbus),
+\t.uclass_node\t= {
+\t\t.prev = &DM_UCLASS_REF(testbus)->dev_head,
+\t\t.next = &DM_UCLASS_REF(testbus)->dev_head,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(test0)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(test)->sibling_node,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(i2c)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(spl_test)->sibling_node,
+\t},
+\t.seq_ = 2,
+};
+
+/*
+ * Node /spl-test index 3
+ * driver sandbox_spl_test parent root_driver
+*/
+static struct dtd_sandbox_spl_test dtv_spl_test = {
+\t.boolval\t\t= true,
+\t.intval\t\t\t= 0x1,
+};
+
+DM_DEVICE_INST(spl_test) = {
+\t.driver\t\t= DM_DRIVER_REF(sandbox_spl_test),
+\t.name\t\t= "sandbox_spl_test",
+\t.plat_\t\t= &dtv_spl_test,
+\t.uclass\t\t= DM_UCLASS_REF(misc),
+\t.uclass_node\t= {
+\t\t.prev = &DM_UCLASS_REF(misc)->dev_head,
+\t\t.next = &DM_DEVICE_REF(spl_test3)->uclass_node,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(spl_test)->child_head,
+\t\t.next = &DM_DEVICE_REF(spl_test)->child_head,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(some_bus)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(spl_test3)->sibling_node,
+\t},
+\t.seq_ = 0,
+};
+
+/*
+ * Node /spl-test3 index 4
+ * driver sandbox_spl_test parent root_driver
+*/
+static struct dtd_sandbox_spl_test dtv_spl_test3 = {
+\t.longbytearray\t\t= {0x90a0b0c, 0xd0e0f10},
+\t.stringarray\t\t= "one",
+};
+
+DM_DEVICE_INST(spl_test3) = {
+\t.driver\t\t= DM_DRIVER_REF(sandbox_spl_test),
+\t.name\t\t= "sandbox_spl_test",
+\t.plat_\t\t= &dtv_spl_test3,
+\t.uclass\t\t= DM_UCLASS_REF(misc),
+\t.uclass_node\t= {
+\t\t.prev = &DM_DEVICE_REF(spl_test)->uclass_node,
+\t\t.next = &DM_UCLASS_REF(misc)->dev_head,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(spl_test3)->child_head,
+\t\t.next = &DM_DEVICE_REF(spl_test3)->child_head,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(spl_test)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(root)->child_head,
+\t},
+\t.seq_ = 1,
+};
+
+/*
+ * Node /some-bus/test index 5
+ * driver denx_u_boot_fdt_test parent denx_u_boot_test_bus
+*/
+
+#include <dm/test.h>
+struct dm_test_pdata __attribute__ ((section (".priv_data")))
+\t_denx_u_boot_fdt_test_plat_test = {
+\t.dtplat = {
+\t\t.ping_add\t\t= 0x5,
+\t\t.ping_expect\t\t= 0x5,
+\t\t.reg\t\t\t= {0x5, 0x0},
+\t},
+};
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_priv_test[sizeof(struct dm_test_priv)]
+\t__attribute__ ((section (".priv_data")));
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_parent_plat_test[sizeof(struct dm_test_parent_plat)]
+\t__attribute__ ((section (".priv_data")));
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_parent_priv_test[sizeof(struct dm_test_parent_data)]
+\t__attribute__ ((section (".priv_data")));
+
+DM_DEVICE_INST(test) = {
+\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_fdt_test),
+\t.name\t\t= "denx_u_boot_fdt_test",
+\t.plat_\t\t= &_denx_u_boot_fdt_test_plat_test,
+\t.parent_plat_\t= _denx_u_boot_fdt_test_parent_plat_test,
+\t.driver_data\t= DM_TEST_TYPE_FIRST,
+\t.parent\t\t= DM_DEVICE_REF(some_bus),
+\t.priv_\t\t= _denx_u_boot_fdt_test_priv_test,
+\t.uclass\t\t= DM_UCLASS_REF(testfdt),
+\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test,
+\t.uclass_node\t= {
+\t\t.prev = &DM_UCLASS_REF(testfdt)->dev_head,
+\t\t.next = &DM_DEVICE_REF(test0)->uclass_node,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(test)->child_head,
+\t\t.next = &DM_DEVICE_REF(test)->child_head,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(some_bus)->child_head,
+\t\t.next = &DM_DEVICE_REF(test0)->sibling_node,
+\t},
+\t.seq_ = 1,
+};
+
+/*
+ * Node /some-bus/test0 index 6
+ * driver denx_u_boot_fdt_test parent denx_u_boot_test_bus
+*/
+
+#include <dm/test.h>
+struct dm_test_pdata __attribute__ ((section (".priv_data")))
+\t_denx_u_boot_fdt_test_plat_test0 = {
+\t.dtplat = {
+\t},
+};
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_priv_test0[sizeof(struct dm_test_priv)]
+\t__attribute__ ((section (".priv_data")));
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_parent_plat_test0[sizeof(struct dm_test_parent_plat)]
+\t__attribute__ ((section (".priv_data")));
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_parent_priv_test0[sizeof(struct dm_test_parent_data)]
+\t__attribute__ ((section (".priv_data")));
+
+DM_DEVICE_INST(test0) = {
+\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_fdt_test),
+\t.name\t\t= "denx_u_boot_fdt_test",
+\t.plat_\t\t= &_denx_u_boot_fdt_test_plat_test0,
+\t.parent_plat_\t= _denx_u_boot_fdt_test_parent_plat_test0,
+\t.driver_data\t= DM_TEST_TYPE_SECOND,
+\t.parent\t\t= DM_DEVICE_REF(some_bus),
+\t.priv_\t\t= _denx_u_boot_fdt_test_priv_test0,
+\t.uclass\t\t= DM_UCLASS_REF(testfdt),
+\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test0,
+\t.uclass_node\t= {
+\t\t.prev = &DM_DEVICE_REF(test)->uclass_node,
+\t\t.next = &DM_UCLASS_REF(testfdt)->dev_head,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(test0)->child_head,
+\t\t.next = &DM_DEVICE_REF(test0)->child_head,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(test)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(some_bus)->child_head,
+\t},
+\t.seq_ = 2,
+};
+
+'''
 
     def test_simple(self):
         """Test output from some simple nodes with various types of data"""
@@ -299,10 +823,18 @@ U_BOOT_DRVINFO(spl_test3) = {
 
         self._check_strings(self.platdata_text, data)
 
+        self.run_test(['decl'], dtb_file, output)
+        with open(output) as infile:
+            data = infile.read()
+
+        self._check_strings(self.decl_text, data)
+
         # Try the 'all' command
         self.run_test(['all'], dtb_file, output)
         data = tools.ReadFile(output, binary=False)
-        self._check_strings(self.platdata_text + self.struct_text, data)
+        self._check_strings(
+            self.decl_text + self.device_text + self.platdata_text +
+            self.struct_text + self.uclass_text, data)
 
     def test_driver_alias(self):
         """Test output from a device tree file with a driver alias"""
@@ -323,7 +855,19 @@ struct dtd_sandbox_gpio {
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
-/* Node /gpios@0 index 0 */
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: gpios_at_0           sandbox_gpio
+ * ---  -------------------- --------------------
+ */
+
+/*
+ * Node /gpios@0 index 0
+ * driver sandbox_gpio parent None
+ */
 static struct dtd_sandbox_gpio dtv_gpios_at_0 = {
 \t.gpio_bank_name\t\t= "a",
 \t.gpio_controller\t= true,
@@ -331,7 +875,7 @@ static struct dtd_sandbox_gpio dtv_gpios_at_0 = {
 };
 U_BOOT_DRVINFO(gpios_at_0) = {
 \t.name\t\t= "sandbox_gpio",
-\t.plat\t= &dtv_gpios_at_0,
+\t.plat\t\t= &dtv_gpios_at_0,
 \t.plat_size\t= sizeof(dtv_gpios_at_0),
 \t.parent_idx\t= -1,
 };
@@ -343,7 +887,9 @@ U_BOOT_DRVINFO(gpios_at_0) = {
         dtb_file = get_dtb_file('dtoc_test_invalid_driver.dts')
         output = tools.GetOutputFilename('output')
         with test_util.capture_sys_output() as _:
-            dtb_platdata.run_steps(['struct'], dtb_file, False, output, [])
+            dtb_platdata.run_steps(
+                ['struct'], dtb_file, False, output, [], None, False,
+                scan=copy_scan())
         with open(output) as infile:
             data = infile.read()
         self._check_strings(HEADER + '''
@@ -352,16 +898,27 @@ struct dtd_invalid {
 ''', data)
 
         with test_util.capture_sys_output() as _:
-            dtb_platdata.run_steps(['platdata'], dtb_file, False, output, [])
+            dtb_platdata.run_steps(
+                ['platdata'], dtb_file, False, output, [], None, False,
+                scan=copy_scan())
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: spl_test             invalid
+ * ---  -------------------- --------------------
+ */
+
 /* Node /spl-test index 0 */
 static struct dtd_invalid dtv_spl_test = {
 };
 U_BOOT_DRVINFO(spl_test) = {
 \t.name\t\t= "invalid",
-\t.plat\t= &dtv_spl_test,
+\t.plat\t\t= &dtv_spl_test,
 \t.plat_size\t= sizeof(dtv_spl_test),
 \t.parent_idx\t= -1,
 };
@@ -388,13 +945,26 @@ struct dtd_target {
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: phandle2_target      target
+ *   1: phandle3_target      target
+ *   2: phandle_source       source
+ *   3: phandle_source2      source
+ *   4: phandle_target       target
+ * ---  -------------------- --------------------
+ */
+
 /* Node /phandle2-target index 0 */
 static struct dtd_target dtv_phandle2_target = {
 \t.intval\t\t\t= 0x1,
 };
 U_BOOT_DRVINFO(phandle2_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle2_target,
+\t.plat\t\t= &dtv_phandle2_target,
 \t.plat_size\t= sizeof(dtv_phandle2_target),
 \t.parent_idx\t= -1,
 };
@@ -405,7 +975,7 @@ static struct dtd_target dtv_phandle3_target = {
 };
 U_BOOT_DRVINFO(phandle3_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle3_target,
+\t.plat\t\t= &dtv_phandle3_target,
 \t.plat_size\t= sizeof(dtv_phandle3_target),
 \t.parent_idx\t= -1,
 };
@@ -420,7 +990,7 @@ static struct dtd_source dtv_phandle_source = {
 };
 U_BOOT_DRVINFO(phandle_source) = {
 \t.name\t\t= "source",
-\t.plat\t= &dtv_phandle_source,
+\t.plat\t\t= &dtv_phandle_source,
 \t.plat_size\t= sizeof(dtv_phandle_source),
 \t.parent_idx\t= -1,
 };
@@ -432,7 +1002,7 @@ static struct dtd_source dtv_phandle_source2 = {
 };
 U_BOOT_DRVINFO(phandle_source2) = {
 \t.name\t\t= "source",
-\t.plat\t= &dtv_phandle_source2,
+\t.plat\t\t= &dtv_phandle_source2,
 \t.plat_size\t= sizeof(dtv_phandle_source2),
 \t.parent_idx\t= -1,
 };
@@ -443,7 +1013,7 @@ static struct dtd_target dtv_phandle_target = {
 };
 U_BOOT_DRVINFO(phandle_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle_target,
+\t.plat\t\t= &dtv_phandle_target,
 \t.plat_size\t= sizeof(dtv_phandle_target),
 \t.parent_idx\t= -1,
 };
@@ -474,6 +1044,16 @@ struct dtd_target {
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: phandle_source2      source
+ *   1: phandle_target       target
+ * ---  -------------------- --------------------
+ */
+
 /* Node /phandle-source2 index 0 */
 static struct dtd_source dtv_phandle_source2 = {
 \t.clocks\t\t\t= {
@@ -481,7 +1061,7 @@ static struct dtd_source dtv_phandle_source2 = {
 };
 U_BOOT_DRVINFO(phandle_source2) = {
 \t.name\t\t= "source",
-\t.plat\t= &dtv_phandle_source2,
+\t.plat\t\t= &dtv_phandle_source2,
 \t.plat_size\t= sizeof(dtv_phandle_source2),
 \t.parent_idx\t= -1,
 };
@@ -491,7 +1071,7 @@ static struct dtd_target dtv_phandle_target = {
 };
 U_BOOT_DRVINFO(phandle_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle_target,
+\t.plat\t\t= &dtv_phandle_target,
 \t.plat_size\t= sizeof(dtv_phandle_target),
 \t.parent_idx\t= -1,
 };
@@ -502,17 +1082,32 @@ U_BOOT_DRVINFO(phandle_target) = {
         """Test that phandle targets are generated when unsing cd-gpios"""
         dtb_file = get_dtb_file('dtoc_test_phandle_cd_gpios.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output, [], True)
+        dtb_platdata.run_steps(
+            ['platdata'], dtb_file, False, output, [], None, False,
+            warning_disabled=True, scan=copy_scan())
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: phandle2_target      target
+ *   1: phandle3_target      target
+ *   2: phandle_source       source
+ *   3: phandle_source2      source
+ *   4: phandle_target       target
+ * ---  -------------------- --------------------
+ */
+
 /* Node /phandle2-target index 0 */
 static struct dtd_target dtv_phandle2_target = {
 \t.intval\t\t\t= 0x1,
 };
 U_BOOT_DRVINFO(phandle2_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle2_target,
+\t.plat\t\t= &dtv_phandle2_target,
 \t.plat_size\t= sizeof(dtv_phandle2_target),
 \t.parent_idx\t= -1,
 };
@@ -523,7 +1118,7 @@ static struct dtd_target dtv_phandle3_target = {
 };
 U_BOOT_DRVINFO(phandle3_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle3_target,
+\t.plat\t\t= &dtv_phandle3_target,
 \t.plat_size\t= sizeof(dtv_phandle3_target),
 \t.parent_idx\t= -1,
 };
@@ -538,7 +1133,7 @@ static struct dtd_source dtv_phandle_source = {
 };
 U_BOOT_DRVINFO(phandle_source) = {
 \t.name\t\t= "source",
-\t.plat\t= &dtv_phandle_source,
+\t.plat\t\t= &dtv_phandle_source,
 \t.plat_size\t= sizeof(dtv_phandle_source),
 \t.parent_idx\t= -1,
 };
@@ -550,7 +1145,7 @@ static struct dtd_source dtv_phandle_source2 = {
 };
 U_BOOT_DRVINFO(phandle_source2) = {
 \t.name\t\t= "source",
-\t.plat\t= &dtv_phandle_source2,
+\t.plat\t\t= &dtv_phandle_source2,
 \t.plat_size\t= sizeof(dtv_phandle_source2),
 \t.parent_idx\t= -1,
 };
@@ -561,7 +1156,7 @@ static struct dtd_target dtv_phandle_target = {
 };
 U_BOOT_DRVINFO(phandle_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle_target,
+\t.plat\t\t= &dtv_phandle_target,
 \t.plat_size\t= sizeof(dtv_phandle_target),
 \t.parent_idx\t= -1,
 };
@@ -611,13 +1206,24 @@ struct dtd_test3 {
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: test1                test1
+ *   1: test2                test2
+ *   2: test3                test3
+ * ---  -------------------- --------------------
+ */
+
 /* Node /test1 index 0 */
 static struct dtd_test1 dtv_test1 = {
 \t.reg\t\t\t= {0x1234, 0x5678},
 };
 U_BOOT_DRVINFO(test1) = {
 \t.name\t\t= "test1",
-\t.plat\t= &dtv_test1,
+\t.plat\t\t= &dtv_test1,
 \t.plat_size\t= sizeof(dtv_test1),
 \t.parent_idx\t= -1,
 };
@@ -628,7 +1234,7 @@ static struct dtd_test2 dtv_test2 = {
 };
 U_BOOT_DRVINFO(test2) = {
 \t.name\t\t= "test2",
-\t.plat\t= &dtv_test2,
+\t.plat\t\t= &dtv_test2,
 \t.plat_size\t= sizeof(dtv_test2),
 \t.parent_idx\t= -1,
 };
@@ -639,7 +1245,7 @@ static struct dtd_test3 dtv_test3 = {
 };
 U_BOOT_DRVINFO(test3) = {
 \t.name\t\t= "test3",
-\t.plat\t= &dtv_test3,
+\t.plat\t\t= &dtv_test3,
 \t.plat_size\t= sizeof(dtv_test3),
 \t.parent_idx\t= -1,
 };
@@ -666,13 +1272,23 @@ struct dtd_test2 {
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: test1                test1
+ *   1: test2                test2
+ * ---  -------------------- --------------------
+ */
+
 /* Node /test1 index 0 */
 static struct dtd_test1 dtv_test1 = {
 \t.reg\t\t\t= {0x1234, 0x5678},
 };
 U_BOOT_DRVINFO(test1) = {
 \t.name\t\t= "test1",
-\t.plat\t= &dtv_test1,
+\t.plat\t\t= &dtv_test1,
 \t.plat_size\t= sizeof(dtv_test1),
 \t.parent_idx\t= -1,
 };
@@ -683,7 +1299,7 @@ static struct dtd_test2 dtv_test2 = {
 };
 U_BOOT_DRVINFO(test2) = {
 \t.name\t\t= "test2",
-\t.plat\t= &dtv_test2,
+\t.plat\t\t= &dtv_test2,
 \t.plat_size\t= sizeof(dtv_test2),
 \t.parent_idx\t= -1,
 };
@@ -713,13 +1329,24 @@ struct dtd_test3 {
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: test1                test1
+ *   1: test2                test2
+ *   2: test3                test3
+ * ---  -------------------- --------------------
+ */
+
 /* Node /test1 index 0 */
 static struct dtd_test1 dtv_test1 = {
 \t.reg\t\t\t= {0x123400000000, 0x5678},
 };
 U_BOOT_DRVINFO(test1) = {
 \t.name\t\t= "test1",
-\t.plat\t= &dtv_test1,
+\t.plat\t\t= &dtv_test1,
 \t.plat_size\t= sizeof(dtv_test1),
 \t.parent_idx\t= -1,
 };
@@ -730,7 +1357,7 @@ static struct dtd_test2 dtv_test2 = {
 };
 U_BOOT_DRVINFO(test2) = {
 \t.name\t\t= "test2",
-\t.plat\t= &dtv_test2,
+\t.plat\t\t= &dtv_test2,
 \t.plat_size\t= sizeof(dtv_test2),
 \t.parent_idx\t= -1,
 };
@@ -741,7 +1368,7 @@ static struct dtd_test3 dtv_test3 = {
 };
 U_BOOT_DRVINFO(test3) = {
 \t.name\t\t= "test3",
-\t.plat\t= &dtv_test3,
+\t.plat\t\t= &dtv_test3,
 \t.plat_size\t= sizeof(dtv_test3),
 \t.parent_idx\t= -1,
 };
@@ -771,13 +1398,24 @@ struct dtd_test3 {
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: test1                test1
+ *   1: test2                test2
+ *   2: test3                test3
+ * ---  -------------------- --------------------
+ */
+
 /* Node /test1 index 0 */
 static struct dtd_test1 dtv_test1 = {
 \t.reg\t\t\t= {0x1234, 0x567800000000},
 };
 U_BOOT_DRVINFO(test1) = {
 \t.name\t\t= "test1",
-\t.plat\t= &dtv_test1,
+\t.plat\t\t= &dtv_test1,
 \t.plat_size\t= sizeof(dtv_test1),
 \t.parent_idx\t= -1,
 };
@@ -788,7 +1426,7 @@ static struct dtd_test2 dtv_test2 = {
 };
 U_BOOT_DRVINFO(test2) = {
 \t.name\t\t= "test2",
-\t.plat\t= &dtv_test2,
+\t.plat\t\t= &dtv_test2,
 \t.plat_size\t= sizeof(dtv_test2),
 \t.parent_idx\t= -1,
 };
@@ -799,7 +1437,7 @@ static struct dtd_test3 dtv_test3 = {
 };
 U_BOOT_DRVINFO(test3) = {
 \t.name\t\t= "test3",
-\t.plat\t= &dtv_test3,
+\t.plat\t\t= &dtv_test3,
 \t.plat_size\t= sizeof(dtv_test3),
 \t.parent_idx\t= -1,
 };
@@ -845,24 +1483,40 @@ struct dtd_sandbox_spl_test {
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
-/* Node /spl-test index 0 */
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: spl_test             sandbox_spl_test
+ *   1: spl_test2            sandbox_spl_test
+ * ---  -------------------- --------------------
+ */
+
+/*
+ * Node /spl-test index 0
+ * driver sandbox_spl_test parent None
+ */
 static struct dtd_sandbox_spl_test dtv_spl_test = {
 \t.intval\t\t\t= 0x1,
 };
 U_BOOT_DRVINFO(spl_test) = {
 \t.name\t\t= "sandbox_spl_test",
-\t.plat\t= &dtv_spl_test,
+\t.plat\t\t= &dtv_spl_test,
 \t.plat_size\t= sizeof(dtv_spl_test),
 \t.parent_idx\t= -1,
 };
 
-/* Node /spl-test2 index 1 */
+/*
+ * Node /spl-test2 index 1
+ * driver sandbox_spl_test parent None
+ */
 static struct dtd_sandbox_spl_test dtv_spl_test2 = {
 \t.intarray\t\t= 0x5,
 };
 U_BOOT_DRVINFO(spl_test2) = {
 \t.name\t\t= "sandbox_spl_test",
-\t.plat\t= &dtv_spl_test2,
+\t.plat\t\t= &dtv_spl_test2,
 \t.plat_size\t= sizeof(dtv_spl_test2),
 \t.parent_idx\t= -1,
 };
@@ -882,7 +1536,9 @@ U_BOOT_DRVINFO(spl_test2) = {
         output = tools.GetOutputFilename('output')
         self.run_test(['all'], dtb_file, output)
         data = tools.ReadFile(output, binary=False)
-        self._check_strings(self.platdata_text + self.struct_text, data)
+        self._check_strings(
+            self.decl_text + self.device_text + self.platdata_text +
+            self.struct_text + self.uclass_text, data)
 
     def test_no_command(self):
         """Test running dtoc without a command"""
@@ -897,13 +1553,16 @@ U_BOOT_DRVINFO(spl_test2) = {
         output = tools.GetOutputFilename('output')
         with self.assertRaises(ValueError) as exc:
             self.run_test(['invalid-cmd'], dtb_file, output)
-        self.assertIn("Unknown command 'invalid-cmd': (use: platdata, struct)",
-                      str(exc.exception))
+        self.assertIn(
+            "Unknown command 'invalid-cmd': (use: decl, platdata, struct)",
+            str(exc.exception))
 
     def test_output_conflict(self):
         """Test a conflict between and output dirs and output file"""
         with self.assertRaises(ValueError) as exc:
-            dtb_platdata.run_steps(['all'], None, False, 'out', ['cdir'], True)
+            dtb_platdata.run_steps(
+                ['all'], None, False, 'out', ['cdir'], None, False,
+                warning_disabled=True, scan=copy_scan())
         self.assertIn("Must specify either output or output_dirs, not both",
                       str(exc.exception))
 
@@ -919,11 +1578,249 @@ U_BOOT_DRVINFO(spl_test2) = {
         fnames = glob.glob(outdir + '/*')
         self.assertEqual(2, len(fnames))
 
-        dtb_platdata.run_steps(['all'], dtb_file, False, None, [outdir], True)
+        dtb_platdata.run_steps(
+            ['all'], dtb_file, False, None, [outdir], None, False,
+            warning_disabled=True, scan=copy_scan())
         fnames = glob.glob(outdir + '/*')
-        self.assertEqual(4, len(fnames))
+        self.assertEqual(7, len(fnames))
 
         leafs = set(os.path.basename(fname) for fname in fnames)
         self.assertEqual(
-            {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb'},
+            {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb',
+             'dt-uclass.c', 'dt-decl.h', 'dt-device.c'},
             leafs)
+
+    def setup_process_test(self):
+        """Set up a test of process_nodes()
+
+        This uses saved_scan but returns a deep copy of it, so it is safe to
+        modify it in these tests
+
+        Returns:
+            tuple:
+                DtbPlatdata: object to test
+                Scanner: scanner to use
+        """
+        dtb_file = get_dtb_file('dtoc_test_simple.dts')
+        output = tools.GetOutputFilename('output')
+
+        # Take a copy before messing with it
+        scan = copy_scan()
+        plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False)
+        plat.scan_dtb()
+        plat.scan_tree(False)
+        plat.prepare_nodes()
+        return plat, scan
+
+    def test_process_nodes(self):
+        """Test processing nodes to add various info"""
+        plat, scan = self.setup_process_test()
+        plat.process_nodes(True)
+
+        i2c_node = plat._fdt.GetNode('/i2c@0')
+        pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9')
+        pmic = scan._drivers['sandbox_pmic']
+        i2c = scan._drivers['sandbox_i2c']
+        self.assertEqual('DM_DEVICE_REF(pmic_at_9)', pmic_node.dev_ref)
+        self.assertEqual(pmic, pmic_node.driver)
+        self.assertEqual(i2c_node, pmic_node.parent)
+        self.assertEqual(i2c, pmic_node.parent_driver)
+
+        # The pmic is the only child
+        self.assertEqual(pmic_node.parent_seq, 0)
+        self.assertEqual([pmic_node], i2c_node.child_devs)
+
+        # Start and end of the list should be the child_head
+        ref = '&DM_DEVICE_REF(i2c_at_0)->child_head'
+        self.assertEqual(
+            {-1: ref, 0: '&DM_DEVICE_REF(pmic_at_9)->sibling_node', 1: ref},
+            i2c_node.child_refs)
+
+    def test_process_nodes_bad_parent(self):
+        # Pretend that i2c has a parent (the pmic) and delete that driver
+        plat, scan = self.setup_process_test()
+
+        i2c_node = plat._fdt.GetNode('/i2c@0')
+        pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9')
+        del scan._drivers['sandbox_pmic']
+        i2c_node.parent = pmic_node
+
+        # Process twice, the second time to generate an exception
+        plat.process_nodes(False)
+        with self.assertRaises(ValueError) as exc:
+            plat.process_nodes(True)
+        self.assertIn(
+            "Cannot parse/find parent driver 'sandbox_pmic' for 'sandbox_i2c",
+            str(exc.exception))
+
+    def test_process_nodes_bad_node(self):
+        plat, scan = self.setup_process_test()
+
+        # Now remove the pmic driver
+        del scan._drivers['sandbox_pmic']
+
+        # Process twice, the second time to generate an exception
+        plat.process_nodes(False)
+        with self.assertRaises(ValueError) as exc:
+            plat.process_nodes(True)
+        self.assertIn("Cannot parse/find driver for 'sandbox_pmic",
+                      str(exc.exception))
+
+    def test_process_nodes_bad_uclass(self):
+        plat, scan = self.setup_process_test()
+
+        self.assertIn('UCLASS_I2C', scan._uclass)
+        del scan._uclass['UCLASS_I2C']
+        with self.assertRaises(ValueError) as exc:
+            plat.process_nodes(True)
+        self.assertIn("Cannot parse/find uclass 'UCLASS_I2C' for driver 'sandbox_i2c'",
+                      str(exc.exception))
+
+    def test_process_nodes_used(self):
+        """Test processing nodes to add various info"""
+        plat, scan = self.setup_process_test()
+        plat.process_nodes(True)
+
+        pmic = scan._drivers['sandbox_pmic']
+        self.assertTrue(pmic.used)
+
+        gpio = scan._drivers['sandbox_gpio']
+        self.assertFalse(gpio.used)
+
+    def test_alias_read(self):
+        """Test obtaining aliases"""
+        dtb_file = get_dtb_file('dtoc_test_inst.dts')
+        output = tools.GetOutputFilename('output')
+        plat = self.run_test(['struct'], dtb_file, output)
+
+        scan = plat._scan
+        testfdt_node = plat._fdt.GetNode('/some-bus/test')
+        test0_node = plat._fdt.GetNode('/some-bus/test0')
+        self.assertIn('UCLASS_TEST_FDT', scan._uclass)
+        uc = scan._uclass['UCLASS_TEST_FDT']
+        self.assertEqual({1: testfdt_node, 2: test0_node},
+                         uc.alias_num_to_node)
+        self.assertEqual({'/some-bus/test': 1, '/some-bus/test0': 2},
+                         uc.alias_path_to_num)
+
+        # Try adding an alias that doesn't exist
+        self.assertFalse(scan.add_uclass_alias('fred', 3, None))
+
+        # Try adding an alias for a missing node
+        self.assertIsNone(scan.add_uclass_alias('testfdt', 3, None))
+
+    def test_alias_read_bad(self):
+        """Test invalid alias property name"""
+        dtb_file = get_dtb_file('dtoc_test_alias_bad.dts')
+        output = tools.GetOutputFilename('output')
+        with self.assertRaises(ValueError) as exc:
+            plat = self.run_test(['struct'], dtb_file, output)
+        self.assertIn("Cannot decode alias 'i2c4-'", str(exc.exception))
+
+    def test_alias_read_bad_path(self):
+        """Test alias pointing to a non-existent node"""
+        # This line may produce a warning, so capture it:
+        # Warning (alias_paths): /aliases:i2c4: aliases property is not a valid
+        #    node (/does/not/exist)
+        dtb_file = get_dtb_file('dtoc_test_alias_bad_path.dts', True)
+
+        output = tools.GetOutputFilename('output')
+        with self.assertRaises(ValueError) as exc:
+            plat = self.run_test(['struct'], dtb_file, output)
+        self.assertIn("Alias 'i2c4' path '/does/not/exist' not found",
+                      str(exc.exception))
+
+    def test_alias_read_bad_uclass(self):
+        """Test alias for a uclass that doesn't exist"""
+        dtb_file = get_dtb_file('dtoc_test_alias_bad_uc.dts')
+        output = tools.GetOutputFilename('output')
+        with test_util.capture_sys_output() as (stdout, _):
+            plat = self.run_test(['struct'], dtb_file, output)
+        self.assertEqual("Could not find uclass for alias 'other1'",
+                         stdout.getvalue().strip())
+
+    def test_sequence(self):
+        """Test assignment of sequence numnbers"""
+        dtb_file = get_dtb_file('dtoc_test_inst.dts')
+        output = tools.GetOutputFilename('output')
+        plat = self.run_test(['struct'], dtb_file, output)
+
+        scan = plat._scan
+        testfdt = plat._fdt.GetNode('/some-bus/test')
+        self.assertEqual(1, testfdt.seq)
+        i2c = plat._fdt.GetNode('/i2c')
+
+        # For now this uclass is not compiled in, so no sequence is assigned
+        self.assertEqual(4, i2c.seq)
+        spl = plat._fdt.GetNode('/spl-test')
+        self.assertEqual(0, spl.seq)
+
+    def test_process_root(self):
+        """Test assignment of sequence numnbers"""
+        dtb_file = get_dtb_file('dtoc_test_simple.dts')
+        output = tools.GetOutputFilename('output')
+
+        # Take a copy before messing with it
+        scan = copy_scan()
+        plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False)
+        plat.scan_dtb()
+        root = plat._fdt.GetRoot()
+
+        plat.scan_tree(False)
+        self.assertNotIn(root, plat._valid_nodes)
+
+        plat.scan_tree(True)
+        self.assertIn(root, plat._valid_nodes)
+        self.assertEqual('root_driver',
+                         scan.get_normalized_compat_name(root)[0])
+
+    def test_simple_inst(self):
+        """Test output from some simple nodes with instantiate enabled"""
+        dtb_file = get_dtb_file('dtoc_test_inst.dts')
+        output = tools.GetOutputFilename('output')
+
+        self.run_test(['decl'], dtb_file, output, True)
+        with open(output) as infile:
+            data = infile.read()
+
+        self._check_strings(self.decl_text_inst, data)
+
+        self.run_test(['platdata'], dtb_file, output, True)
+        with open(output) as infile:
+            data = infile.read()
+
+        self._check_strings(C_HEADER_PRE + '''
+/* This file is not used: --instantiate was enabled */
+''', data)
+
+        self.run_test(['uclass'], dtb_file, output, True)
+        with open(output) as infile:
+            data = infile.read()
+
+        self._check_strings(UCLASS_HEADER_COMMON + self.uclass_text_inst, data)
+
+        self.run_test(['device'], dtb_file, output, True)
+        with open(output) as infile:
+            data = infile.read()
+
+        self._check_strings(self.device_text_inst, data)
+
+    def test_inst_no_hdr(self):
+        """Test dealing with a struct tsssshat has no header"""
+        dtb_file = get_dtb_file('dtoc_test_inst.dts')
+        output = tools.GetOutputFilename('output')
+
+        # Run it once to set everything up
+        plat = self.run_test(['decl'], dtb_file, output, True)
+        scan = plat._scan
+
+        # Restart the output file and delete any record of the uclass' struct
+        plat.setup_output(Ftype.SOURCE, output)
+        del scan._structs['dm_test_uc_priv']
+
+        # Now generate the uclasses, which should provide a warning
+        with test_util.capture_sys_output() as (stdout, _):
+            plat.generate_uclasses()
+        self.assertEqual(
+            'Warning: Cannot find header file for struct dm_test_uc_priv',
+            stdout.getvalue().strip())
index e8fbbd5..856392b 100755 (executable)
@@ -48,6 +48,17 @@ def _GetPropertyValue(dtb, node, prop_name):
     data = dtb.GetContents()[offset:offset + len(prop.value)]
     return prop, [chr(x) for x in data]
 
+def find_dtb_file(dts_fname):
+    """Locate a test file in the test/ directory
+
+    Args:
+        dts_fname (str): Filename to find, e.g. 'dtoc_test_simple.dts]
+
+    Returns:
+        str: Path to the test filename
+    """
+    return os.path.join('tools/dtoc/test', dts_fname)
+
 
 class TestFdt(unittest.TestCase):
     """Tests for the Fdt module
@@ -64,7 +75,7 @@ class TestFdt(unittest.TestCase):
         tools.FinaliseOutputDir()
 
     def setUp(self):
-        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
+        self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
 
     def testFdt(self):
         """Test that we can open an Fdt"""
@@ -141,8 +152,9 @@ class TestNode(unittest.TestCase):
         tools.FinaliseOutputDir()
 
     def setUp(self):
-        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
+        self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
         self.node = self.dtb.GetNode('/spl-test')
+        self.fdt = self.dtb.GetFdtObj()
 
     def testOffset(self):
         """Tests that we can obtain the offset of a node"""
@@ -186,7 +198,7 @@ class TestNode(unittest.TestCase):
     def testRefreshExtraNode(self):
         """Test refreshing offsets when an expected node is missing"""
         # Delete it from the device tre, not our tables
-        self.dtb.GetFdtObj().del_node(self.node.Offset())
+        self.fdt.del_node(self.node.Offset())
         with self.assertRaises(ValueError) as e:
             self.dtb.Refresh()
         self.assertIn('Internal error, node name mismatch '
@@ -198,17 +210,77 @@ class TestNode(unittest.TestCase):
         del self.node.props['notstring']
         with self.assertRaises(ValueError) as e:
             self.dtb.Refresh()
-        self.assertIn("Internal error, property 'notstring' missing, offset ",
+        self.assertIn("Internal error, node '/spl-test' 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')
+        dtb = fdt.FdtScan(find_dtb_file('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)))
 
+    def testAddNodeSpace(self):
+        """Test adding a single node when out of space"""
+        self.fdt.pack()
+        self.node.AddSubnode('subnode')
+        with self.assertRaises(libfdt.FdtException) as e:
+            self.dtb.Sync(auto_resize=False)
+        self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
+
+        self.dtb.Sync(auto_resize=True)
+        offset = self.fdt.path_offset('/spl-test/subnode')
+        self.assertTrue(offset > 0)
+
+    def testAddNodes(self):
+        """Test adding various subnode and properies"""
+        node = self.dtb.GetNode('/i2c@0')
+
+        # Add one more node next to the pmic one
+        sn1 = node.AddSubnode('node-one')
+        sn1.AddInt('integer-a', 12)
+        sn1.AddInt('integer-b', 23)
+
+        # Sync so that everything is clean
+        self.dtb.Sync(auto_resize=True)
+
+        # Add two subnodes next to pmic and node-one
+        sn2 = node.AddSubnode('node-two')
+        sn2.AddInt('integer-2a', 34)
+        sn2.AddInt('integer-2b', 45)
+
+        sn3 = node.AddSubnode('node-three')
+        sn3.AddInt('integer-3', 123)
+
+        # Add a property to the node after i2c@0 to check that this is not
+        # disturbed by adding a subnode to i2c@0
+        orig_node = self.dtb.GetNode('/orig-node')
+        orig_node.AddInt('integer-4', 456)
+
+        # Add a property to the pmic node to check that pmic properties are not
+        # disturbed
+        pmic = self.dtb.GetNode('/i2c@0/pmic@9')
+        pmic.AddInt('integer-5', 567)
+
+        self.dtb.Sync(auto_resize=True)
+
+    def testRefreshNameMismatch(self):
+        """Test name mismatch when syncing nodes and properties"""
+        prop = self.node.AddInt('integer-a', 12)
+
+        wrong_offset = self.dtb.GetNode('/i2c@0')._offset
+        self.node._offset = wrong_offset
+        with self.assertRaises(ValueError) as e:
+            self.dtb.Sync()
+        self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'",
+                      str(e.exception))
+
+        with self.assertRaises(ValueError) as e:
+            self.node.Refresh(wrong_offset)
+        self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'",
+                      str(e.exception))
+
 
 class TestProp(unittest.TestCase):
     """Test operation of the Prop class"""
@@ -222,7 +294,7 @@ class TestProp(unittest.TestCase):
         tools.FinaliseOutputDir()
 
     def setUp(self):
-        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
+        self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
         self.node = self.dtb.GetNode('/spl-test')
         self.fdt = self.dtb.GetFdtObj()
 
@@ -230,7 +302,7 @@ class TestProp(unittest.TestCase):
         self.assertEqual(None, self.dtb.GetNode('missing'))
 
     def testPhandle(self):
-        dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+        dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
         node = dtb.GetNode('/phandle-source2')
         prop = node.props['clocks']
         self.assertTrue(fdt32_to_cpu(prop.value) > 0)
@@ -374,17 +446,6 @@ class TestProp(unittest.TestCase):
         self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
         self.dtb.Sync(auto_resize=True)
 
-    def testAddNode(self):
-        self.fdt.pack()
-        self.node.AddSubnode('subnode')
-        with self.assertRaises(libfdt.FdtException) as e:
-            self.dtb.Sync(auto_resize=False)
-        self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
-
-        self.dtb.Sync(auto_resize=True)
-        offset = self.fdt.path_offset('/spl-test/subnode')
-        self.assertTrue(offset > 0)
-
     def testAddMore(self):
         """Test various other methods for adding and setting properties"""
         self.node.AddZeroProp('one')
@@ -488,7 +549,7 @@ class TestFdtUtil(unittest.TestCase):
         tools.FinaliseOutputDir()
 
     def setUp(self):
-        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
+        self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
         self.node = self.dtb.GetNode('/spl-test')
 
     def testGetInt(self):
@@ -531,7 +592,7 @@ class TestFdtUtil(unittest.TestCase):
                       str(e.exception))
 
     def testGetPhandleList(self):
-        dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+        dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
         node = dtb.GetNode('/phandle-source2')
         self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
         node = dtb.GetNode('/phandle-source')
@@ -551,7 +612,7 @@ class TestFdtUtil(unittest.TestCase):
         self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
         self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
 
-        dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts')
+        dtb2 = fdt.FdtScan(find_dtb_file('dtoc_test_addr64.dts'))
         node1 = dtb2.GetNode('/test1')
         val = node1.props['reg'].value
         self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
@@ -565,7 +626,7 @@ class TestFdtUtil(unittest.TestCase):
 
     def testEnsureCompiled(self):
         """Test a degenerate case of this function (file already compiled)"""
-        dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts')
+        dtb = fdt_util.EnsureCompiled(find_dtb_file('dtoc_test_simple.dts'))
         self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
 
     def testEnsureCompiledTmpdir(self):
@@ -574,7 +635,7 @@ class TestFdtUtil(unittest.TestCase):
             old_outdir = tools.outdir
             tools.outdir= None
             tmpdir = tempfile.mkdtemp(prefix='test_fdt.')
-            dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts',
+            dtb = fdt_util.EnsureCompiled(find_dtb_file('dtoc_test_simple.dts'),
                                           tmpdir)
             self.assertEqual(tmpdir, os.path.dirname(dtb))
             shutil.rmtree(tmpdir)
index 7d68653..0af86dc 100644 (file)
@@ -7,6 +7,7 @@
 This includes unit tests for scanning of the source code
 """
 
+import copy
 import os
 import shutil
 import tempfile
@@ -17,6 +18,20 @@ from dtoc import src_scan
 from patman import test_util
 from patman import tools
 
+OUR_PATH = os.path.dirname(os.path.realpath(__file__))
+
+class FakeNode:
+    """Fake Node object for testing"""
+    def __init__(self):
+        self.name = None
+        self.props = {}
+
+class FakeProp:
+    """Fake Prop object for testing"""
+    def __init__(self):
+        self.name = None
+        self.value = None
+
 # This is a test so is allowed to access private things in the module it is
 # testing
 # pylint: disable=W0212
@@ -44,7 +59,8 @@ class TestSrcScan(unittest.TestCase):
     def test_additional(self):
         """Test with additional drivers to scan"""
         scan = src_scan.Scanner(
-            None, True, [None, '', 'tools/dtoc/dtoc_test_scan_drivers.cxx'])
+            None, True,
+            [None, '', 'tools/dtoc/test/dtoc_test_scan_drivers.cxx'])
         scan.scan_drivers()
         self.assertIn('sandbox_gpio_alias2', scan._driver_aliases)
         self.assertEqual('sandbox_gpio',
@@ -69,10 +85,22 @@ class TestSrcScan(unittest.TestCase):
 
     def test_driver(self):
         """Test the Driver class"""
-        drv1 = src_scan.Driver('fred')
-        drv2 = src_scan.Driver('mary')
-        drv3 = src_scan.Driver('fred')
-        self.assertEqual("Driver(name='fred')", str(drv1))
+        i2c = 'I2C_UCLASS'
+        compat = {'rockchip,rk3288-grf': 'ROCKCHIP_SYSCON_GRF',
+                  'rockchip,rk3288-srf': None}
+        drv1 = src_scan.Driver('fred', 'fred.c')
+        drv2 = src_scan.Driver('mary', 'mary.c')
+        drv3 = src_scan.Driver('fred', 'fred.c')
+        drv1.uclass_id = i2c
+        drv1.compat = compat
+        drv2.uclass_id = i2c
+        drv2.compat = compat
+        drv3.uclass_id = i2c
+        drv3.compat = compat
+        self.assertEqual(
+            "Driver(name='fred', used=False, uclass_id='I2C_UCLASS', "
+            "compat={'rockchip,rk3288-grf': 'ROCKCHIP_SYSCON_GRF', "
+            "'rockchip,rk3288-srf': None}, priv=)", str(drv1))
         self.assertEqual(drv1, drv3)
         self.assertNotEqual(drv1, drv2)
         self.assertNotEqual(drv2, drv3)
@@ -91,7 +119,9 @@ class TestSrcScan(unittest.TestCase):
 
             fname_list = []
             add_file('fname.c')
+            add_file('.git/ignoreme.c')
             add_file('dir/fname2.c')
+            add_file('build-sandbox/ignoreme2.c')
 
             # Mock out scan_driver and check that it is called with the
             # expected files
@@ -101,7 +131,362 @@ class TestSrcScan(unittest.TestCase):
             self.assertEqual(2, len(mocked.mock_calls))
             self.assertEqual(mock.call(fname_list[0]),
                              mocked.mock_calls[0])
-            self.assertEqual(mock.call(fname_list[1]),
+            # .git file should be ignored
+            self.assertEqual(mock.call(fname_list[2]),
                              mocked.mock_calls[1])
         finally:
             shutil.rmtree(indir)
+
+    def test_scan(self):
+        """Test scanning of a driver"""
+        fname = os.path.join(OUR_PATH, '..', '..', 'drivers/i2c/tegra_i2c.c')
+        buff = tools.ReadFile(fname, False)
+        scan = src_scan.Scanner(None, False, None)
+        scan._parse_driver(fname, buff)
+        self.assertIn('i2c_tegra', scan._drivers)
+        drv = scan._drivers['i2c_tegra']
+        self.assertEqual('i2c_tegra', drv.name)
+        self.assertEqual('UCLASS_I2C', drv.uclass_id)
+        self.assertEqual(
+            {'nvidia,tegra114-i2c': 'TYPE_114',
+             'nvidia,tegra20-i2c': 'TYPE_STD',
+             'nvidia,tegra20-i2c-dvc': 'TYPE_DVC'}, drv.compat)
+        self.assertEqual('i2c_bus', drv.priv)
+        self.assertEqual(1, len(scan._drivers))
+
+    def test_normalized_name(self):
+        """Test operation of get_normalized_compat_name()"""
+        prop = FakeProp()
+        prop.name = 'compatible'
+        prop.value = 'rockchip,rk3288-grf'
+        node = FakeNode()
+        node.props = {'compatible': prop}
+
+        # get_normalized_compat_name() uses this to check for root node
+        node.parent = FakeNode()
+
+        scan = src_scan.Scanner(None, False, None)
+        with test_util.capture_sys_output() as (stdout, _):
+            name, aliases = scan.get_normalized_compat_name(node)
+        self.assertEqual('rockchip_rk3288_grf', name)
+        self.assertEqual([], aliases)
+        self.assertEqual(
+            'WARNING: the driver rockchip_rk3288_grf was not found in the driver list',
+            stdout.getvalue().strip())
+
+        i2c = 'I2C_UCLASS'
+        compat = {'rockchip,rk3288-grf': 'ROCKCHIP_SYSCON_GRF',
+                  'rockchip,rk3288-srf': None}
+        drv = src_scan.Driver('fred', 'fred.c')
+        drv.uclass_id = i2c
+        drv.compat = compat
+        scan._drivers['rockchip_rk3288_grf'] = drv
+
+        scan._driver_aliases['rockchip_rk3288_srf'] = 'rockchip_rk3288_grf'
+
+        with test_util.capture_sys_output() as (stdout, _):
+            name, aliases = scan.get_normalized_compat_name(node)
+        self.assertEqual('', stdout.getvalue().strip())
+        self.assertEqual('rockchip_rk3288_grf', name)
+        self.assertEqual([], aliases)
+
+        prop.value = 'rockchip,rk3288-srf'
+        with test_util.capture_sys_output() as (stdout, _):
+            name, aliases = scan.get_normalized_compat_name(node)
+        self.assertEqual('', stdout.getvalue().strip())
+        self.assertEqual('rockchip_rk3288_grf', name)
+        self.assertEqual(['rockchip_rk3288_srf'], aliases)
+
+    def test_scan_errors(self):
+        """Test detection of scanning errors"""
+        buff = '''
+static const struct udevice_id tegra_i2c_ids2[] = {
+       { .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+       { }
+};
+
+U_BOOT_DRIVER(i2c_tegra) = {
+       .name   = "i2c_tegra",
+       .id     = UCLASS_I2C,
+       .of_match = tegra_i2c_ids,
+};
+'''
+        scan = src_scan.Scanner(None, False, None)
+        with self.assertRaises(ValueError) as exc:
+            scan._parse_driver('file.c', buff)
+        self.assertIn(
+            "file.c: Unknown compatible var 'tegra_i2c_ids' (found: tegra_i2c_ids2)",
+            str(exc.exception))
+
+    def test_of_match(self):
+        """Test detection of of_match_ptr() member"""
+        buff = '''
+static const struct udevice_id tegra_i2c_ids[] = {
+       { .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+       { }
+};
+
+U_BOOT_DRIVER(i2c_tegra) = {
+       .name   = "i2c_tegra",
+       .id     = UCLASS_I2C,
+       .of_match = of_match_ptr(tegra_i2c_ids),
+};
+'''
+        scan = src_scan.Scanner(None, False, None)
+        scan._parse_driver('file.c', buff)
+        self.assertIn('i2c_tegra', scan._drivers)
+        drv = scan._drivers['i2c_tegra']
+        self.assertEqual('i2c_tegra', drv.name)
+        self.assertEqual('', drv.phase)
+        self.assertEqual([], drv.headers)
+
+    def test_priv(self):
+        """Test collection of struct info from drivers"""
+        buff = '''
+static const struct udevice_id test_ids[] = {
+       { .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+       { }
+};
+
+U_BOOT_DRIVER(testing) = {
+       .name   = "testing",
+       .id     = UCLASS_I2C,
+       .of_match = test_ids,
+       .priv_auto      = sizeof(struct some_priv),
+       .plat_auto = sizeof(struct some_plat),
+       .per_child_auto = sizeof(struct some_cpriv),
+       .per_child_plat_auto = sizeof(struct some_cplat),
+       DM_PHASE(tpl)
+       DM_HEADER(<i2c.h>)
+       DM_HEADER(<asm/clk.h>)
+};
+'''
+        scan = src_scan.Scanner(None, False, None)
+        scan._parse_driver('file.c', buff)
+        self.assertIn('testing', scan._drivers)
+        drv = scan._drivers['testing']
+        self.assertEqual('testing', drv.name)
+        self.assertEqual('UCLASS_I2C', drv.uclass_id)
+        self.assertEqual(
+            {'nvidia,tegra114-i2c': 'TYPE_114'}, drv.compat)
+        self.assertEqual('some_priv', drv.priv)
+        self.assertEqual('some_plat', drv.plat)
+        self.assertEqual('some_cpriv', drv.child_priv)
+        self.assertEqual('some_cplat', drv.child_plat)
+        self.assertEqual('tpl', drv.phase)
+        self.assertEqual(['<i2c.h>', '<asm/clk.h>'], drv.headers)
+        self.assertEqual(1, len(scan._drivers))
+
+    def test_uclass_scan(self):
+        """Test collection of uclass-driver info"""
+        buff = '''
+UCLASS_DRIVER(i2c) = {
+       .id             = UCLASS_I2C,
+       .name           = "i2c",
+       .flags          = DM_UC_FLAG_SEQ_ALIAS,
+       .priv_auto      = sizeof(struct some_priv),
+       .per_device_auto        = sizeof(struct per_dev_priv),
+       .per_device_plat_auto   = sizeof(struct per_dev_plat),
+       .per_child_auto = sizeof(struct per_child_priv),
+       .per_child_plat_auto    = sizeof(struct per_child_plat),
+       .child_post_bind = i2c_child_post_bind,
+};
+
+'''
+        scan = src_scan.Scanner(None, False, None)
+        scan._parse_uclass_driver('file.c', buff)
+        self.assertIn('UCLASS_I2C', scan._uclass)
+        drv = scan._uclass['UCLASS_I2C']
+        self.assertEqual('i2c', drv.name)
+        self.assertEqual('UCLASS_I2C', drv.uclass_id)
+        self.assertEqual('some_priv', drv.priv)
+        self.assertEqual('per_dev_priv', drv.per_dev_priv)
+        self.assertEqual('per_dev_plat', drv.per_dev_plat)
+        self.assertEqual('per_child_priv', drv.per_child_priv)
+        self.assertEqual('per_child_plat', drv.per_child_plat)
+        self.assertEqual(1, len(scan._uclass))
+
+        drv2 = copy.deepcopy(drv)
+        self.assertEqual(drv, drv2)
+        drv2.priv = 'other_priv'
+        self.assertNotEqual(drv, drv2)
+
+        # The hashes only depend on the uclass ID, so should be equal
+        self.assertEqual(drv.__hash__(), drv2.__hash__())
+
+        self.assertEqual("UclassDriver(name='i2c', uclass_id='UCLASS_I2C')",
+                         str(drv))
+
+    def test_uclass_scan_errors(self):
+        """Test detection of uclass scanning errors"""
+        buff = '''
+UCLASS_DRIVER(i2c) = {
+       .name           = "i2c",
+};
+
+'''
+        scan = src_scan.Scanner(None, False, None)
+        with self.assertRaises(ValueError) as exc:
+            scan._parse_uclass_driver('file.c', buff)
+        self.assertIn("file.c: Cannot parse uclass ID in driver 'i2c'",
+                      str(exc.exception))
+
+    def test_struct_scan(self):
+        """Test collection of struct info"""
+        buff = '''
+/* some comment */
+struct some_struct1 {
+       struct i2c_msg *msgs;
+       uint nmsgs;
+};
+'''
+        scan = src_scan.Scanner(None, False, None)
+        scan._basedir = os.path.join(OUR_PATH, '..', '..')
+        scan._parse_structs('arch/arm/include/asm/file.h', buff)
+        self.assertIn('some_struct1', scan._structs)
+        struc = scan._structs['some_struct1']
+        self.assertEqual('some_struct1', struc.name)
+        self.assertEqual('asm/file.h', struc.fname)
+
+        buff = '''
+/* another comment */
+struct another_struct {
+       int speed_hz;
+       int max_transaction_bytes;
+};
+'''
+        scan._parse_structs('include/file2.h', buff)
+        self.assertIn('another_struct', scan._structs)
+        struc = scan._structs['another_struct']
+        self.assertEqual('another_struct', struc.name)
+        self.assertEqual('file2.h', struc.fname)
+
+        self.assertEqual(2, len(scan._structs))
+
+        self.assertEqual("Struct(name='another_struct', fname='file2.h')",
+                         str(struc))
+
+    def test_struct_scan_errors(self):
+        """Test scanning a header file with an invalid unicode file"""
+        output = tools.GetOutputFilename('output.h')
+        tools.WriteFile(output, b'struct this is a test \x81 of bad unicode')
+
+        scan = src_scan.Scanner(None, False, None)
+        with test_util.capture_sys_output() as (stdout, _):
+            scan.scan_header(output)
+        self.assertIn('due to unicode error', stdout.getvalue())
+
+    def setup_dup_drivers(self, name, phase=''):
+        """Set up for a duplcate test
+
+        Returns:
+            tuple:
+                Scanner to use
+                Driver record for first driver
+                Text of second driver declaration
+                Node for driver 1
+        """
+        driver1 = '''
+static const struct udevice_id test_ids[] = {
+       { .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+       { }
+};
+
+U_BOOT_DRIVER(%s) = {
+       .name   = "testing",
+       .id     = UCLASS_I2C,
+       .of_match = test_ids,
+       %s
+};
+''' % (name, 'DM_PHASE(%s)' % phase if phase else '')
+        driver2 = '''
+static const struct udevice_id test_ids[] = {
+       { .compatible = "nvidia,tegra114-dvc" },
+       { }
+};
+
+U_BOOT_DRIVER(%s) = {
+       .name   = "testing",
+       .id     = UCLASS_RAM,
+       .of_match = test_ids,
+};
+''' % name
+        scan = src_scan.Scanner(None, False, None, phase)
+        scan._parse_driver('file1.c', driver1)
+        self.assertIn(name, scan._drivers)
+        drv1 = scan._drivers[name]
+
+        prop = FakeProp()
+        prop.name = 'compatible'
+        prop.value = 'nvidia,tegra114-i2c'
+        node = FakeNode()
+        node.name = 'testing'
+        node.props = {'compatible': prop}
+
+        # get_normalized_compat_name() uses this to check for root node
+        node.parent = FakeNode()
+
+        return scan, drv1, driver2, node
+
+    def test_dup_drivers(self):
+        """Test handling of duplicate drivers"""
+        name = 'nvidia_tegra114_i2c'
+        scan, drv1, driver2, node = self.setup_dup_drivers(name)
+        self.assertEqual('', drv1.phase)
+
+        # The driver should not have a duplicate yet
+        self.assertEqual([], drv1.dups)
+
+        scan._parse_driver('file2.c', driver2)
+
+        # The first driver should now be a duplicate of the second
+        drv2 = scan._drivers[name]
+        self.assertEqual('', drv2.phase)
+        self.assertEqual(1, len(drv2.dups))
+        self.assertEqual([drv1], drv2.dups)
+
+        # There is no way to distinguish them, so we should expect a warning
+        self.assertTrue(drv2.warn_dups)
+
+        # We should see a warning
+        with test_util.capture_sys_output() as (stdout, _):
+            scan.mark_used([node])
+        self.assertEqual(
+            "Warning: Duplicate driver name 'nvidia_tegra114_i2c' (orig=file2.c, dups=file1.c)",
+            stdout.getvalue().strip())
+
+    def test_dup_drivers_phase(self):
+        """Test handling of duplicate drivers but with different phases"""
+        name = 'nvidia_tegra114_i2c'
+        scan, drv1, driver2, node = self.setup_dup_drivers(name, 'spl')
+        scan._parse_driver('file2.c', driver2)
+        self.assertEqual('spl', drv1.phase)
+
+        # The second driver should now be a duplicate of the second
+        self.assertEqual(1, len(drv1.dups))
+        drv2 = drv1.dups[0]
+
+        # The phase is different, so we should not warn of dups
+        self.assertFalse(drv1.warn_dups)
+
+        # We should not see a warning
+        with test_util.capture_sys_output() as (stdout, _):
+            scan.mark_used([node])
+        self.assertEqual('', stdout.getvalue().strip())
+
+    def test_sequence(self):
+        """Test assignment of sequence numnbers"""
+        scan = src_scan.Scanner(None, False, None, '')
+        node = FakeNode()
+        uc = src_scan.UclassDriver('UCLASS_I2C')
+        node.uclass = uc
+        node.driver = True
+        node.seq = -1
+        node.path = 'mypath'
+        uc.alias_num_to_node[2] = node
+
+        # This should assign 3 (after the 2 that exists)
+        seq = scan.assign_seq(node)
+        self.assertEqual(3, seq)
+        self.assertEqual({'mypath': 3}, uc.alias_path_to_num)
+        self.assertEqual({2: node, 3: node}, uc.alias_num_to_node)
index e4112b8..db51246 100644 (file)
@@ -213,7 +213,7 @@ static void utilfdt_print_data(const char *data, int len)
        } else {
                printf(" = [");
                for (i = 0; i < len; i++)
-                       printf("%02x%s", *p++, i < len - 1 ? " " : "");
+                       printf("%02x%s", (unsigned char)*p++, i < len - 1 ? " " : "");
                printf("]");
        }
 }
index bde1e5d..418c5fd 100644 (file)
@@ -243,8 +243,13 @@ static const struct brom_img_type {
        }
 };
 
+/* Indicates whether we're generating or verifying */
+static bool img_gen;
+static uint32_t img_size;
+
 /* Image type selected by user */
 static enum brlyt_img_type hdr_media;
+static uint32_t hdr_offset;
 static int use_lk_hdr;
 static bool is_arm64_image;
 
@@ -275,6 +280,7 @@ static int mtk_brom_parse_imagename(const char *imagename)
 
        /* User passed arguments from image name */
        static const char *media = "";
+       static const char *hdr_offs = "";
        static const char *nandinfo = "";
        static const char *lk = "";
        static const char *arm64_param = "";
@@ -317,6 +323,9 @@ static int mtk_brom_parse_imagename(const char *imagename)
                        if (!strcmp(key, "media"))
                                media = val;
 
+                       if (!strcmp(key, "hdroffset"))
+                               hdr_offs = val;
+
                        if (!strcmp(key, "nandinfo"))
                                nandinfo = val;
 
@@ -359,6 +368,10 @@ static int mtk_brom_parse_imagename(const char *imagename)
                }
        }
 
+       /* parse device header offset */
+       if (hdr_offs && hdr_offs[0])
+               hdr_offset = strtoul(hdr_offs, NULL, 0);
+
        if (arm64_param && arm64_param[0] == '1')
                is_arm64_image = true;
 
@@ -422,6 +435,7 @@ static int mtk_image_vrec_header(struct image_tool_params *params,
 static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
 {
        union gen_boot_header *gbh = (union gen_boot_header *)ptr;
+       uint32_t gfh_offset, total_size, devh_size;
        struct brom_layout_header *bh;
        struct gfh_header *gfh;
        const char *bootmedia;
@@ -453,7 +467,32 @@ static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
            le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
                return -1;
 
-       gfh = (struct gfh_header *)(ptr + le32_to_cpu(bh->header_size));
+       devh_size = sizeof(struct gen_device_header);
+
+       if (img_gen) {
+               gfh_offset = devh_size;
+       } else {
+               gfh_offset = le32_to_cpu(bh->header_size);
+
+               if (gfh_offset + sizeof(struct gfh_header) > img_size) {
+                       /*
+                        * This may happen if the hdr_offset used to generate
+                        * this image is not zero.
+                        * Since device header size is not fixed, we can't
+                        * cover all possible cases.
+                        * Assuming the image is valid only if the real
+                        * device header size equals to devh_size.
+                        */
+                       total_size = le32_to_cpu(bh->total_size);
+
+                       if (total_size - gfh_offset > img_size - devh_size)
+                               return -1;
+
+                       gfh_offset = devh_size;
+               }
+       }
+
+       gfh = (struct gfh_header *)(ptr + gfh_offset);
 
        if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
                return -1;
@@ -549,6 +588,8 @@ static int mtk_image_verify_header(unsigned char *ptr, int image_size,
        if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
                return 0;
 
+       img_size = image_size;
+
        if (!strcmp((char *)ptr, NAND_BOOT_NAME))
                return mtk_image_verify_nand_header(ptr, 0);
        else
@@ -682,8 +723,8 @@ static void mtk_image_set_gen_header(void *ptr, off_t filesize,
 
        /* BRLYT header */
        put_brom_layout_header(&hdr->brlyt, hdr_media);
-       hdr->brlyt.header_size = cpu_to_le32(sizeof(struct gen_device_header));
-       hdr->brlyt.total_size = cpu_to_le32(filesize);
+       hdr->brlyt.header_size = cpu_to_le32(hdr_offset + sizeof(*hdr));
+       hdr->brlyt.total_size = cpu_to_le32(hdr_offset + filesize);
        hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
        hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
 
@@ -747,6 +788,9 @@ static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
                return;
        }
 
+       img_gen = true;
+       img_size = sbuf->st_size;
+
        if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
                mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
        else
index 6b80663..53f55ce 100644 (file)
@@ -136,17 +136,17 @@ How to run it
 
 First do a dry run:
 
-$ ./tools/patman/patman -n
+$ ./tools/patman/patman send -n
 
 If it can't detect the upstream branch, try telling it how many patches
 there are in your series:
 
-$ ./tools/patman/patman -n -c5
+$ ./tools/patman/patman -c5 send -n
 
 This will create patch files in your current directory and tell you who
 it is thinking of sending them to. Take a look at the patch files.
 
-$ ./tools/patman/patman -n -c5 -s1
+$ ./tools/patman/patman -c5 -s1 send -n
 
 Similar to the above, but skip the first commit and take the next 5. This
 is useful if your top commit is for setting up testing.
@@ -433,12 +433,12 @@ but that you don't want to submit because there is an existing patch for it
 on the list. So you can tell patman to create and check some patches
 (skipping the first patch) with:
 
-    patman -s1 -n
+    patman -s1 send -n
 
 If you want to do all of them including the work-in-progress one, then
 (if you are tracking an upstream branch):
 
-    patman -n
+    patman send -n
 
 Let's say that patman reports an error in the second patch. Then:
 
@@ -450,7 +450,7 @@ Let's say that patman reports an error in the second patch. Then:
 
 Now you have an updated patch series. To check it:
 
-    patman -s1 -n
+    patman -s1 send -n
 
 Let's say it is now clean and you want to send it. Now you need to set up
 the destination. So amend the top commit with:
@@ -485,7 +485,7 @@ mmc and sparc, and the last one to sandbox.
 
 Now to send the patches, take off the -n flag:
 
-   patman -s1
+   patman -s1 send
 
 The patches will be created, shown in your editor, and then sent along with
 the cover letter. Note that patman's tags are automatically removed so that
index 89072b1..450fe66 100644 (file)
@@ -186,7 +186,7 @@ class TestFunctional(unittest.TestCase):
             - Commit-notes
         """
         process_tags = True
-        ignore_bad_tags = True
+        ignore_bad_tags = False
         stefan = b'Stefan Br\xc3\xbcns <stefan.bruens@rwth-aachen.de>'.decode('utf-8')
         rick = 'Richard III <richard@palace.gov>'
         mel = b'Lord M\xc3\xablchett <clergy@palace.gov>'.decode('utf-8')
index bf1271d..5e4c112 100644 (file)
@@ -345,7 +345,7 @@ def CreatePatches(branch, start, count, ignore_binary, series, signoff = True):
     else:
        return None, files
 
-def BuildEmailList(in_list, tag=None, alias=None, raise_on_error=True):
+def BuildEmailList(in_list, tag=None, alias=None, warn_on_error=True):
     """Build a list of email addresses based on an input list.
 
     Takes a list of email addresses and aliases, and turns this into a list
@@ -359,7 +359,7 @@ def BuildEmailList(in_list, tag=None, alias=None, raise_on_error=True):
         in_list:        List of aliases/email addresses
         tag:            Text to put before each address
         alias:          Alias dictionary
-        raise_on_error: True to raise an error when an alias fails to match,
+        warn_on_error: True to raise an error when an alias fails to match,
                 False to just print a message.
 
     Returns:
@@ -382,7 +382,7 @@ def BuildEmailList(in_list, tag=None, alias=None, raise_on_error=True):
     quote = '"' if tag and tag[0] == '-' else ''
     raw = []
     for item in in_list:
-        raw += LookupEmail(item, alias, raise_on_error=raise_on_error)
+        raw += LookupEmail(item, alias, warn_on_error=warn_on_error)
     result = []
     for item in raw:
         if not item in result:
@@ -416,7 +416,7 @@ def CheckSuppressCCConfig():
 
     return True
 
-def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname,
+def EmailPatches(series, cover_fname, args, dry_run, warn_on_error, cc_fname,
         self_only=False, alias=None, in_reply_to=None, thread=False,
         smtp_server=None):
     """Email a patch series.
@@ -426,8 +426,8 @@ def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname,
         cover_fname: filename of cover letter
         args: list of filenames of patch files
         dry_run: Just return the command that would be run
-        raise_on_error: True to raise an error when an alias fails to match,
-                False to just print a message.
+        warn_on_error: True to print a warning when an alias fails to match,
+                False to ignore it.
         cc_fname: Filename of Cc file for per-commit Cc
         self_only: True to just email to yourself as a test
         in_reply_to: If set we'll pass this to git as --in-reply-to.
@@ -475,7 +475,7 @@ send --cc-cmd cc-fname" cover p1 p2'
     # Restore argv[0] since we clobbered it.
     >>> sys.argv[0] = _old_argv0
     """
-    to = BuildEmailList(series.get('to'), '--to', alias, raise_on_error)
+    to = BuildEmailList(series.get('to'), '--to', alias, warn_on_error)
     if not to:
         git_config_to = command.Output('git', 'config', 'sendemail.to',
                                        raise_on_error=False)
@@ -487,9 +487,9 @@ send --cc-cmd cc-fname" cover p1 p2'
                   "git config sendemail.to u-boot@lists.denx.de")
             return
     cc = BuildEmailList(list(set(series.get('cc')) - set(series.get('to'))),
-                        '--cc', alias, raise_on_error)
+                        '--cc', alias, warn_on_error)
     if self_only:
-        to = BuildEmailList([os.getenv('USER')], '--to', alias, raise_on_error)
+        to = BuildEmailList([os.getenv('USER')], '--to', alias, warn_on_error)
         cc = []
     cmd = ['git', 'send-email', '--annotate']
     if smtp_server:
@@ -511,7 +511,7 @@ send --cc-cmd cc-fname" cover p1 p2'
     return cmdstr
 
 
-def LookupEmail(lookup_name, alias=None, raise_on_error=True, level=0):
+def LookupEmail(lookup_name, alias=None, warn_on_error=True, level=0):
     """If an email address is an alias, look it up and return the full name
 
     TODO: Why not just use git's own alias feature?
@@ -519,8 +519,8 @@ def LookupEmail(lookup_name, alias=None, raise_on_error=True, level=0):
     Args:
         lookup_name: Alias or email address to look up
         alias: Dictionary containing aliases (None to use settings default)
-        raise_on_error: True to raise an error when an alias fails to match,
-                False to just print a message.
+        warn_on_error: True to print a warning when an alias fails to match,
+                False to ignore it.
 
     Returns:
         tuple:
@@ -547,18 +547,16 @@ def LookupEmail(lookup_name, alias=None, raise_on_error=True, level=0):
     >>> LookupEmail('all', alias)
     ['f.bloggs@napier.co.nz', 'j.bloggs@napier.co.nz', 'm.poppins@cloud.net']
     >>> LookupEmail('odd', alias)
-    Traceback (most recent call last):
-    ...
-    ValueError: Alias 'odd' not found
+    Alias 'odd' not found
+    []
     >>> LookupEmail('loop', alias)
     Traceback (most recent call last):
     ...
     OSError: Recursive email alias at 'other'
-    >>> LookupEmail('odd', alias, raise_on_error=False)
-    Alias 'odd' not found
+    >>> LookupEmail('odd', alias, warn_on_error=False)
     []
     >>> # In this case the loop part will effectively be ignored.
-    >>> LookupEmail('loop', alias, raise_on_error=False)
+    >>> LookupEmail('loop', alias, warn_on_error=False)
     Recursive email alias at 'other'
     Recursive email alias at 'john'
     Recursive email alias at 'mary'
@@ -576,7 +574,7 @@ def LookupEmail(lookup_name, alias=None, raise_on_error=True, level=0):
     out_list = []
     if level > 10:
         msg = "Recursive email alias at '%s'" % lookup_name
-        if raise_on_error:
+        if warn_on_error:
             raise OSError(msg)
         else:
             print(col.Color(col.RED, msg))
@@ -585,18 +583,15 @@ def LookupEmail(lookup_name, alias=None, raise_on_error=True, level=0):
     if lookup_name:
         if not lookup_name in alias:
             msg = "Alias '%s' not found" % lookup_name
-            if raise_on_error:
-                raise ValueError(msg)
-            else:
+            if warn_on_error:
                 print(col.Color(col.RED, msg))
-                return out_list
+            return out_list
         for item in alias[lookup_name]:
-            todo = LookupEmail(item, alias, raise_on_error, level + 1)
+            todo = LookupEmail(item, alias, warn_on_error, level + 1)
             for new_item in todo:
                 if not new_item in out_list:
                     out_list.append(new_item)
 
-    #print("No match for alias '%s'" % lookup_name)
     return out_list
 
 def GetTopLevel():
index c4e4d80..04e37a5 100755 (executable)
@@ -9,6 +9,7 @@
 from argparse import ArgumentParser
 import os
 import re
+import shutil
 import sys
 import traceback
 import unittest
@@ -68,7 +69,8 @@ send.add_argument('-n', '--dry-run', action='store_true', dest='dry_run',
 send.add_argument('-r', '--in-reply-to', type=str, action='store',
                   help="Message ID that this series is in reply to")
 send.add_argument('-t', '--ignore-bad-tags', action='store_true',
-                  default=False, help='Ignore bad tags / aliases')
+                  default=False,
+                  help='Ignore bad tags / aliases (default=warn)')
 send.add_argument('-T', '--thread', action='store_true', dest='thread',
                   default=False, help='Create patches as a single thread')
 send.add_argument('--cc-cmd', dest='cc_cmd', type=str, action='store',
@@ -170,12 +172,17 @@ elif args.cmd == 'send':
     elif args.full_help:
         pager = os.getenv('PAGER')
         if not pager:
+            pager = shutil.which('less')
+        if not pager:
             pager = 'more'
         fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
                              'README')
         command.Run(pager, fname)
 
     else:
+        # If we are not processing tags, no need to warning about bad ones
+        if not args.process_tags:
+            args.ignore_bad_tags = True
         control.send(args)
 
 # Check status of patches in patchwork
index 41a1173..8ae218d 100644 (file)
@@ -234,7 +234,7 @@ class Series(dict):
             str = 'Change log exists, but no version is set'
             print(col.Color(col.RED, str))
 
-    def MakeCcFile(self, process_tags, cover_fname, raise_on_error,
+    def MakeCcFile(self, process_tags, cover_fname, warn_on_error,
                    add_maintainers, limit):
         """Make a cc file for us to use for per-commit Cc automation
 
@@ -243,8 +243,8 @@ class Series(dict):
         Args:
             process_tags: Process tags as if they were aliases
             cover_fname: If non-None the name of the cover letter.
-            raise_on_error: True to raise an error when an alias fails to match,
-                False to just print a message.
+            warn_on_error: True to print a warning when an alias fails to match,
+                False to ignore it.
             add_maintainers: Either:
                 True/False to call the get_maintainers to CC maintainers
                 List of maintainers to include (for testing)
@@ -261,9 +261,9 @@ class Series(dict):
             cc = []
             if process_tags:
                 cc += gitutil.BuildEmailList(commit.tags,
-                                               raise_on_error=raise_on_error)
+                                               warn_on_error=warn_on_error)
             cc += gitutil.BuildEmailList(commit.cc_list,
-                                           raise_on_error=raise_on_error)
+                                           warn_on_error=warn_on_error)
             if type(add_maintainers) == type(cc):
                 cc += add_maintainers
             elif add_maintainers:
index 10997e4..e5f391b 100644 (file)
@@ -130,8 +130,12 @@ def GetInputFilename(fname, allow_missing=False):
         allow_missing: True if the filename can be missing
 
     Returns:
-        The full path of the filename, within the input directory, or
-        None on error
+        fname, if indir is None;
+        full path of the filename, within the input directory;
+        None, if file is missing and allow_missing is True
+
+    Raises:
+        ValueError if file is missing and allow_missing is False
     """
     if not indir or fname[:1] == '/':
         return fname