Merge branch 'master' of git://git.denx.de/u-boot-net
authorTom Rini <trini@konsulko.com>
Thu, 9 May 2019 02:46:31 +0000 (22:46 -0400)
committerTom Rini <trini@konsulko.com>
Thu, 9 May 2019 02:46:31 +0000 (22:46 -0400)
- Various PHY fixes / enhancements.
- TI K2G fixes

104 files changed:
Makefile
arch/Kconfig
arch/arm/dts/Makefile
arch/arm/dts/sun50i-a64-teres-i-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/sun50i-a64-teres-i.dts [new file with mode: 0644]
arch/arm/dts/sun50i-h6-beelink-gs1.dts [new file with mode: 0644]
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/cpu/Makefile
arch/x86/cpu/broadwell/Makefile
arch/x86/cpu/broadwell/cpu.c
arch/x86/cpu/broadwell/cpu_from_spl.c [new file with mode: 0644]
arch/x86/cpu/broadwell/cpu_full.c [new file with mode: 0644]
arch/x86/cpu/broadwell/northbridge.c
arch/x86/cpu/broadwell/pch.c
arch/x86/cpu/broadwell/sdram.c
arch/x86/cpu/i386/cpu.c
arch/x86/cpu/intel_common/Makefile
arch/x86/cpu/intel_common/car.S
arch/x86/cpu/intel_common/cpu_from_spl.c [new file with mode: 0644]
arch/x86/cpu/ivybridge/bd82x6x.c
arch/x86/cpu/mp_init.c
arch/x86/cpu/start.S
arch/x86/cpu/start64.S
arch/x86/cpu/start_from_spl.S [new file with mode: 0644]
arch/x86/cpu/start_from_tpl.S [new file with mode: 0644]
arch/x86/cpu/u-boot-spl.lds
arch/x86/cpu/x86_64/cpu.c
arch/x86/dts/chromebook_samus.dts
arch/x86/dts/reset.dtsi
arch/x86/dts/rtc.dtsi
arch/x86/dts/u-boot.dtsi
arch/x86/include/asm/handoff.h [new file with mode: 0644]
arch/x86/include/asm/mrccache.h
arch/x86/include/asm/spl.h
arch/x86/include/asm/u-boot-x86.h
arch/x86/lib/Makefile
arch/x86/lib/bootm.c
arch/x86/lib/fsp/fsp_car.S
arch/x86/lib/init_helpers.c
arch/x86/lib/mrccache.c
arch/x86/lib/spl.c
arch/x86/lib/tpl.c [new file with mode: 0644]
board/google/Kconfig
board/google/chromebook_samus/Kconfig
board/google/chromebook_samus/MAINTAINERS
board/sunxi/MAINTAINERS
cmd/bootefi.c
configs/Cubietruck_plus_defconfig
configs/Sinovoip_BPI_M3_defconfig
configs/beelink_gs1_defconfig [new file with mode: 0644]
configs/chromebook_samus_defconfig
configs/chromebook_samus_tpl_defconfig [new file with mode: 0644]
configs/teres_i_defconfig [new file with mode: 0644]
doc/README.x86
drivers/clk/clk-uclass.c
drivers/clk/sifive/fu540-prci.c
drivers/core/ofnode.c
drivers/misc/cros_ec.c
drivers/net/sun8i_emac.c
drivers/pci/pci_rom.c
drivers/reset/reset-uclass.c
drivers/serial/serial_sifive.c
drivers/spi/atcspi200_spi.c
drivers/sysreset/sysreset_x86.c
include/clk.h
include/configs/chromebook_link.h
include/configs/chromebook_samus.h
include/configs/qemu-x86.h
include/configs/sunxi-common.h
include/configs/x86-common.h
include/efi_api.h
include/efi_loader.h
include/efi_selftest.h
include/pch.h
include/pci.h
include/reset.h
lib/efi_loader/efi_boottime.c
lib/efi_loader/efi_image_loader.c
lib/efi_loader/efi_root_node.c
lib/efi_loader/efi_setup.c
lib/efi_selftest/Makefile
lib/efi_selftest/efi_selftest_block_device.c
lib/efi_selftest/efi_selftest_config_table.c
lib/efi_selftest/efi_selftest_loaded_image.c
lib/efi_selftest/efi_selftest_loadimage.c
lib/efi_selftest/efi_selftest_manageprotocols.c
lib/efi_selftest/efi_selftest_memory.c
lib/efi_selftest/efi_selftest_register_notify.c [new file with mode: 0644]
lib/efi_selftest/efi_selftest_snp.c
lib/efi_selftest/efi_selftest_startimage_exit.c
lib/efi_selftest/efi_selftest_util.c
lib/efi_selftest/efi_selftest_variables.c
scripts/Makefile.spl
test/dm/clk.c
test/dm/reset.c
tools/binman/README
tools/binman/bsection.py
tools/binman/control.py
tools/binman/etype/section.py
tools/binman/etype/text.py
tools/binman/etype/vblock.py
tools/binman/ftest.py
tools/binman/test/101_sections_offset.dts [new file with mode: 0644]

index 5ae5db5..9fb90c0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1380,6 +1380,7 @@ cmd_ldr = $(LD) $(LDFLAGS_$(@F)) \
 
 u-boot.rom: u-boot-x86-16bit.bin u-boot.bin \
                $(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \
+               $(if $(CONFIG_TPL_X86_16BIT_INIT),tpl/u-boot-tpl.bin) \
                $(if $(CONFIG_HAVE_REFCODE),refcode.bin) FORCE
        $(call if_changed,binman)
 
index 760023b..0ad3867 100644 (file)
@@ -126,6 +126,8 @@ config SH
 
 config X86
        bool "x86 architecture"
+       select SUPPORT_SPL
+       select SUPPORT_TPL
        select CREATE_ARCH_SYMLINK
        select DM
        select DM_PCI
@@ -163,6 +165,36 @@ config X86
        imply USB_ETHER_SMSC95XX
        imply USB_HOST_ETHER
        imply PCH
+       imply RTC_MC146818
+
+       # Thing to enable for when SPL/TPL are enabled: SPL
+       imply SPL_DM
+       imply SPL_OF_LIBFDT
+       imply SPL_DRIVERS_MISC_SUPPORT
+       imply SPL_GPIO_SUPPORT
+       imply SPL_LIBCOMMON_SUPPORT
+       imply SPL_LIBGENERIC_SUPPORT
+       imply SPL_SERIAL_SUPPORT
+       imply SPL_SPI_FLASH_SUPPORT
+       imply SPL_SPI_SUPPORT
+       imply SPL_OF_CONTROL
+       imply SPL_TIMER
+       imply SPL_REGMAP
+       imply SPL_SYSCON
+       # TPL
+       imply TPL_DM
+       imply TPL_OF_LIBFDT
+       imply TPL_DRIVERS_MISC_SUPPORT
+       imply TPL_GPIO_SUPPORT
+       imply TPL_LIBCOMMON_SUPPORT
+       imply TPL_LIBGENERIC_SUPPORT
+       imply TPL_SERIAL_SUPPORT
+       imply TPL_SPI_FLASH_SUPPORT
+       imply TPL_SPI_SUPPORT
+       imply TPL_OF_CONTROL
+       imply TPL_TIMER
+       imply TPL_REGMAP
+       imply TPL_SYSCON
 
 config XTENSA
        bool "Xtensa architecture"
index a199f3f..8b97143 100644 (file)
@@ -480,6 +480,7 @@ dtb-$(CONFIG_MACH_SUN50I_H5) += \
        sun50i-h5-orangepi-prime.dtb \
        sun50i-h5-orangepi-zero-plus2.dtb
 dtb-$(CONFIG_MACH_SUN50I_H6) += \
+       sun50i-h6-beelink-gs1.dtb \
        sun50i-h6-orangepi-lite2.dtb \
        sun50i-h6-orangepi-one-plus.dtb \
        sun50i-h6-pine-h64.dtb
@@ -494,7 +495,8 @@ dtb-$(CONFIG_MACH_SUN50I) += \
        sun50i-a64-pine64-plus.dtb \
        sun50i-a64-pine64.dtb \
        sun50i-a64-pinebook.dtb \
-       sun50i-a64-sopine-baseboard.dtb
+       sun50i-a64-sopine-baseboard.dtb \
+       sun50i-a64-teres-i.dtb
 dtb-$(CONFIG_MACH_SUN9I) += \
        sun9i-a80-optimus.dtb \
        sun9i-a80-cubieboard4.dtb \
diff --git a/arch/arm/dts/sun50i-a64-teres-i-u-boot.dtsi b/arch/arm/dts/sun50i-a64-teres-i-u-boot.dtsi
new file mode 100644 (file)
index 0000000..1a64b7d
--- /dev/null
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Vasily Khoruzhick <anarsoul@gmail.com>
+ *
+ */
+
+#include "sunxi-u-boot.dtsi"
+
+/ {
+       vdd_bl: regulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "bl-3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */
+               enable-active-high;
+       };
+
+       backlight: backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 0 50000 0>;
+               brightness-levels = <0 5 10 15 20 30 40 55 70 85 100>;
+               default-brightness-level = <2>;
+               enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* PD23 */
+               power-supply = <&vdd_bl>;
+       };
+};
+
+/* The ANX6345 eDP-bridge is on i2c */
+&i2c0 {
+       anx6345: edp-bridge@38 {
+               compatible = "analogix,anx6345";
+               reg = <0x38>;
+               reset-gpios = <&pio 3 24 GPIO_ACTIVE_LOW>; /* PD24 */
+               status = "okay";
+       };
+};
+
+&pwm {
+       status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-a64-teres-i.dts b/arch/arm/dts/sun50i-a64-teres-i.dts
new file mode 100644 (file)
index 0000000..c455b24
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) Harald Geyer <harald@ccbib.org>
+ * based on sun50i-a64-olinuxino.dts by Jagan Teki <jteki@openedev.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ */
+
+/dts-v1/;
+
+#include "sun50i-a64.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+       model = "Olimex A64 Teres-I";
+       compatible = "olimex,a64-teres-i", "allwinner,sun50i-a64";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+
+               framebuffer-lcd {
+                       eDP25-supply = <&reg_dldo2>;
+                       eDP12-supply = <&reg_dldo3>;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               lid-switch {
+                       label = "Lid Switch";
+                       gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */
+                       linux,input-type = <EV_SW>;
+                       linux,code = <SW_LID>;
+                       wakeup-source;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               capslock {
+                       label = "teres-i:green:capslock";
+                       gpios = <&pio 2 7 GPIO_ACTIVE_HIGH>; /* PC7 */
+               };
+
+               numlock {
+                       label = "teres-i:green:numlock";
+                       gpios = <&pio 2 4 GPIO_ACTIVE_HIGH>; /* PC4 */
+               };
+       };
+
+       reg_usb1_vbus: usb1-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb1-vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               enable-active-high;
+               gpio = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
+               status = "okay";
+       };
+
+       wifi_pwrseq: wifi_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
+       };
+};
+
+&ehci1 {
+       status = "okay";
+};
+
+
+/* The ANX6345 eDP-bridge is on i2c0. There is no linux (mainline)
+ * driver for this chip at the moment, the bootloader initializes it.
+ * However it can be accessed with the i2c-dev driver from user space.
+ */
+&i2c0 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c0_pins>;
+       status = "okay";
+};
+
+&mmc0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc0_pins>;
+       vmmc-supply = <&reg_dcdc1>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+       disable-wp;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&mmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       vmmc-supply = <&reg_aldo2>;
+       vqmmc-supply = <&reg_dldo4>;
+       mmc-pwrseq = <&wifi_pwrseq>;
+       bus-width = <4>;
+       non-removable;
+       status = "okay";
+
+       rtl8723bs: wifi@1 {
+               reg = <1>;
+               interrupt-parent = <&r_pio>;
+               interrupts = <0 3 IRQ_TYPE_LEVEL_LOW>; /* PL3 */
+               interrupt-names = "host-wake";
+       };
+};
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&reg_dcdc1>;
+       vqmmc-supply = <&reg_dcdc1>;
+       bus-width = <8>;
+       non-removable;
+       cap-mmc-hw-reset;
+       status = "okay";
+};
+
+&ohci1 {
+       status = "okay";
+};
+
+&r_rsb {
+       status = "okay";
+
+       axp803: pmic@3a3 {
+               compatible = "x-powers,axp803";
+               reg = <0x3a3>;
+               interrupt-parent = <&r_intc>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               wakeup-source;
+       };
+};
+
+#include "axp803.dtsi"
+
+&reg_aldo1 {
+       regulator-always-on;
+       regulator-min-microvolt = <2800000>;
+       regulator-max-microvolt = <2800000>;
+       regulator-name = "vcc-pe";
+};
+
+&reg_aldo2 {
+       regulator-always-on;
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-pl";
+};
+
+&reg_aldo3 {
+       regulator-always-on;
+       regulator-min-microvolt = <3000000>;
+       regulator-max-microvolt = <3000000>;
+       regulator-name = "vcc-pll-avcc";
+};
+
+&reg_dcdc1 {
+       regulator-always-on;
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-3v3";
+};
+
+&reg_dcdc2 {
+       regulator-always-on;
+       regulator-min-microvolt = <1040000>;
+       regulator-max-microvolt = <1300000>;
+       regulator-name = "vdd-cpux";
+};
+
+/* DCDC3 is polyphased with DCDC2 */
+
+&reg_dcdc5 {
+       regulator-always-on;
+       regulator-min-microvolt = <1500000>;
+       regulator-max-microvolt = <1500000>;
+       regulator-name = "vcc-ddr3";
+};
+
+&reg_dcdc6 {
+       regulator-always-on;
+       regulator-min-microvolt = <1100000>;
+       regulator-max-microvolt = <1100000>;
+       regulator-name = "vdd-sys";
+};
+
+&reg_dldo1 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-hdmi";
+};
+
+&reg_dldo2 {
+       regulator-min-microvolt = <2500000>;
+       regulator-max-microvolt = <2500000>;
+       regulator-name = "vcc-pd";
+};
+
+&reg_dldo3 {
+       regulator-min-microvolt = <1200000>;
+       regulator-max-microvolt = <1200000>;
+       regulator-name = "vdd-edp";
+};
+
+&reg_dldo4 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-wifi-io";
+};
+
+&reg_eldo1 {
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-name = "cpvdd";
+};
+
+&reg_eldo2 {
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-name = "vcc-dvdd-csi";
+};
+
+&reg_fldo1 {
+       regulator-min-microvolt = <1200000>;
+       regulator-max-microvolt = <1200000>;
+       regulator-name = "vcc-1v2-hsic";
+};
+
+/*
+ * The A64 chip cannot work without this regulator off, although
+ * it seems to be only driving the AR100 core.
+ * Maybe we don't still know well about CPUs domain.
+ */
+&reg_fldo2 {
+       regulator-always-on;
+       regulator-min-microvolt = <1100000>;
+       regulator-max-microvolt = <1100000>;
+       regulator-name = "vdd-cpus";
+};
+
+&reg_rtc_ldo {
+       regulator-name = "vcc-rtc";
+};
+
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pb_pins>;
+       status = "okay";
+};
+
+&usbphy {
+       usb1_vbus-supply = <&reg_usb1_vbus>;
+       status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-h6-beelink-gs1.dts b/arch/arm/dts/sun50i-h6-beelink-gs1.dts
new file mode 100644 (file)
index 0000000..54b0882
--- /dev/null
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2019 Clément Péron <peron.clem@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-h6.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "Beelink GS1";
+       compatible = "azw,beelink-gs1", "allwinner,sun50i-h6";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               power {
+                       label = "beelink:white:power";
+                       gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */
+                       default-state = "on";
+               };
+       };
+
+       reg_vcc5v: vcc5v {
+               /* board wide 5V supply directly from the DC jack */
+               compatible = "regulator-fixed";
+               regulator-name = "vcc-5v";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+};
+
+&mmc0 {
+       vmmc-supply = <&reg_cldo1>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&mmc2 {
+       vmmc-supply = <&reg_cldo1>;
+       vqmmc-supply = <&reg_bldo2>;
+       non-removable;
+       cap-mmc-hw-reset;
+       bus-width = <8>;
+       status = "okay";
+};
+
+&r_i2c {
+       status = "okay";
+
+       axp805: pmic@36 {
+               compatible = "x-powers,axp805", "x-powers,axp806";
+               reg = <0x36>;
+               interrupt-parent = <&r_intc>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               x-powers,self-working-mode;
+               vina-supply = <&reg_vcc5v>;
+               vinb-supply = <&reg_vcc5v>;
+               vinc-supply = <&reg_vcc5v>;
+               vind-supply = <&reg_vcc5v>;
+               vine-supply = <&reg_vcc5v>;
+               aldoin-supply = <&reg_vcc5v>;
+               bldoin-supply = <&reg_vcc5v>;
+               cldoin-supply = <&reg_vcc5v>;
+
+               regulators {
+                       reg_aldo1: aldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-pl";
+                       };
+
+                       reg_aldo2: aldo2 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-ac200";
+                               regulator-enable-ramp-delay = <100000>;
+                       };
+
+                       reg_aldo3: aldo3 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc25-dram";
+                       };
+
+                       reg_bldo1: bldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-bias-pll";
+                       };
+
+                       reg_bldo2: bldo2 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-efuse-pcie-hdmi-io";
+                       };
+
+                       reg_bldo3: bldo3 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-dcxoio";
+                       };
+
+                       bldo4 {
+                               /* unused */
+                       };
+
+                       reg_cldo1: cldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-3v3";
+                       };
+
+                       reg_cldo2: cldo2 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-wifi-1";
+                       };
+
+                       reg_cldo3: cldo3 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-wifi-2";
+                       };
+
+                       reg_dcdca: dcdca {
+                               regulator-always-on;
+                               regulator-min-microvolt = <810000>;
+                               regulator-max-microvolt = <1080000>;
+                               regulator-name = "vdd-cpu";
+                       };
+
+                       reg_dcdcc: dcdcc {
+                               regulator-min-microvolt = <810000>;
+                               regulator-max-microvolt = <1080000>;
+                               regulator-name = "vdd-gpu";
+                       };
+
+                       reg_dcdcd: dcdcd {
+                               regulator-always-on;
+                               regulator-min-microvolt = <960000>;
+                               regulator-max-microvolt = <960000>;
+                               regulator-name = "vdd-sys";
+                       };
+
+                       reg_dcdce: dcdce {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-name = "vcc-dram";
+                       };
+
+                       sw {
+                               /* unused */
+                       };
+               };
+       };
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_ph_pins>;
+       status = "okay";
+};
index e052093..45a5336 100644 (file)
@@ -32,7 +32,6 @@ config X86_RUN_32BIT
 config X86_RUN_64BIT
        bool "64-bit"
        select X86_64
-       select SUPPORT_SPL
        select SPL
        select SPL_SEPARATE_BSS
        help
@@ -177,10 +176,17 @@ config X86_16BIT_INIT
 config SPL_X86_16BIT_INIT
        bool
        depends on X86_RESET_VECTOR
-       default y if X86_RESET_VECTOR && SPL
+       default y if X86_RESET_VECTOR && SPL && !TPL
        help
          This is enabled when 16-bit init is in SPL
 
+config TPL_X86_16BIT_INIT
+       bool
+       depends on X86_RESET_VECTOR
+       default y if X86_RESET_VECTOR && TPL
+       help
+         This is enabled when 16-bit init is in TPL
+
 config X86_32BIT_INIT
        bool
        depends on X86_RESET_VECTOR
index fec1484..f1afc74 100644 (file)
@@ -4,12 +4,24 @@ ifeq ($(CONFIG_EFI_APP),)
 ifdef CONFIG_$(SPL_)X86_64
 head-y := arch/x86/cpu/start64.o
 else
+ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y)
 head-y := arch/x86/cpu/start.o
+else
+ifndef CONFIG_SPL
+head-y := arch/x86/cpu/start.o
+else
+ifdef CONFIG_SPL_BUILD
+head-y = arch/x86/cpu/start_from_tpl.o
+else
+head-y = arch/x86/cpu/start_from_spl.o
+endif
+endif
 endif
 endif
+endif # EFI
 
-head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/start16.o
-head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/resetvec.o
+head-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += arch/x86/cpu/start16.o
+head-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += arch/x86/cpu/resetvec.o
 
 libs-y += arch/x86/cpu/
 libs-y += arch/x86/lib/
index 54668aa..85fd5e6 100644 (file)
@@ -9,9 +9,22 @@
 ifeq ($(CONFIG_$(SPL_)X86_64),y)
 extra-y        = start64.o
 else
+ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y)
 extra-y        = start.o
+else
+ifndef CONFIG_SPL
+extra-y        = start.o
+else
+ifdef CONFIG_SPL_BUILD
+extra-y        = start_from_tpl.o
+else
+extra-y        = start_from_spl.o
 endif
-extra-$(CONFIG_$(SPL_)X86_16BIT_INIT) += resetvec.o start16.o
+endif
+endif
+endif
+
+extra-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += resetvec.o start16.o
 
 obj-y  += cpu.o cpu_x86.o
 
index d3785aa..52d56c6 100644 (file)
@@ -3,7 +3,24 @@
 # Copyright (c) 2016 Google, Inc
 
 obj-y += adsp.o
-obj-y += cpu.o
+obj-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += cpu.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += cpu_full.o
+
+ifdef CONFIG_SPL
+ifndef CONFIG_SPL_BUILD
+obj-y += cpu_from_spl.o
+obj-y += cpu_full.o
+obj-y += refcode.o
+endif
+ifndef CONFIG_SPL_BUILD
+# obj-y += cpu_from_spl.o
+endif
+endif
+
+ifeq ($(CONFIG_$(SPL_TPL_)X86_32BIT_INIT),)
+#obj-y += cpu_from_spl.o
+endif
+
 obj-y += iobp.o
 obj-y += lpc.o
 obj-y += me.o
@@ -11,6 +28,6 @@ obj-y += northbridge.o
 obj-y += pch.o
 obj-y += pinctrl_broadwell.o
 obj-y += power_state.o
-obj-y += refcode.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += refcode.o
 obj-y += sata.o
-obj-y += sdram.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += sdram.o
index 232fa40..bb7c361 100644 (file)
 #include <asm/cpu_x86.h>
 #include <asm/cpu_common.h>
 #include <asm/intel_regs.h>
+#include <asm/lpc_common.h>
 #include <asm/msr.h>
+#include <asm/pci.h>
 #include <asm/post.h>
 #include <asm/turbo.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/pch.h>
 #include <asm/arch/rcb.h>
 
-struct cpu_broadwell_priv {
-       bool ht_disabled;
-};
-
-/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
-static const u8 power_limit_time_sec_to_msr[] = {
-       [0]   = 0x00,
-       [1]   = 0x0a,
-       [2]   = 0x0b,
-       [3]   = 0x4b,
-       [4]   = 0x0c,
-       [5]   = 0x2c,
-       [6]   = 0x4c,
-       [7]   = 0x6c,
-       [8]   = 0x0d,
-       [10]  = 0x2d,
-       [12]  = 0x4d,
-       [14]  = 0x6d,
-       [16]  = 0x0e,
-       [20]  = 0x2e,
-       [24]  = 0x4e,
-       [28]  = 0x6e,
-       [32]  = 0x0f,
-       [40]  = 0x2f,
-       [48]  = 0x4f,
-       [56]  = 0x6f,
-       [64]  = 0x10,
-       [80]  = 0x30,
-       [96]  = 0x50,
-       [112] = 0x70,
-       [128] = 0x11,
-};
-
-/* Convert POWER_LIMIT_1_TIME MSR value to seconds */
-static const u8 power_limit_time_msr_to_sec[] = {
-       [0x00] = 0,
-       [0x0a] = 1,
-       [0x0b] = 2,
-       [0x4b] = 3,
-       [0x0c] = 4,
-       [0x2c] = 5,
-       [0x4c] = 6,
-       [0x6c] = 7,
-       [0x0d] = 8,
-       [0x2d] = 10,
-       [0x4d] = 12,
-       [0x6d] = 14,
-       [0x0e] = 16,
-       [0x2e] = 20,
-       [0x4e] = 24,
-       [0x6e] = 28,
-       [0x0f] = 32,
-       [0x2f] = 40,
-       [0x4f] = 48,
-       [0x6f] = 56,
-       [0x10] = 64,
-       [0x30] = 80,
-       [0x50] = 96,
-       [0x70] = 112,
-       [0x11] = 128,
-};
-
 int arch_cpu_init_dm(void)
 {
        struct udevice *dev;
@@ -156,613 +96,13 @@ int print_cpuinfo(void)
        return 0;
 }
 
-/*
- * The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate
- * the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly
- * when a core is woken up
- */
-static int pcode_ready(void)
-{
-       int wait_count;
-       const int delay_step = 10;
-
-       wait_count = 0;
-       do {
-               if (!(readl(MCHBAR_REG(BIOS_MAILBOX_INTERFACE)) &
-                               MAILBOX_RUN_BUSY))
-                       return 0;
-               wait_count += delay_step;
-               udelay(delay_step);
-       } while (wait_count < 1000);
-
-       return -ETIMEDOUT;
-}
-
-static u32 pcode_mailbox_read(u32 command)
-{
-       int ret;
-
-       ret = pcode_ready();
-       if (ret) {
-               debug("PCODE: mailbox timeout on wait ready\n");
-               return ret;
-       }
-
-       /* Send command and start transaction */
-       writel(command | MAILBOX_RUN_BUSY, MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
-
-       ret = pcode_ready();
-       if (ret) {
-               debug("PCODE: mailbox timeout on completion\n");
-               return ret;
-       }
-
-       /* Read mailbox */
-       return readl(MCHBAR_REG(BIOS_MAILBOX_DATA));
-}
-
-static int pcode_mailbox_write(u32 command, u32 data)
-{
-       int ret;
-
-       ret = pcode_ready();
-       if (ret) {
-               debug("PCODE: mailbox timeout on wait ready\n");
-               return ret;
-       }
-
-       writel(data, MCHBAR_REG(BIOS_MAILBOX_DATA));
-
-       /* Send command and start transaction */
-       writel(command | MAILBOX_RUN_BUSY, MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
-
-       ret = pcode_ready();
-       if (ret) {
-               debug("PCODE: mailbox timeout on completion\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-/* @dev is the CPU device */
-static void initialize_vr_config(struct udevice *dev)
-{
-       int ramp, min_vid;
-       msr_t msr;
-
-       debug("Initializing VR config\n");
-
-       /* Configure VR_CURRENT_CONFIG */
-       msr = msr_read(MSR_VR_CURRENT_CONFIG);
-       /*
-        * Preserve bits 63 and 62. Bit 62 is PSI4 enable, but it is only valid
-        * on ULT systems
-        */
-       msr.hi &= 0xc0000000;
-       msr.hi |= (0x01 << (52 - 32)); /* PSI3 threshold -  1A */
-       msr.hi |= (0x05 << (42 - 32)); /* PSI2 threshold -  5A */
-       msr.hi |= (0x14 << (32 - 32)); /* PSI1 threshold - 20A */
-       msr.hi |= (1 <<  (62 - 32)); /* Enable PSI4 */
-       /* Leave the max instantaneous current limit (12:0) to default */
-       msr_write(MSR_VR_CURRENT_CONFIG, msr);
-
-       /* Configure VR_MISC_CONFIG MSR */
-       msr = msr_read(MSR_VR_MISC_CONFIG);
-       /* Set the IOUT_SLOPE scalar applied to dIout in U10.1.9 format */
-       msr.hi &= ~(0x3ff << (40 - 32));
-       msr.hi |= (0x200 << (40 - 32)); /* 1.0 */
-       /* Set IOUT_OFFSET to 0 */
-       msr.hi &= ~0xff;
-       /* Set entry ramp rate to slow */
-       msr.hi &= ~(1 << (51 - 32));
-       /* Enable decay mode on C-state entry */
-       msr.hi |= (1 << (52 - 32));
-       /* Set the slow ramp rate */
-       msr.hi &= ~(0x3 << (53 - 32));
-       /* Configure the C-state exit ramp rate */
-       ramp = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-                             "intel,slow-ramp", -1);
-       if (ramp != -1) {
-               /* Configured slow ramp rate */
-               msr.hi |= ((ramp & 0x3) << (53 - 32));
-               /* Set exit ramp rate to slow */
-               msr.hi &= ~(1 << (50 - 32));
-       } else {
-               /* Fast ramp rate / 4 */
-               msr.hi |= (0x01 << (53 - 32));
-               /* Set exit ramp rate to fast */
-               msr.hi |= (1 << (50 - 32));
-       }
-       /* Set MIN_VID (31:24) to allow CPU to have full control */
-       msr.lo &= ~0xff000000;
-       min_vid = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-                                "intel,min-vid", 0);
-       msr.lo |= (min_vid & 0xff) << 24;
-       msr_write(MSR_VR_MISC_CONFIG, msr);
-
-       /*  Configure VR_MISC_CONFIG2 MSR */
-       msr = msr_read(MSR_VR_MISC_CONFIG2);
-       msr.lo &= ~0xffff;
-       /*
-        * Allow CPU to control minimum voltage completely (15:8) and
-        * set the fast ramp voltage in 10mV steps
-        */
-       if (cpu_get_family_model() == BROADWELL_FAMILY_ULT)
-               msr.lo |= 0x006a; /* 1.56V */
-       else
-               msr.lo |= 0x006f; /* 1.60V */
-       msr_write(MSR_VR_MISC_CONFIG2, msr);
-
-       /* Set C9/C10 VCC Min */
-       pcode_mailbox_write(MAILBOX_BIOS_CMD_WRITE_C9C10_VOLTAGE, 0x1f1f);
-}
-
-static int calibrate_24mhz_bclk(void)
-{
-       int err_code;
-       int ret;
-
-       ret = pcode_ready();
-       if (ret)
-               return ret;
-
-       /* A non-zero value initiates the PCODE calibration */
-       writel(~0, MCHBAR_REG(BIOS_MAILBOX_DATA));
-       writel(MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL,
-              MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
-
-       ret = pcode_ready();
-       if (ret)
-               return ret;
-
-       err_code = readl(MCHBAR_REG(BIOS_MAILBOX_INTERFACE)) & 0xff;
-
-       debug("PCODE: 24MHz BLCK calibration response: %d\n", err_code);
-
-       /* Read the calibrated value */
-       writel(MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_READ_CALIBRATION,
-              MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
-
-       ret = pcode_ready();
-       if (ret)
-               return ret;
-
-       debug("PCODE: 24MHz BLCK calibration value: 0x%08x\n",
-             readl(MCHBAR_REG(BIOS_MAILBOX_DATA)));
-
-       return 0;
-}
-
-static void configure_pch_power_sharing(void)
-{
-       u32 pch_power, pch_power_ext, pmsync, pmsync2;
-       int i;
-
-       /* Read PCH Power levels from PCODE */
-       pch_power = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER);
-       pch_power_ext = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT);
-
-       debug("PCH Power: PCODE Levels 0x%08x 0x%08x\n", pch_power,
-             pch_power_ext);
-
-       pmsync = readl(RCB_REG(PMSYNC_CONFIG));
-       pmsync2 = readl(RCB_REG(PMSYNC_CONFIG2));
-
-       /*
-        * Program PMSYNC_TPR_CONFIG PCH power limit values
-        *  pmsync[0:4]   = mailbox[0:5]
-        *  pmsync[8:12]  = mailbox[6:11]
-        *  pmsync[16:20] = mailbox[12:17]
-        */
-       for (i = 0; i < 3; i++) {
-               u32 level = pch_power & 0x3f;
-               pch_power >>= 6;
-               pmsync &= ~(0x1f << (i * 8));
-               pmsync |= (level & 0x1f) << (i * 8);
-       }
-       writel(pmsync, RCB_REG(PMSYNC_CONFIG));
-
-       /*
-        * Program PMSYNC_TPR_CONFIG2 Extended PCH power limit values
-        *  pmsync2[0:4]   = mailbox[23:18]
-        *  pmsync2[8:12]  = mailbox_ext[6:11]
-        *  pmsync2[16:20] = mailbox_ext[12:17]
-        *  pmsync2[24:28] = mailbox_ext[18:22]
-        */
-       pmsync2 &= ~0x1f;
-       pmsync2 |= pch_power & 0x1f;
-
-       for (i = 1; i < 4; i++) {
-               u32 level = pch_power_ext & 0x3f;
-               pch_power_ext >>= 6;
-               pmsync2 &= ~(0x1f << (i * 8));
-               pmsync2 |= (level & 0x1f) << (i * 8);
-       }
-       writel(pmsync2, RCB_REG(PMSYNC_CONFIG2));
-}
-
-static int bsp_init_before_ap_bringup(struct udevice *dev)
-{
-       int ret;
-
-       initialize_vr_config(dev);
-       ret = calibrate_24mhz_bclk();
-       if (ret)
-               return ret;
-       configure_pch_power_sharing();
-
-       return 0;
-}
-
-int cpu_config_tdp_levels(void)
-{
-       msr_t platform_info;
-
-       /* Bits 34:33 indicate how many levels supported */
-       platform_info = msr_read(MSR_PLATFORM_INFO);
-       return (platform_info.hi >> 1) & 3;
-}
-
-static void set_max_ratio(void)
-{
-       msr_t msr, perf_ctl;
-
-       perf_ctl.hi = 0;
-
-       /* Check for configurable TDP option */
-       if (turbo_get_state() == TURBO_ENABLED) {
-               msr = msr_read(MSR_NHM_TURBO_RATIO_LIMIT);
-               perf_ctl.lo = (msr.lo & 0xff) << 8;
-       } else if (cpu_config_tdp_levels()) {
-               /* Set to nominal TDP ratio */
-               msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
-               perf_ctl.lo = (msr.lo & 0xff) << 8;
-       } else {
-               /* Platform Info bits 15:8 give max ratio */
-               msr = msr_read(MSR_PLATFORM_INFO);
-               perf_ctl.lo = msr.lo & 0xff00;
-       }
-       msr_write(IA32_PERF_CTL, perf_ctl);
-
-       debug("cpu: frequency set to %d\n",
-             ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK);
-}
-
-int broadwell_init(struct udevice *dev)
-{
-       struct cpu_broadwell_priv *priv = dev_get_priv(dev);
-       int num_threads;
-       int num_cores;
-       msr_t msr;
-       int ret;
-
-       msr = msr_read(CORE_THREAD_COUNT_MSR);
-       num_threads = (msr.lo >> 0) & 0xffff;
-       num_cores = (msr.lo >> 16) & 0xffff;
-       debug("CPU has %u cores, %u threads enabled\n", num_cores,
-             num_threads);
-
-       priv->ht_disabled = num_threads == num_cores;
-
-       ret = bsp_init_before_ap_bringup(dev);
-       if (ret)
-               return ret;
-
-       set_max_ratio();
-
-       return ret;
-}
-
-static void configure_mca(void)
-{
-       msr_t msr;
-       const unsigned int mcg_cap_msr = 0x179;
-       int i;
-       int num_banks;
-
-       msr = msr_read(mcg_cap_msr);
-       num_banks = msr.lo & 0xff;
-       msr.lo = 0;
-       msr.hi = 0;
-       /*
-        * TODO(adurbin): This should only be done on a cold boot. Also, some
-        * of these banks are core vs package scope. For now every CPU clears
-        * every bank
-        */
-       for (i = 0; i < num_banks; i++)
-               msr_write(MSR_IA32_MC0_STATUS + (i * 4), msr);
-}
-
-static void enable_lapic_tpr(void)
-{
-       msr_t msr;
-
-       msr = msr_read(MSR_PIC_MSG_CONTROL);
-       msr.lo &= ~(1 << 10);   /* Enable APIC TPR updates */
-       msr_write(MSR_PIC_MSG_CONTROL, msr);
-}
-
-
-static void configure_c_states(void)
-{
-       msr_t msr;
-
-       msr = msr_read(MSR_PMG_CST_CONFIG_CONTROL);
-       msr.lo |= (1 << 31);    /* Timed MWAIT Enable */
-       msr.lo |= (1 << 30);    /* Package c-state Undemotion Enable */
-       msr.lo |= (1 << 29);    /* Package c-state Demotion Enable */
-       msr.lo |= (1 << 28);    /* C1 Auto Undemotion Enable */
-       msr.lo |= (1 << 27);    /* C3 Auto Undemotion Enable */
-       msr.lo |= (1 << 26);    /* C1 Auto Demotion Enable */
-       msr.lo |= (1 << 25);    /* C3 Auto Demotion Enable */
-       msr.lo &= ~(1 << 10);   /* Disable IO MWAIT redirection */
-       /* The deepest package c-state defaults to factory-configured value */
-       msr_write(MSR_PMG_CST_CONFIG_CONTROL, msr);
-
-       msr = msr_read(MSR_MISC_PWR_MGMT);
-       msr.lo &= ~(1 << 0);    /* Enable P-state HW_ALL coordination */
-       msr_write(MSR_MISC_PWR_MGMT, msr);
-
-       msr = msr_read(MSR_POWER_CTL);
-       msr.lo |= (1 << 18);    /* Enable Energy Perf Bias MSR 0x1b0 */
-       msr.lo |= (1 << 1);     /* C1E Enable */
-       msr.lo |= (1 << 0);     /* Bi-directional PROCHOT# */
-       msr_write(MSR_POWER_CTL, msr);
-
-       /* C-state Interrupt Response Latency Control 0 - package C3 latency */
-       msr.hi = 0;
-       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_0_LIMIT;
-       msr_write(MSR_C_STATE_LATENCY_CONTROL_0, msr);
-
-       /* C-state Interrupt Response Latency Control 1 */
-       msr.hi = 0;
-       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_1_LIMIT;
-       msr_write(MSR_C_STATE_LATENCY_CONTROL_1, msr);
-
-       /* C-state Interrupt Response Latency Control 2 - package C6/C7 short */
-       msr.hi = 0;
-       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT;
-       msr_write(MSR_C_STATE_LATENCY_CONTROL_2, msr);
-
-       /* C-state Interrupt Response Latency Control 3 - package C8 */
-       msr.hi = 0;
-       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_3_LIMIT;
-       msr_write(MSR_C_STATE_LATENCY_CONTROL_3, msr);
-
-       /* C-state Interrupt Response Latency Control 4 - package C9 */
-       msr.hi = 0;
-       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_4_LIMIT;
-       msr_write(MSR_C_STATE_LATENCY_CONTROL_4, msr);
-
-       /* C-state Interrupt Response Latency Control 5 - package C10 */
-       msr.hi = 0;
-       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_5_LIMIT;
-       msr_write(MSR_C_STATE_LATENCY_CONTROL_5, msr);
-}
-
-static void configure_misc(void)
-{
-       msr_t msr;
-
-       msr = msr_read(MSR_IA32_MISC_ENABLE);
-       msr.lo |= (1 << 0);       /* Fast String enable */
-       msr.lo |= (1 << 3);       /* TM1/TM2/EMTTM enable */
-       msr.lo |= (1 << 16);      /* Enhanced SpeedStep Enable */
-       msr_write(MSR_IA32_MISC_ENABLE, msr);
-
-       /* Disable thermal interrupts */
-       msr.lo = 0;
-       msr.hi = 0;
-       msr_write(MSR_IA32_THERM_INTERRUPT, msr);
-
-       /* Enable package critical interrupt only */
-       msr.lo = 1 << 4;
-       msr.hi = 0;
-       msr_write(MSR_IA32_PACKAGE_THERM_INTERRUPT, msr);
-}
-
-static void configure_thermal_target(struct udevice *dev)
-{
-       int tcc_offset;
-       msr_t msr;
-
-       tcc_offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-                                   "intel,tcc-offset", 0);
-
-       /* Set TCC activaiton offset if supported */
-       msr = msr_read(MSR_PLATFORM_INFO);
-       if ((msr.lo & (1 << 30)) && tcc_offset) {
-               msr = msr_read(MSR_TEMPERATURE_TARGET);
-               msr.lo &= ~(0xf << 24); /* Bits 27:24 */
-               msr.lo |= (tcc_offset & 0xf) << 24;
-               msr_write(MSR_TEMPERATURE_TARGET, msr);
-       }
-}
-
-static void configure_dca_cap(void)
-{
-       struct cpuid_result cpuid_regs;
-       msr_t msr;
-
-       /* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
-       cpuid_regs = cpuid(1);
-       if (cpuid_regs.ecx & (1 << 18)) {
-               msr = msr_read(MSR_IA32_PLATFORM_DCA_CAP);
-               msr.lo |= 1;
-               msr_write(MSR_IA32_PLATFORM_DCA_CAP, msr);
-       }
-}
-
-static void set_energy_perf_bias(u8 policy)
-{
-       msr_t msr;
-       int ecx;
-
-       /* Determine if energy efficient policy is supported */
-       ecx = cpuid_ecx(0x6);
-       if (!(ecx & (1 << 3)))
-               return;
-
-       /* Energy Policy is bits 3:0 */
-       msr = msr_read(MSR_IA32_ENERGY_PERFORMANCE_BIAS);
-       msr.lo &= ~0xf;
-       msr.lo |= policy & 0xf;
-       msr_write(MSR_IA32_ENERGY_PERFORMANCE_BIAS, msr);
-
-       debug("cpu: energy policy set to %u\n", policy);
-}
-
-/* All CPUs including BSP will run the following function */
-static void cpu_core_init(struct udevice *dev)
-{
-       /* Clear out pending MCEs */
-       configure_mca();
-
-       /* Enable the local cpu apics */
-       enable_lapic_tpr();
-
-       /* Configure C States */
-       configure_c_states();
-
-       /* Configure Enhanced SpeedStep and Thermal Sensors */
-       configure_misc();
-
-       /* Thermal throttle activation offset */
-       configure_thermal_target(dev);
-
-       /* Enable Direct Cache Access */
-       configure_dca_cap();
-
-       /* Set energy policy */
-       set_energy_perf_bias(ENERGY_POLICY_NORMAL);
-
-       /* Enable Turbo */
-       turbo_enable();
-}
-
-/*
- * Configure processor power limits if possible
- * This must be done AFTER set of BIOS_RESET_CPL
- */
-void cpu_set_power_limits(int power_limit_1_time)
-{
-       msr_t msr;
-       msr_t limit;
-       unsigned power_unit;
-       unsigned tdp, min_power, max_power, max_time;
-       u8 power_limit_1_val;
-
-       msr = msr_read(MSR_PLATFORM_INFO);
-       if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
-               power_limit_1_time = 28;
-
-       if (!(msr.lo & PLATFORM_INFO_SET_TDP))
-               return;
-
-       /* Get units */
-       msr = msr_read(MSR_PKG_POWER_SKU_UNIT);
-       power_unit = 2 << ((msr.lo & 0xf) - 1);
-
-       /* Get power defaults for this SKU */
-       msr = msr_read(MSR_PKG_POWER_SKU);
-       tdp = msr.lo & 0x7fff;
-       min_power = (msr.lo >> 16) & 0x7fff;
-       max_power = msr.hi & 0x7fff;
-       max_time = (msr.hi >> 16) & 0x7f;
-
-       debug("CPU TDP: %u Watts\n", tdp / power_unit);
-
-       if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time)
-               power_limit_1_time = power_limit_time_msr_to_sec[max_time];
-
-       if (min_power > 0 && tdp < min_power)
-               tdp = min_power;
-
-       if (max_power > 0 && tdp > max_power)
-               tdp = max_power;
-
-       power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time];
-
-       /* Set long term power limit to TDP */
-       limit.lo = 0;
-       limit.lo |= tdp & PKG_POWER_LIMIT_MASK;
-       limit.lo |= PKG_POWER_LIMIT_EN;
-       limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) <<
-               PKG_POWER_LIMIT_TIME_SHIFT;
-
-       /* Set short term power limit to 1.25 * TDP */
-       limit.hi = 0;
-       limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
-       limit.hi |= PKG_POWER_LIMIT_EN;
-       /* Power limit 2 time is only programmable on server SKU */
-
-       msr_write(MSR_PKG_POWER_LIMIT, limit);
-
-       /* Set power limit values in MCHBAR as well */
-       writel(limit.lo, MCHBAR_REG(MCH_PKG_POWER_LIMIT_LO));
-       writel(limit.hi, MCHBAR_REG(MCH_PKG_POWER_LIMIT_HI));
-
-       /* Set DDR RAPL power limit by copying from MMIO to MSR */
-       msr.lo = readl(MCHBAR_REG(MCH_DDR_POWER_LIMIT_LO));
-       msr.hi = readl(MCHBAR_REG(MCH_DDR_POWER_LIMIT_HI));
-       msr_write(MSR_DDR_RAPL_LIMIT, msr);
-
-       /* Use nominal TDP values for CPUs with configurable TDP */
-       if (cpu_config_tdp_levels()) {
-               msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
-               limit.hi = 0;
-               limit.lo = msr.lo & 0xff;
-               msr_write(MSR_TURBO_ACTIVATION_RATIO, limit);
-       }
-}
-
-static int broadwell_get_info(struct udevice *dev, struct cpu_info *info)
-{
-       msr_t msr;
-
-       msr = msr_read(IA32_PERF_CTL);
-       info->cpu_freq = ((msr.lo >> 8) & 0xff) * BROADWELL_BCLK * 1000000;
-       info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU |
-               1 << CPU_FEAT_UCODE | 1 << CPU_FEAT_DEVICE_ID;
-
-       return 0;
-}
-
-static int broadwell_get_count(struct udevice *dev)
+void board_debug_uart_init(void)
 {
-       return 4;
-}
+       struct udevice *bus = NULL;
 
-static int cpu_x86_broadwell_probe(struct udevice *dev)
-{
-       if (dev->seq == 0) {
-               cpu_core_init(dev);
-               return broadwell_init(dev);
-       }
+       /* com1 / com2 decode range */
+       pci_x86_write_config(bus, PCH_DEV_LPC, LPC_IO_DEC, 1 << 4, PCI_SIZE_16);
 
-       return 0;
+       pci_x86_write_config(bus, PCH_DEV_LPC, LPC_EN, COMA_LPC_EN,
+                            PCI_SIZE_16);
 }
-
-static const struct cpu_ops cpu_x86_broadwell_ops = {
-       .get_desc       = cpu_x86_get_desc,
-       .get_info       = broadwell_get_info,
-       .get_count      = broadwell_get_count,
-       .get_vendor     = cpu_x86_get_vendor,
-};
-
-static const struct udevice_id cpu_x86_broadwell_ids[] = {
-       { .compatible = "intel,core-i3-gen5" },
-       { }
-};
-
-U_BOOT_DRIVER(cpu_x86_broadwell_drv) = {
-       .name           = "cpu_x86_broadwell",
-       .id             = UCLASS_CPU,
-       .of_match       = cpu_x86_broadwell_ids,
-       .bind           = cpu_x86_bind,
-       .probe          = cpu_x86_broadwell_probe,
-       .ops            = &cpu_x86_broadwell_ops,
-       .priv_auto_alloc_size   = sizeof(struct cpu_broadwell_priv),
-       .flags          = DM_FLAG_PRE_RELOC,
-};
diff --git a/arch/x86/cpu/broadwell/cpu_from_spl.c b/arch/x86/cpu/broadwell/cpu_from_spl.c
new file mode 100644 (file)
index 0000000..c3d4a8d
--- /dev/null
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bloblist.h>
+#include <debug_uart.h>
+#include <handoff.h>
+#include <asm/mtrr.h>
+
+int misc_init_r(void)
+{
+       return 0;
+}
+
+int dram_init(void)
+{
+       struct spl_handoff *ho;
+
+       ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(*ho));
+       if (!ho)
+               return log_msg_ret("Missing SPL hand-off info", -ENOENT);
+       handoff_load_dram_size(ho);
+#ifdef CONFIG_TPL
+       /* TODO(sjg@chromium.org): MTRR cannot be adjusted without a hang */
+       mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30);
+#else
+       mtrr_add_request(MTRR_TYPE_WRBACK, 0, gd->ram_size);
+       mtrr_commit(true);
+#endif
+
+       return 0;
+}
+
+int checkcpu(void)
+{
+       return 0;
+}
+
+int print_cpuinfo(void)
+{
+       return 0;
+}
+
+void board_debug_uart_init(void)
+{
+}
+
+int dram_init_banksize(void)
+{
+#ifdef CONFIG_NR_DRAM_BANKS
+       struct spl_handoff *ho;
+
+       ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(*ho));
+       if (!ho)
+               return log_msg_ret("Missing SPL hand-off info", -ENOENT);
+       handoff_load_dram_banks(ho);
+#endif
+
+       return 0;
+}
diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c
new file mode 100644 (file)
index 0000000..c1db184
--- /dev/null
@@ -0,0 +1,694 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * Based on code from coreboot src/soc/intel/broadwell/cpu.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <cpu.h>
+#include <asm/cpu.h>
+#include <asm/cpu_x86.h>
+#include <asm/cpu_common.h>
+#include <asm/intel_regs.h>
+#include <asm/msr.h>
+#include <asm/post.h>
+#include <asm/turbo.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/rcb.h>
+
+struct cpu_broadwell_priv {
+       bool ht_disabled;
+};
+
+/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
+static const u8 power_limit_time_sec_to_msr[] = {
+       [0]   = 0x00,
+       [1]   = 0x0a,
+       [2]   = 0x0b,
+       [3]   = 0x4b,
+       [4]   = 0x0c,
+       [5]   = 0x2c,
+       [6]   = 0x4c,
+       [7]   = 0x6c,
+       [8]   = 0x0d,
+       [10]  = 0x2d,
+       [12]  = 0x4d,
+       [14]  = 0x6d,
+       [16]  = 0x0e,
+       [20]  = 0x2e,
+       [24]  = 0x4e,
+       [28]  = 0x6e,
+       [32]  = 0x0f,
+       [40]  = 0x2f,
+       [48]  = 0x4f,
+       [56]  = 0x6f,
+       [64]  = 0x10,
+       [80]  = 0x30,
+       [96]  = 0x50,
+       [112] = 0x70,
+       [128] = 0x11,
+};
+
+/* Convert POWER_LIMIT_1_TIME MSR value to seconds */
+static const u8 power_limit_time_msr_to_sec[] = {
+       [0x00] = 0,
+       [0x0a] = 1,
+       [0x0b] = 2,
+       [0x4b] = 3,
+       [0x0c] = 4,
+       [0x2c] = 5,
+       [0x4c] = 6,
+       [0x6c] = 7,
+       [0x0d] = 8,
+       [0x2d] = 10,
+       [0x4d] = 12,
+       [0x6d] = 14,
+       [0x0e] = 16,
+       [0x2e] = 20,
+       [0x4e] = 24,
+       [0x6e] = 28,
+       [0x0f] = 32,
+       [0x2f] = 40,
+       [0x4f] = 48,
+       [0x6f] = 56,
+       [0x10] = 64,
+       [0x30] = 80,
+       [0x50] = 96,
+       [0x70] = 112,
+       [0x11] = 128,
+};
+
+/*
+ * The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate
+ * the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly
+ * when a core is woken up
+ */
+static int pcode_ready(void)
+{
+       int wait_count;
+       const int delay_step = 10;
+
+       wait_count = 0;
+       do {
+               if (!(readl(MCHBAR_REG(BIOS_MAILBOX_INTERFACE)) &
+                               MAILBOX_RUN_BUSY))
+                       return 0;
+               wait_count += delay_step;
+               udelay(delay_step);
+       } while (wait_count < 1000);
+
+       return -ETIMEDOUT;
+}
+
+static u32 pcode_mailbox_read(u32 command)
+{
+       int ret;
+
+       ret = pcode_ready();
+       if (ret) {
+               debug("PCODE: mailbox timeout on wait ready\n");
+               return ret;
+       }
+
+       /* Send command and start transaction */
+       writel(command | MAILBOX_RUN_BUSY, MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
+
+       ret = pcode_ready();
+       if (ret) {
+               debug("PCODE: mailbox timeout on completion\n");
+               return ret;
+       }
+
+       /* Read mailbox */
+       return readl(MCHBAR_REG(BIOS_MAILBOX_DATA));
+}
+
+static int pcode_mailbox_write(u32 command, u32 data)
+{
+       int ret;
+
+       ret = pcode_ready();
+       if (ret) {
+               debug("PCODE: mailbox timeout on wait ready\n");
+               return ret;
+       }
+
+       writel(data, MCHBAR_REG(BIOS_MAILBOX_DATA));
+
+       /* Send command and start transaction */
+       writel(command | MAILBOX_RUN_BUSY, MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
+
+       ret = pcode_ready();
+       if (ret) {
+               debug("PCODE: mailbox timeout on completion\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+/* @dev is the CPU device */
+static void initialize_vr_config(struct udevice *dev)
+{
+       int ramp, min_vid;
+       msr_t msr;
+
+       debug("Initializing VR config\n");
+
+       /* Configure VR_CURRENT_CONFIG */
+       msr = msr_read(MSR_VR_CURRENT_CONFIG);
+       /*
+        * Preserve bits 63 and 62. Bit 62 is PSI4 enable, but it is only valid
+        * on ULT systems
+        */
+       msr.hi &= 0xc0000000;
+       msr.hi |= (0x01 << (52 - 32)); /* PSI3 threshold -  1A */
+       msr.hi |= (0x05 << (42 - 32)); /* PSI2 threshold -  5A */
+       msr.hi |= (0x14 << (32 - 32)); /* PSI1 threshold - 20A */
+       msr.hi |= (1 <<  (62 - 32)); /* Enable PSI4 */
+       /* Leave the max instantaneous current limit (12:0) to default */
+       msr_write(MSR_VR_CURRENT_CONFIG, msr);
+
+       /* Configure VR_MISC_CONFIG MSR */
+       msr = msr_read(MSR_VR_MISC_CONFIG);
+       /* Set the IOUT_SLOPE scalar applied to dIout in U10.1.9 format */
+       msr.hi &= ~(0x3ff << (40 - 32));
+       msr.hi |= (0x200 << (40 - 32)); /* 1.0 */
+       /* Set IOUT_OFFSET to 0 */
+       msr.hi &= ~0xff;
+       /* Set entry ramp rate to slow */
+       msr.hi &= ~(1 << (51 - 32));
+       /* Enable decay mode on C-state entry */
+       msr.hi |= (1 << (52 - 32));
+       /* Set the slow ramp rate */
+       msr.hi &= ~(0x3 << (53 - 32));
+       /* Configure the C-state exit ramp rate */
+       ramp = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+                             "intel,slow-ramp", -1);
+       if (ramp != -1) {
+               /* Configured slow ramp rate */
+               msr.hi |= ((ramp & 0x3) << (53 - 32));
+               /* Set exit ramp rate to slow */
+               msr.hi &= ~(1 << (50 - 32));
+       } else {
+               /* Fast ramp rate / 4 */
+               msr.hi |= (0x01 << (53 - 32));
+               /* Set exit ramp rate to fast */
+               msr.hi |= (1 << (50 - 32));
+       }
+       /* Set MIN_VID (31:24) to allow CPU to have full control */
+       msr.lo &= ~0xff000000;
+       min_vid = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+                                "intel,min-vid", 0);
+       msr.lo |= (min_vid & 0xff) << 24;
+       msr_write(MSR_VR_MISC_CONFIG, msr);
+
+       /*  Configure VR_MISC_CONFIG2 MSR */
+       msr = msr_read(MSR_VR_MISC_CONFIG2);
+       msr.lo &= ~0xffff;
+       /*
+        * Allow CPU to control minimum voltage completely (15:8) and
+        * set the fast ramp voltage in 10mV steps
+        */
+       if (cpu_get_family_model() == BROADWELL_FAMILY_ULT)
+               msr.lo |= 0x006a; /* 1.56V */
+       else
+               msr.lo |= 0x006f; /* 1.60V */
+       msr_write(MSR_VR_MISC_CONFIG2, msr);
+
+       /* Set C9/C10 VCC Min */
+       pcode_mailbox_write(MAILBOX_BIOS_CMD_WRITE_C9C10_VOLTAGE, 0x1f1f);
+}
+
+static int calibrate_24mhz_bclk(void)
+{
+       int err_code;
+       int ret;
+
+       ret = pcode_ready();
+       if (ret)
+               return ret;
+
+       /* A non-zero value initiates the PCODE calibration */
+       writel(~0, MCHBAR_REG(BIOS_MAILBOX_DATA));
+       writel(MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL,
+              MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
+
+       ret = pcode_ready();
+       if (ret)
+               return ret;
+
+       err_code = readl(MCHBAR_REG(BIOS_MAILBOX_INTERFACE)) & 0xff;
+
+       debug("PCODE: 24MHz BLCK calibration response: %d\n", err_code);
+
+       /* Read the calibrated value */
+       writel(MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_READ_CALIBRATION,
+              MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
+
+       ret = pcode_ready();
+       if (ret)
+               return ret;
+
+       debug("PCODE: 24MHz BLCK calibration value: 0x%08x\n",
+             readl(MCHBAR_REG(BIOS_MAILBOX_DATA)));
+
+       return 0;
+}
+
+static void configure_pch_power_sharing(void)
+{
+       u32 pch_power, pch_power_ext, pmsync, pmsync2;
+       int i;
+
+       /* Read PCH Power levels from PCODE */
+       pch_power = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER);
+       pch_power_ext = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT);
+
+       debug("PCH Power: PCODE Levels 0x%08x 0x%08x\n", pch_power,
+             pch_power_ext);
+
+       pmsync = readl(RCB_REG(PMSYNC_CONFIG));
+       pmsync2 = readl(RCB_REG(PMSYNC_CONFIG2));
+
+       /*
+        * Program PMSYNC_TPR_CONFIG PCH power limit values
+        *  pmsync[0:4]   = mailbox[0:5]
+        *  pmsync[8:12]  = mailbox[6:11]
+        *  pmsync[16:20] = mailbox[12:17]
+        */
+       for (i = 0; i < 3; i++) {
+               u32 level = pch_power & 0x3f;
+
+               pch_power >>= 6;
+               pmsync &= ~(0x1f << (i * 8));
+               pmsync |= (level & 0x1f) << (i * 8);
+       }
+       writel(pmsync, RCB_REG(PMSYNC_CONFIG));
+
+       /*
+        * Program PMSYNC_TPR_CONFIG2 Extended PCH power limit values
+        *  pmsync2[0:4]   = mailbox[23:18]
+        *  pmsync2[8:12]  = mailbox_ext[6:11]
+        *  pmsync2[16:20] = mailbox_ext[12:17]
+        *  pmsync2[24:28] = mailbox_ext[18:22]
+        */
+       pmsync2 &= ~0x1f;
+       pmsync2 |= pch_power & 0x1f;
+
+       for (i = 1; i < 4; i++) {
+               u32 level = pch_power_ext & 0x3f;
+
+               pch_power_ext >>= 6;
+               pmsync2 &= ~(0x1f << (i * 8));
+               pmsync2 |= (level & 0x1f) << (i * 8);
+       }
+       writel(pmsync2, RCB_REG(PMSYNC_CONFIG2));
+}
+
+static int bsp_init_before_ap_bringup(struct udevice *dev)
+{
+       int ret;
+
+       initialize_vr_config(dev);
+       ret = calibrate_24mhz_bclk();
+       if (ret)
+               return ret;
+       configure_pch_power_sharing();
+
+       return 0;
+}
+
+static int cpu_config_tdp_levels(void)
+{
+       msr_t platform_info;
+
+       /* Bits 34:33 indicate how many levels supported */
+       platform_info = msr_read(MSR_PLATFORM_INFO);
+       return (platform_info.hi >> 1) & 3;
+}
+
+static void set_max_ratio(void)
+{
+       msr_t msr, perf_ctl;
+
+       perf_ctl.hi = 0;
+
+       /* Check for configurable TDP option */
+       if (turbo_get_state() == TURBO_ENABLED) {
+               msr = msr_read(MSR_NHM_TURBO_RATIO_LIMIT);
+               perf_ctl.lo = (msr.lo & 0xff) << 8;
+       } else if (cpu_config_tdp_levels()) {
+               /* Set to nominal TDP ratio */
+               msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+               perf_ctl.lo = (msr.lo & 0xff) << 8;
+       } else {
+               /* Platform Info bits 15:8 give max ratio */
+               msr = msr_read(MSR_PLATFORM_INFO);
+               perf_ctl.lo = msr.lo & 0xff00;
+       }
+       msr_write(IA32_PERF_CTL, perf_ctl);
+
+       debug("cpu: frequency set to %d\n",
+             ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK);
+}
+
+int broadwell_init(struct udevice *dev)
+{
+       struct cpu_broadwell_priv *priv = dev_get_priv(dev);
+       int num_threads;
+       int num_cores;
+       msr_t msr;
+       int ret;
+
+       msr = msr_read(CORE_THREAD_COUNT_MSR);
+       num_threads = (msr.lo >> 0) & 0xffff;
+       num_cores = (msr.lo >> 16) & 0xffff;
+       debug("CPU has %u cores, %u threads enabled\n", num_cores,
+             num_threads);
+
+       priv->ht_disabled = num_threads == num_cores;
+
+       ret = bsp_init_before_ap_bringup(dev);
+       if (ret)
+               return ret;
+
+       set_max_ratio();
+
+       return ret;
+}
+
+static void configure_mca(void)
+{
+       msr_t msr;
+       const unsigned int mcg_cap_msr = 0x179;
+       int i;
+       int num_banks;
+
+       msr = msr_read(mcg_cap_msr);
+       num_banks = msr.lo & 0xff;
+       msr.lo = 0;
+       msr.hi = 0;
+       /*
+        * TODO(adurbin): This should only be done on a cold boot. Also, some
+        * of these banks are core vs package scope. For now every CPU clears
+        * every bank
+        */
+       for (i = 0; i < num_banks; i++)
+               msr_write(MSR_IA32_MC0_STATUS + (i * 4), msr);
+}
+
+static void enable_lapic_tpr(void)
+{
+       msr_t msr;
+
+       msr = msr_read(MSR_PIC_MSG_CONTROL);
+       msr.lo &= ~(1 << 10);   /* Enable APIC TPR updates */
+       msr_write(MSR_PIC_MSG_CONTROL, msr);
+}
+
+static void configure_c_states(void)
+{
+       msr_t msr;
+
+       msr = msr_read(MSR_PMG_CST_CONFIG_CONTROL);
+       msr.lo |= (1 << 31);    /* Timed MWAIT Enable */
+       msr.lo |= (1 << 30);    /* Package c-state Undemotion Enable */
+       msr.lo |= (1 << 29);    /* Package c-state Demotion Enable */
+       msr.lo |= (1 << 28);    /* C1 Auto Undemotion Enable */
+       msr.lo |= (1 << 27);    /* C3 Auto Undemotion Enable */
+       msr.lo |= (1 << 26);    /* C1 Auto Demotion Enable */
+       msr.lo |= (1 << 25);    /* C3 Auto Demotion Enable */
+       msr.lo &= ~(1 << 10);   /* Disable IO MWAIT redirection */
+       /* The deepest package c-state defaults to factory-configured value */
+       msr_write(MSR_PMG_CST_CONFIG_CONTROL, msr);
+
+       msr = msr_read(MSR_MISC_PWR_MGMT);
+       msr.lo &= ~(1 << 0);    /* Enable P-state HW_ALL coordination */
+       msr_write(MSR_MISC_PWR_MGMT, msr);
+
+       msr = msr_read(MSR_POWER_CTL);
+       msr.lo |= (1 << 18);    /* Enable Energy Perf Bias MSR 0x1b0 */
+       msr.lo |= (1 << 1);     /* C1E Enable */
+       msr.lo |= (1 << 0);     /* Bi-directional PROCHOT# */
+       msr_write(MSR_POWER_CTL, msr);
+
+       /* C-state Interrupt Response Latency Control 0 - package C3 latency */
+       msr.hi = 0;
+       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_0_LIMIT;
+       msr_write(MSR_C_STATE_LATENCY_CONTROL_0, msr);
+
+       /* C-state Interrupt Response Latency Control 1 */
+       msr.hi = 0;
+       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_1_LIMIT;
+       msr_write(MSR_C_STATE_LATENCY_CONTROL_1, msr);
+
+       /* C-state Interrupt Response Latency Control 2 - package C6/C7 short */
+       msr.hi = 0;
+       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT;
+       msr_write(MSR_C_STATE_LATENCY_CONTROL_2, msr);
+
+       /* C-state Interrupt Response Latency Control 3 - package C8 */
+       msr.hi = 0;
+       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_3_LIMIT;
+       msr_write(MSR_C_STATE_LATENCY_CONTROL_3, msr);
+
+       /* C-state Interrupt Response Latency Control 4 - package C9 */
+       msr.hi = 0;
+       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_4_LIMIT;
+       msr_write(MSR_C_STATE_LATENCY_CONTROL_4, msr);
+
+       /* C-state Interrupt Response Latency Control 5 - package C10 */
+       msr.hi = 0;
+       msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_5_LIMIT;
+       msr_write(MSR_C_STATE_LATENCY_CONTROL_5, msr);
+}
+
+static void configure_misc(void)
+{
+       msr_t msr;
+
+       msr = msr_read(MSR_IA32_MISC_ENABLE);
+       msr.lo |= (1 << 0);       /* Fast String enable */
+       msr.lo |= (1 << 3);       /* TM1/TM2/EMTTM enable */
+       msr.lo |= (1 << 16);      /* Enhanced SpeedStep Enable */
+       msr_write(MSR_IA32_MISC_ENABLE, msr);
+
+       /* Disable thermal interrupts */
+       msr.lo = 0;
+       msr.hi = 0;
+       msr_write(MSR_IA32_THERM_INTERRUPT, msr);
+
+       /* Enable package critical interrupt only */
+       msr.lo = 1 << 4;
+       msr.hi = 0;
+       msr_write(MSR_IA32_PACKAGE_THERM_INTERRUPT, msr);
+}
+
+static void configure_thermal_target(struct udevice *dev)
+{
+       int tcc_offset;
+       msr_t msr;
+
+       tcc_offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+                                   "intel,tcc-offset", 0);
+
+       /* Set TCC activaiton offset if supported */
+       msr = msr_read(MSR_PLATFORM_INFO);
+       if ((msr.lo & (1 << 30)) && tcc_offset) {
+               msr = msr_read(MSR_TEMPERATURE_TARGET);
+               msr.lo &= ~(0xf << 24); /* Bits 27:24 */
+               msr.lo |= (tcc_offset & 0xf) << 24;
+               msr_write(MSR_TEMPERATURE_TARGET, msr);
+       }
+}
+
+static void configure_dca_cap(void)
+{
+       struct cpuid_result cpuid_regs;
+       msr_t msr;
+
+       /* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
+       cpuid_regs = cpuid(1);
+       if (cpuid_regs.ecx & (1 << 18)) {
+               msr = msr_read(MSR_IA32_PLATFORM_DCA_CAP);
+               msr.lo |= 1;
+               msr_write(MSR_IA32_PLATFORM_DCA_CAP, msr);
+       }
+}
+
+static void set_energy_perf_bias(u8 policy)
+{
+       msr_t msr;
+       int ecx;
+
+       /* Determine if energy efficient policy is supported */
+       ecx = cpuid_ecx(0x6);
+       if (!(ecx & (1 << 3)))
+               return;
+
+       /* Energy Policy is bits 3:0 */
+       msr = msr_read(MSR_IA32_ENERGY_PERFORMANCE_BIAS);
+       msr.lo &= ~0xf;
+       msr.lo |= policy & 0xf;
+       msr_write(MSR_IA32_ENERGY_PERFORMANCE_BIAS, msr);
+
+       debug("cpu: energy policy set to %u\n", policy);
+}
+
+/* All CPUs including BSP will run the following function */
+static void cpu_core_init(struct udevice *dev)
+{
+       /* Clear out pending MCEs */
+       configure_mca();
+
+       /* Enable the local cpu apics */
+       enable_lapic_tpr();
+
+       /* Configure C States */
+       configure_c_states();
+
+       /* Configure Enhanced SpeedStep and Thermal Sensors */
+       configure_misc();
+
+       /* Thermal throttle activation offset */
+       configure_thermal_target(dev);
+
+       /* Enable Direct Cache Access */
+       configure_dca_cap();
+
+       /* Set energy policy */
+       set_energy_perf_bias(ENERGY_POLICY_NORMAL);
+
+       /* Enable Turbo */
+       turbo_enable();
+}
+
+/*
+ * Configure processor power limits if possible
+ * This must be done AFTER set of BIOS_RESET_CPL
+ */
+void cpu_set_power_limits(int power_limit_1_time)
+{
+       msr_t msr;
+       msr_t limit;
+       uint power_unit;
+       uint tdp, min_power, max_power, max_time;
+       u8 power_limit_1_val;
+
+       msr = msr_read(MSR_PLATFORM_INFO);
+       if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
+               power_limit_1_time = 28;
+
+       if (!(msr.lo & PLATFORM_INFO_SET_TDP))
+               return;
+
+       /* Get units */
+       msr = msr_read(MSR_PKG_POWER_SKU_UNIT);
+       power_unit = 2 << ((msr.lo & 0xf) - 1);
+
+       /* Get power defaults for this SKU */
+       msr = msr_read(MSR_PKG_POWER_SKU);
+       tdp = msr.lo & 0x7fff;
+       min_power = (msr.lo >> 16) & 0x7fff;
+       max_power = msr.hi & 0x7fff;
+       max_time = (msr.hi >> 16) & 0x7f;
+
+       debug("CPU TDP: %u Watts\n", tdp / power_unit);
+
+       if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time)
+               power_limit_1_time = power_limit_time_msr_to_sec[max_time];
+
+       if (min_power > 0 && tdp < min_power)
+               tdp = min_power;
+
+       if (max_power > 0 && tdp > max_power)
+               tdp = max_power;
+
+       power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time];
+
+       /* Set long term power limit to TDP */
+       limit.lo = 0;
+       limit.lo |= tdp & PKG_POWER_LIMIT_MASK;
+       limit.lo |= PKG_POWER_LIMIT_EN;
+       limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) <<
+               PKG_POWER_LIMIT_TIME_SHIFT;
+
+       /* Set short term power limit to 1.25 * TDP */
+       limit.hi = 0;
+       limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
+       limit.hi |= PKG_POWER_LIMIT_EN;
+       /* Power limit 2 time is only programmable on server SKU */
+
+       msr_write(MSR_PKG_POWER_LIMIT, limit);
+
+       /* Set power limit values in MCHBAR as well */
+       writel(limit.lo, MCHBAR_REG(MCH_PKG_POWER_LIMIT_LO));
+       writel(limit.hi, MCHBAR_REG(MCH_PKG_POWER_LIMIT_HI));
+
+       /* Set DDR RAPL power limit by copying from MMIO to MSR */
+       msr.lo = readl(MCHBAR_REG(MCH_DDR_POWER_LIMIT_LO));
+       msr.hi = readl(MCHBAR_REG(MCH_DDR_POWER_LIMIT_HI));
+       msr_write(MSR_DDR_RAPL_LIMIT, msr);
+
+       /* Use nominal TDP values for CPUs with configurable TDP */
+       if (cpu_config_tdp_levels()) {
+               msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+               limit.hi = 0;
+               limit.lo = msr.lo & 0xff;
+               msr_write(MSR_TURBO_ACTIVATION_RATIO, limit);
+       }
+}
+
+static int broadwell_get_info(struct udevice *dev, struct cpu_info *info)
+{
+       msr_t msr;
+
+       msr = msr_read(IA32_PERF_CTL);
+       info->cpu_freq = ((msr.lo >> 8) & 0xff) * BROADWELL_BCLK * 1000000;
+       info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU |
+               1 << CPU_FEAT_UCODE | 1 << CPU_FEAT_DEVICE_ID;
+
+       return 0;
+}
+
+static int broadwell_get_count(struct udevice *dev)
+{
+       return 4;
+}
+
+static int cpu_x86_broadwell_probe(struct udevice *dev)
+{
+       if (dev->seq == 0) {
+               cpu_core_init(dev);
+               return broadwell_init(dev);
+       }
+
+       return 0;
+}
+
+static const struct cpu_ops cpu_x86_broadwell_ops = {
+       .get_desc       = cpu_x86_get_desc,
+       .get_info       = broadwell_get_info,
+       .get_count      = broadwell_get_count,
+       .get_vendor     = cpu_x86_get_vendor,
+};
+
+static const struct udevice_id cpu_x86_broadwell_ids[] = {
+       { .compatible = "intel,core-i3-gen5" },
+       { }
+};
+
+U_BOOT_DRIVER(cpu_x86_broadwell_drv) = {
+       .name           = "cpu_x86_broadwell",
+       .id             = UCLASS_CPU,
+       .of_match       = cpu_x86_broadwell_ids,
+       .bind           = cpu_x86_bind,
+       .probe          = cpu_x86_broadwell_probe,
+       .ops            = &cpu_x86_broadwell_ops,
+       .priv_auto_alloc_size   = sizeof(struct cpu_broadwell_priv),
+       .flags          = DM_FLAG_PRE_RELOC,
+};
index 3055880..4bcab78 100644 (file)
@@ -6,8 +6,108 @@
 #include <common.h>
 #include <dm.h>
 #include <asm/io.h>
+#include <asm/mrc_common.h>
 #include <asm/arch/iomap.h>
 #include <asm/arch/pch.h>
+#include <asm/arch/pei_data.h>
+
+__weak asmlinkage void sdram_console_tx_byte(unsigned char byte)
+{
+#ifdef DEBUG
+       putc(byte);
+#endif
+}
+
+void broadwell_fill_pei_data(struct pei_data *pei_data)
+{
+       pei_data->pei_version = PEI_VERSION;
+       pei_data->board_type = BOARD_TYPE_ULT;
+       pei_data->pciexbar = MCFG_BASE_ADDRESS;
+       pei_data->smbusbar = SMBUS_BASE_ADDRESS;
+       pei_data->ehcibar = EARLY_EHCI_BAR;
+       pei_data->xhcibar = EARLY_XHCI_BAR;
+       pei_data->gttbar = EARLY_GTT_BAR;
+       pei_data->pmbase = ACPI_BASE_ADDRESS;
+       pei_data->gpiobase = GPIO_BASE_ADDRESS;
+       pei_data->tseg_size = CONFIG_SMM_TSEG_SIZE;
+       pei_data->temp_mmio_base = EARLY_TEMP_MMIO;
+       pei_data->tx_byte = sdram_console_tx_byte;
+       pei_data->ddr_refresh_2x = 1;
+}
+
+static void pei_data_usb2_port(struct pei_data *pei_data, int port, uint length,
+                              uint enable, uint oc_pin, uint location)
+{
+       pei_data->usb2_ports[port].length   = length;
+       pei_data->usb2_ports[port].enable   = enable;
+       pei_data->usb2_ports[port].oc_pin   = oc_pin;
+       pei_data->usb2_ports[port].location = location;
+}
+
+static void pei_data_usb3_port(struct pei_data *pei_data, int port, uint enable,
+                              uint oc_pin, uint fixed_eq)
+{
+       pei_data->usb3_ports[port].enable   = enable;
+       pei_data->usb3_ports[port].oc_pin   = oc_pin;
+       pei_data->usb3_ports[port].fixed_eq = fixed_eq;
+}
+
+void mainboard_fill_pei_data(struct pei_data *pei_data)
+{
+       /* DQ byte map for Samus board */
+       const u8 dq_map[2][6][2] = {
+               { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 },
+                 { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } },
+               { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 },
+                 { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } } };
+       /* DQS CPU<>DRAM map for Samus board */
+       const u8 dqs_map[2][8] = {
+               { 2, 0, 1, 3, 6, 4, 7, 5 },
+               { 2, 1, 0, 3, 6, 5, 4, 7 } };
+
+       pei_data->ec_present = 1;
+
+       /* One installed DIMM per channel */
+       pei_data->dimm_channel0_disabled = 2;
+       pei_data->dimm_channel1_disabled = 2;
+
+       memcpy(pei_data->dq_map, dq_map, sizeof(dq_map));
+       memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map));
+
+       /* P0: HOST PORT */
+       pei_data_usb2_port(pei_data, 0, 0x0080, 1, 0,
+                          USB_PORT_BACK_PANEL);
+       /* P1: HOST PORT */
+       pei_data_usb2_port(pei_data, 1, 0x0080, 1, 1,
+                          USB_PORT_BACK_PANEL);
+       /* P2: RAIDEN */
+       pei_data_usb2_port(pei_data, 2, 0x0080, 1, USB_OC_PIN_SKIP,
+                          USB_PORT_BACK_PANEL);
+       /* P3: SD CARD */
+       pei_data_usb2_port(pei_data, 3, 0x0040, 1, USB_OC_PIN_SKIP,
+                          USB_PORT_INTERNAL);
+       /* P4: RAIDEN */
+       pei_data_usb2_port(pei_data, 4, 0x0080, 1, USB_OC_PIN_SKIP,
+                          USB_PORT_BACK_PANEL);
+       /* P5: WWAN (Disabled) */
+       pei_data_usb2_port(pei_data, 5, 0x0000, 0, USB_OC_PIN_SKIP,
+                          USB_PORT_SKIP);
+       /* P6: CAMERA */
+       pei_data_usb2_port(pei_data, 6, 0x0040, 1, USB_OC_PIN_SKIP,
+                          USB_PORT_INTERNAL);
+       /* P7: BT */
+       pei_data_usb2_port(pei_data, 7, 0x0040, 1, USB_OC_PIN_SKIP,
+                          USB_PORT_INTERNAL);
+
+       /* P1: HOST PORT */
+       pei_data_usb3_port(pei_data, 0, 1, 0, 0);
+       /* P2: HOST PORT */
+       pei_data_usb3_port(pei_data, 1, 1, 1, 0);
+       /* P3: RAIDEN */
+       pei_data_usb3_port(pei_data, 2, 1, USB_OC_PIN_SKIP, 0);
+       /* P4: RAIDEN */
+       pei_data_usb3_port(pei_data, 3, 1, USB_OC_PIN_SKIP, 0);
+}
 
 static int broadwell_northbridge_early_init(struct udevice *dev)
 {
index 73d3d3b..a48945a 100644 (file)
@@ -599,10 +599,16 @@ static int broadwell_pch_init(struct udevice *dev)
 
 static int broadwell_pch_probe(struct udevice *dev)
 {
-       if (!(gd->flags & GD_FLG_RELOC))
-               return broadwell_pch_early_init(dev);
-       else
+       if (CONFIG_IS_ENABLED(X86_32BIT_INIT)) {
+               if (!(gd->flags & GD_FLG_RELOC))
+                       return broadwell_pch_early_init(dev);
+               else
+                       return broadwell_pch_init(dev);
+       } else if (IS_ENABLED(CONFIG_SPL) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
                return broadwell_pch_init(dev);
+       } else {
+               return 0;
+       }
 }
 
 static int broadwell_pch_get_spi_base(struct udevice *dev, ulong *sbasep)
@@ -630,10 +636,35 @@ static int broadwell_get_gpio_base(struct udevice *dev, u32 *gbasep)
        return 0;
 }
 
+static int broadwell_ioctl(struct udevice *dev, enum pch_req_t req, void *data,
+                          int size)
+{
+       switch (req) {
+       case PCH_REQ_PMBASE_INFO: {
+               struct pch_pmbase_info *pm = data;
+               int ret;
+
+               /* Find the base address of the powermanagement registers */
+               ret = dm_pci_read_config16(dev, 0x40, &pm->base);
+               if (ret)
+                       return ret;
+               pm->base &= 0xfffe;
+               pm->gpio0_en_ofs = GPE0_EN(0);
+               pm->pm1_sts_ofs = PM1_STS;
+               pm->pm1_cnt_ofs = PM1_CNT;
+
+               return 0;
+       }
+       default:
+               return -ENOSYS;
+       }
+}
+
 static const struct pch_ops broadwell_pch_ops = {
        .get_spi_base   = broadwell_pch_get_spi_base,
        .set_spi_protect = broadwell_set_spi_protect,
        .get_gpio_base  = broadwell_get_gpio_base,
+       .ioctl          = broadwell_ioctl,
 };
 
 static const struct udevice_id broadwell_pch_ids[] = {
index 03a35bc..b31d78c 100644 (file)
@@ -34,99 +34,6 @@ int dram_init_banksize(void)
        return 0;
 }
 
-void broadwell_fill_pei_data(struct pei_data *pei_data)
-{
-       pei_data->pei_version = PEI_VERSION;
-       pei_data->board_type = BOARD_TYPE_ULT;
-       pei_data->pciexbar = MCFG_BASE_ADDRESS;
-       pei_data->smbusbar = SMBUS_BASE_ADDRESS;
-       pei_data->ehcibar = EARLY_EHCI_BAR;
-       pei_data->xhcibar = EARLY_XHCI_BAR;
-       pei_data->gttbar = EARLY_GTT_BAR;
-       pei_data->pmbase = ACPI_BASE_ADDRESS;
-       pei_data->gpiobase = GPIO_BASE_ADDRESS;
-       pei_data->tseg_size = CONFIG_SMM_TSEG_SIZE;
-       pei_data->temp_mmio_base = EARLY_TEMP_MMIO;
-       pei_data->tx_byte = sdram_console_tx_byte;
-       pei_data->ddr_refresh_2x = 1;
-}
-
-static inline void pei_data_usb2_port(struct pei_data *pei_data, int port,
-                                     uint16_t length, uint8_t enable,
-                                     uint8_t oc_pin, uint8_t location)
-{
-       pei_data->usb2_ports[port].length   = length;
-       pei_data->usb2_ports[port].enable   = enable;
-       pei_data->usb2_ports[port].oc_pin   = oc_pin;
-       pei_data->usb2_ports[port].location = location;
-}
-
-static inline void pei_data_usb3_port(struct pei_data *pei_data, int port,
-                                     uint8_t enable, uint8_t oc_pin,
-                                     uint8_t fixed_eq)
-{
-       pei_data->usb3_ports[port].enable   = enable;
-       pei_data->usb3_ports[port].oc_pin   = oc_pin;
-       pei_data->usb3_ports[port].fixed_eq = fixed_eq;
-}
-
-void mainboard_fill_pei_data(struct pei_data *pei_data)
-{
-       /* DQ byte map for Samus board */
-       const u8 dq_map[2][6][2] = {
-               { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 },
-                 { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } },
-               { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 },
-                 { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } } };
-       /* DQS CPU<>DRAM map for Samus board */
-       const u8 dqs_map[2][8] = {
-               { 2, 0, 1, 3, 6, 4, 7, 5 },
-               { 2, 1, 0, 3, 6, 5, 4, 7 } };
-
-       pei_data->ec_present = 1;
-
-       /* One installed DIMM per channel */
-       pei_data->dimm_channel0_disabled = 2;
-       pei_data->dimm_channel1_disabled = 2;
-
-       memcpy(pei_data->dq_map, dq_map, sizeof(dq_map));
-       memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map));
-
-       /* P0: HOST PORT */
-       pei_data_usb2_port(pei_data, 0, 0x0080, 1, 0,
-                          USB_PORT_BACK_PANEL);
-       /* P1: HOST PORT */
-       pei_data_usb2_port(pei_data, 1, 0x0080, 1, 1,
-                          USB_PORT_BACK_PANEL);
-       /* P2: RAIDEN */
-       pei_data_usb2_port(pei_data, 2, 0x0080, 1, USB_OC_PIN_SKIP,
-                          USB_PORT_BACK_PANEL);
-       /* P3: SD CARD */
-       pei_data_usb2_port(pei_data, 3, 0x0040, 1, USB_OC_PIN_SKIP,
-                          USB_PORT_INTERNAL);
-       /* P4: RAIDEN */
-       pei_data_usb2_port(pei_data, 4, 0x0080, 1, USB_OC_PIN_SKIP,
-                          USB_PORT_BACK_PANEL);
-       /* P5: WWAN (Disabled) */
-       pei_data_usb2_port(pei_data, 5, 0x0000, 0, USB_OC_PIN_SKIP,
-                          USB_PORT_SKIP);
-       /* P6: CAMERA */
-       pei_data_usb2_port(pei_data, 6, 0x0040, 1, USB_OC_PIN_SKIP,
-                          USB_PORT_INTERNAL);
-       /* P7: BT */
-       pei_data_usb2_port(pei_data, 7, 0x0040, 1, USB_OC_PIN_SKIP,
-                          USB_PORT_INTERNAL);
-
-       /* P1: HOST PORT */
-       pei_data_usb3_port(pei_data, 0, 1, 0, 0);
-       /* P2: HOST PORT */
-       pei_data_usb3_port(pei_data, 1, 1, 1, 0);
-       /* P3: RAIDEN */
-       pei_data_usb3_port(pei_data, 2, 1, USB_OC_PIN_SKIP, 0);
-       /* P4: RAIDEN */
-       pei_data_usb3_port(pei_data, 3, 1, USB_OC_PIN_SKIP, 0);
-}
-
 static unsigned long get_top_of_ram(struct udevice *dev)
 {
        /*
@@ -204,16 +111,18 @@ int dram_init(void)
 
        /* Print ME state before MRC */
        ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev);
-       if (ret)
+       if (ret) {
+               debug("Cannot get ME (err=%d)\n", ret);
                return ret;
+       }
        intel_me_status(me_dev);
 
        /* Save ME HSIO version */
-       ret = uclass_first_device(UCLASS_PCH, &pch_dev);
-       if (ret)
+       ret = uclass_first_device_err(UCLASS_PCH, &pch_dev);
+       if (ret) {
+               debug("Cannot get PCH (err=%d)\n", ret);
                return ret;
-       if (!pch_dev)
-               return -ENODEV;
+       }
        power_state_get(pch_dev, &ps);
 
        intel_me_hsio_version(me_dev, &ps.hsio_version, &ps.hsio_checksum);
@@ -221,15 +130,17 @@ int dram_init(void)
        broadwell_fill_pei_data(pei_data);
        mainboard_fill_pei_data(pei_data);
 
-       ret = uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
-       if (ret)
+       ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
+       if (ret) {
+               debug("Cannot get Northbridge (err=%d)\n", ret);
                return ret;
-       if (!dev)
-               return -ENODEV;
+       }
        size = 256;
        ret = mrc_locate_spd(dev, size, &spd_data);
-       if (ret)
+       if (ret) {
+               debug("Cannot locate SPD (err=%d)\n", ret);
                return ret;
+       }
        memcpy(pei_data->spd_data[0][0], spd_data, size);
        memcpy(pei_data->spd_data[1][0], spd_data, size);
 
@@ -239,13 +150,17 @@ int dram_init(void)
 
        debug("PEI version %#x\n", pei_data->pei_version);
        ret = mrc_common_init(dev, pei_data, true);
-       if (ret)
+       if (ret) {
+               debug("mrc_common_init() failed(err=%d)\n", ret);
                return ret;
+       }
        debug("Memory init done\n");
 
        ret = sdram_find(dev);
-       if (ret)
+       if (ret) {
+               debug("sdram_find() failed (err=%d)\n", ret);
                return ret;
+       }
        gd->ram_size = gd->arch.meminfo.total_32bit_memory;
        debug("RAM size %llx\n", (unsigned long long)gd->ram_size);
 
@@ -279,17 +194,6 @@ int misc_init_r(void)
        return 0;
 }
 
-void board_debug_uart_init(void)
-{
-       struct udevice *bus = NULL;
-
-       /* com1 / com2 decode range */
-       pci_x86_write_config(bus, PCH_DEV_LPC, LPC_IO_DEC, 1 << 4, PCI_SIZE_16);
-
-       pci_x86_write_config(bus, PCH_DEV_LPC, LPC_EN, COMA_LPC_EN,
-                            PCI_SIZE_16);
-}
-
 static const struct udevice_id broadwell_syscon_ids[] = {
        { .compatible = "intel,me", .data = X86_SYSCON_ME },
        { }
index 3bde44e..90b546e 100644 (file)
@@ -309,21 +309,22 @@ u32 cpu_get_stepping(void)
        return gd->arch.x86_mask;
 }
 
-int x86_cpu_init_f(void)
+/* initialise FPU, reset EM, set MP and NE */
+static void setup_cpu_features(void)
 {
        const u32 em_rst = ~X86_CR0_EM;
        const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE;
 
-       if (ll_boot_init()) {
-               /* initialize FPU, reset EM, set MP and NE */
-               asm ("fninit\n" \
-               "movl %%cr0, %%eax\n" \
-               "andl %0, %%eax\n" \
-               "orl  %1, %%eax\n" \
-               "movl %%eax, %%cr0\n" \
-               : : "i" (em_rst), "i" (mp_ne_set) : "eax");
-       }
+       asm ("fninit\n" \
+       "movl %%cr0, %%eax\n" \
+       "andl %0, %%eax\n" \
+       "orl  %1, %%eax\n" \
+       "movl %%eax, %%cr0\n" \
+       : : "i" (em_rst), "i" (mp_ne_set) : "eax");
+}
 
+static void setup_identity(void)
+{
        /* identify CPU via cpuid and store the decoded info into gd->arch */
        if (has_cpuid()) {
                struct cpu_device_id cpu;
@@ -339,46 +340,70 @@ int x86_cpu_init_f(void)
 
                gd->arch.has_mtrr = has_mtrr();
        }
-       /* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
+}
+
+/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
+static void setup_pci_ram_top(void)
+{
        gd->pci_ram_top = 0x80000000U;
+}
+
+static void setup_mtrr(void)
+{
+       u64 mtrr_cap;
 
        /* Configure fixed range MTRRs for some legacy regions */
-       if (gd->arch.has_mtrr) {
-               u64 mtrr_cap;
-
-               mtrr_cap = native_read_msr(MTRR_CAP_MSR);
-               if (mtrr_cap & MTRR_CAP_FIX) {
-                       /* Mark the VGA RAM area as uncacheable */
-                       native_write_msr(MTRR_FIX_16K_A0000_MSR,
-                                        MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE),
-                                        MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
-
-                       /*
-                        * Mark the PCI ROM area as cacheable to improve ROM
-                        * execution performance.
-                        */
-                       native_write_msr(MTRR_FIX_4K_C0000_MSR,
-                                        MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
-                                        MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
-                       native_write_msr(MTRR_FIX_4K_C8000_MSR,
-                                        MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
-                                        MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
-                       native_write_msr(MTRR_FIX_4K_D0000_MSR,
-                                        MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
-                                        MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
-                       native_write_msr(MTRR_FIX_4K_D8000_MSR,
-                                        MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
-                                        MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
-
-                       /* Enable the fixed range MTRRs */
-                       msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
-               }
+       if (!gd->arch.has_mtrr)
+               return;
+
+       mtrr_cap = native_read_msr(MTRR_CAP_MSR);
+       if (mtrr_cap & MTRR_CAP_FIX) {
+               /* Mark the VGA RAM area as uncacheable */
+               native_write_msr(MTRR_FIX_16K_A0000_MSR,
+                                MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE),
+                                MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
+
+               /*
+                * Mark the PCI ROM area as cacheable to improve ROM
+                * execution performance.
+                */
+               native_write_msr(MTRR_FIX_4K_C0000_MSR,
+                                MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+                                MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+               native_write_msr(MTRR_FIX_4K_C8000_MSR,
+                                MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+                                MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+               native_write_msr(MTRR_FIX_4K_D0000_MSR,
+                                MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+                                MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+               native_write_msr(MTRR_FIX_4K_D8000_MSR,
+                                MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+                                MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+
+               /* Enable the fixed range MTRRs */
+               msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
        }
+}
+
+int x86_cpu_init_f(void)
+{
+       if (ll_boot_init())
+               setup_cpu_features();
+       setup_identity();
+       setup_mtrr();
+       setup_pci_ram_top();
 
-#ifdef CONFIG_I8254_TIMER
        /* Set up the i8254 timer if required */
-       i8254_init();
-#endif
+       if (IS_ENABLED(CONFIG_I8254_TIMER))
+               i8254_init();
+
+       return 0;
+}
+
+int x86_cpu_reinit_f(void)
+{
+       setup_identity();
+       setup_pci_ram_top();
 
        return 0;
 }
index bf798c2..07f27c2 100644 (file)
@@ -3,14 +3,23 @@
 # Copyright (c) 2016 Google, Inc
 
 ifdef CONFIG_HAVE_MRC
-obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += car.o
-obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += me_status.o
-obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += report_platform.o
-obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += mrc.o
+obj-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += car.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += me_status.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o
 endif
 obj-y += cpu.o
 obj-y += lpc.o
 ifndef CONFIG_TARGET_EFI_APP
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o
+ifndef CONFIG_$(SPL_)X86_64
 obj-y += microcode.o
 endif
+endif
 obj-y += pch.o
+
+ifdef CONFIG_SPL
+ifndef CONFIG_SPL_BUILD
+obj-y += cpu_from_spl.o
+endif
+endif
index 52a77bb..00308db 100644 (file)
@@ -235,7 +235,7 @@ mtrr_table_end:
 
        .align 4
 _dt_ucode_base_size:
-       /* These next two fields are filled in by ifdtool */
+       /* These next two fields are filled in by binman */
 .globl ucode_base
 ucode_base:    /* Declared in microcode.h */
        .long   0                       /* microcode base */
diff --git a/arch/x86/cpu/intel_common/cpu_from_spl.c b/arch/x86/cpu/intel_common/cpu_from_spl.c
new file mode 100644 (file)
index 0000000..a6233c7
--- /dev/null
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/cpu_common.h>
+#include <asm/intel_regs.h>
+#include <asm/lapic.h>
+#include <asm/lpc_common.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/post.h>
+#include <asm/microcode.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int arch_cpu_init(void)
+{
+       int ret;
+
+       ret = x86_cpu_reinit_f();
+
+       return ret;
+}
index ed9bce6..1cb6cec 100644 (file)
@@ -229,6 +229,21 @@ static int bd82x6x_ioctl(struct udevice *dev, enum pch_req_t req, void *data,
                        return -ENOENT;
 
                return val & RCBA_AUDIO_CONFIG_MASK;
+       case PCH_REQ_PMBASE_INFO: {
+               struct pch_pmbase_info *pm = data;
+               int ret;
+
+               /* Find the base address of the powermanagement registers */
+               ret = dm_pci_read_config16(dev, 0x40, &pm->base);
+               if (ret)
+                       return ret;
+               pm->base &= 0xfffe;
+               pm->gpio0_en_ofs = GPE0_EN;
+               pm->pm1_sts_ofs = PM1_STS;
+               pm->pm1_cnt_ofs = PM1_CNT;
+
+               return 0;
+       }
        default:
                return -ENOSYS;
        }
index ea64c2e..fefbf8f 100644 (file)
@@ -322,7 +322,7 @@ static int start_aps(int ap_count, atomic_t *num_aps)
        if (sipi_vector > max_vector_loc) {
                printf("SIPI vector too large! 0x%08x\n",
                       sipi_vector);
-               return -1;
+               return -ENOSPC;
        }
 
        debug("Attempting to start %d APs\n", ap_count);
@@ -364,7 +364,7 @@ static int start_aps(int ap_count, atomic_t *num_aps)
        if (wait_for_aps(num_aps, ap_count, 10000, 50)) {
                debug("Not all APs checked in: %d/%d\n",
                      atomic_read(num_aps), ap_count);
-               return -1;
+               return -EIO;
        }
 
        return 0;
@@ -387,7 +387,7 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params)
                        if (wait_for_aps(&rec->cpus_entered, num_aps,
                                         timeout_us, step_us)) {
                                debug("MP record %d timeout\n", i);
-                               ret = -1;
+                               ret = -ETIMEDOUT;
                        }
                }
 
@@ -508,7 +508,7 @@ int mp_init(struct mp_params *p)
 
        if (p == NULL || p->flight_plan == NULL || p->num_records < 1) {
                printf("Invalid MP parameters\n");
-               return -1;
+               return -EINVAL;
        }
 
        num_cpus = cpu_get_count(cpu);
@@ -531,7 +531,7 @@ int mp_init(struct mp_params *p)
        /* Load the SIPI vector */
        ret = load_sipi_vector(&ap_count, num_cpus);
        if (ap_count == NULL)
-               return -1;
+               return -ENOENT;
 
        /*
         * Make sure SIPI data hits RAM so the APs that come up will see
index 30fa7de..4a82add 100644 (file)
@@ -190,6 +190,19 @@ board_init_f_r_trampoline:
        /* Re-enter U-Boot by calling board_init_f_r() */
        call    board_init_f_r
 
+#ifdef CONFIG_TPL
+.globl jump_to_spl
+.type jump_to_spl, @function
+jump_to_spl:
+       /* Reset stack to the top of CAR space */
+       movl    $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp
+#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
+       subl    $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp
+#endif
+
+       jmp     *%eax
+#endif
+
 die:
        hlt
        jmp     die
index a78a331..7be8347 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * 64-bit x86 Startup Code
  *
- * (C) Copyright 216 Google, Inc
+ * Copyright 2019 Google, Inc
  * Written by Simon Glass <sjg@chromium.org>
  */
 
diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S
new file mode 100644 (file)
index 0000000..4d4e5d0
--- /dev/null
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * 32-bit x86 Startup Code when running from SPL
+ *
+ * Copyright 2018 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <config.h>
+
+.section .text.start
+.code32
+.globl _start
+.type _start, @function
+_start:
+       /* Set up memory using the existing stack */
+       movl    $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %eax
+#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
+       subl    $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %eax
+#endif
+       /*
+        * We don't subject CONFIG_DCACHE_RAM_MRC_VAR_SIZE since memory is
+        * already set up. This has the happy side-effect of putting gd in a
+        * new place separate from SPL, so the memset() in
+        * board_init_f_init_reserve() does not cause any problems (otherwise
+        * it would zero out the gd and crash)
+        */
+       call    board_init_f_alloc_reserve
+       mov     %eax, %esp
+
+       call    board_init_f_init_reserve
+
+       xorl    %eax, %eax
+       call    board_init_f
+       call    board_init_f_r
+
+       /* Should not return here */
+       jmp     .
+
+.globl board_init_f_r_trampoline
+.type board_init_f_r_trampoline, @function
+board_init_f_r_trampoline:
+       /*
+        * SPL has been executed and SDRAM has been initialised, U-Boot code
+        * has been copied into RAM, BSS has been cleared and relocation
+        * adjustments have been made. It is now time to jump into the in-RAM
+        * copy of U-Boot
+        *
+        * %eax = Address of top of new stack
+        */
+
+       /* Stack grows down from top of SDRAM */
+       movl    %eax, %esp
+
+       /* Re-enter U-Boot by calling board_init_f_r() */
+       call    board_init_f_r
+
+die:
+       hlt
+       jmp     die
+       hlt
+
+       .align 4
+_dt_ucode_base_size:
+       /* These next two fields are filled in by binman */
+.globl ucode_base
+ucode_base:    /* Declared in microcode.h */
+       .long   0                       /* microcode base */
+.globl ucode_size
+ucode_size:    /* Declared in microcode.h */
+       .long   0                       /* microcode size */
diff --git a/arch/x86/cpu/start_from_tpl.S b/arch/x86/cpu/start_from_tpl.S
new file mode 100644 (file)
index 0000000..44b5363
--- /dev/null
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * 32-bit x86 Startup Code when running from TPL
+ *
+ * Copyright 2018 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <config.h>
+
+.section .text.start
+.code32
+.globl _start
+.type _start, @function
+_start:
+       /* Set up memory using the existing stack */
+       mov     %esp, %eax
+       call    board_init_f_alloc_reserve
+       mov     %eax, %esp
+
+       call    board_init_f_init_reserve
+
+       xorl    %eax, %eax
+       call    board_init_f
+       call    board_init_f_r
+
+       /* Should not return here */
+       jmp     .
+
+.globl board_init_f_r_trampoline
+.type board_init_f_r_trampoline, @function
+board_init_f_r_trampoline:
+       /*
+        * TPL has been executed: SDRAM has been initialised, BSS has been
+        * cleared.
+        *
+        * %eax = Address of top of new stack
+        */
+
+       /* Stack grows down from top of SDRAM */
+       movl    %eax, %esp
+
+       /* Re-enter SPL by calling board_init_f_r() */
+       call    board_init_f_r
+
+die:
+       hlt
+       jmp     die
+       hlt
index 4e656dc..f20c0b8 100644 (file)
@@ -54,7 +54,7 @@ SECTIONS
        /DISCARD/ : { *(.interp*) }
        /DISCARD/ : { *(.gnu*) }
 
-#ifdef CONFIG_SPL_X86_16BIT_INIT
+#if defined(CONFIG_SPL_X86_16BIT_INIT) || defined(CONFIG_TPL_X86_16BIT_INIT)
        /*
         * The following expressions place the 16-bit Real-Mode code and
         * Reset Vector at the end of the Flash ROM
index 6c063e8..42abb23 100644 (file)
@@ -61,3 +61,8 @@ int print_cpuinfo(void)
 {
        return 0;
 }
+
+int x86_cpu_reinit_f(void)
+{
+       return 0;
+}
index 35211ed..772ea5c 100644 (file)
@@ -9,6 +9,12 @@
 /include/ "rtc.dtsi"
 /include/ "tsc_timer.dtsi"
 
+#ifdef CONFIG_CHROMEOS
+#include "chromeos-x86.dtsi"
+#include "flashmap-x86-ro.dtsi"
+#include "flashmap-8mb-rw.dtsi"
+#endif
+
 / {
        model = "Google Samus";
        compatible = "google,samus", "intel,broadwell";
@@ -17,6 +23,7 @@
                spi0 = &spi;
                usb0 = &usb_0;
                usb1 = &usb_1;
+               cros-ec0 = &cros_ec;
        };
 
        config {
@@ -73,6 +80,7 @@
 
                /* Put this first: it is the default */
                gpio_unused: gpio-unused {
+                       u-boot,dm-pre-reloc;
                        mode-gpio;
                        direction = <PIN_INPUT>;
                        owner = <OWNER_GPIO>;
@@ -80,6 +88,7 @@
                };
 
                gpio_acpi_sci: acpi-sci {
+                       u-boot,dm-pre-reloc;
                        mode-gpio;
                        direction = <PIN_INPUT>;
                        invert;
@@ -87,6 +96,7 @@
                };
 
                gpio_acpi_smi: acpi-smi {
+                       u-boot,dm-pre-reloc;
                        mode-gpio;
                        direction = <PIN_INPUT>;
                        invert;
                };
 
                gpio_input: gpio-input {
+                       u-boot,dm-pre-reloc;
                        mode-gpio;
                        direction = <PIN_INPUT>;
                        owner = <OWNER_GPIO>;
                };
 
                gpio_input_invert: gpio-input-invert {
+                       u-boot,dm-pre-reloc;
                        mode-gpio;
                        direction = <PIN_INPUT>;
                        owner = <OWNER_GPIO>;
                };
 
                gpio_native: gpio-native {
+                       u-boot,dm-pre-reloc;
                };
 
                gpio_out_high: gpio-out-high {
+                       u-boot,dm-pre-reloc;
                        mode-gpio;
                        direction = <PIN_OUTPUT>;
                        output-value = <1>;
                };
 
                gpio_out_low: gpio-out-low {
+                       u-boot,dm-pre-reloc;
                        mode-gpio;
                        direction = <PIN_OUTPUT>;
                        output-value = <0>;
                };
 
                gpio_pirq: gpio-pirq {
+                       u-boot,dm-pre-reloc;
                        mode-gpio;
                        direction = <PIN_INPUT>;
                        owner = <OWNER_GPIO>;
                };
 
                soc_gpio@0 {
+                       u-boot,dm-pre-reloc;
                        config =
                                <0 &gpio_unused 0>,     /* unused */
                                <1 &gpio_unused 0>,     /* unused */
                        spd {
                                #address-cells = <1>;
                                #size-cells = <0>;
+                               u-boot,dm-pre-reloc;
                                samsung_4 {
                                        reg = <6>;
+                                       u-boot,dm-pre-reloc;
                                        data = [91 20 f1 03 04 11 05 0b
                                                03 11 01 08 0a 00 50 01
                                                78 78 90 50 90 11 50 e0
                                         * columns 10, density 4096 mb, x32
                                         */
                                        reg = <8>;
+                                       u-boot,dm-pre-reloc;
                                        data = [91 20 f1 03 04 11 05 0b
                                                03 11 01 08 0a 00 50 01
                                                78 78 90 50 90 11 50 e0
                                        };
                                samsung_8 {
                                        reg = <10>;
+                                       u-boot,dm-pre-reloc;
                                        data = [91 20 f1 03 04 12 05 0a
                                                03 11 01 08 0a 00 50 01
                                                78 78 90 50 90 11 50 e0
                                         * columns 11, density 4096 mb, x16
                                         */
                                        reg = <12>;
+                                       u-boot,dm-pre-reloc;
                                        data = [91 20 f1 03 04 12 05 0a
                                                03 11 01 08 0a 00 50 01
                                                78 78 90 50 90 11 50 e0
                                         * columns 11, density 8192 mb, x16
                                         */
                                        reg = <13>;
+                                       u-boot,dm-pre-reloc;
                                        data = [91 20 f1 03 05 1a 05 0a
                                                03 11 01 08 0a 00 50 01
                                                78 78 90 50 90 11 50 e0
                                         * columns 11, density 8192 mb, x16
                                         */
                                        reg = <15>;
+                                       u-boot,dm-pre-reloc;
                                        data = [91 20 f1 03 05 1a 05 0a
                                                03 11 01 08 0a 00 50 01
                                                78 78 90 50 90 11 50 e0
                        compatible = "ehci-pci";
                };
 
-               pch@1f,0 {
+               pch: pch@1f,0 {
                        reg = <0x0000f800 0 0 0 0>;
                        compatible = "intel,broadwell-pch";
                        u-boot,dm-pre-reloc;
                        power-enable-gpio = <&gpio_a 23 0>;
 
                        spi: spi {
+                               u-boot,dm-pre-reloc;
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "intel,ich9-spi";
-                               spi-flash@0 {
+                               fwstore_spi: spi-flash@0 {
+                                       u-boot,dm-pre-reloc;
                                        #size-cells = <1>;
                                        #address-cells = <1>;
                                        reg = <0>;
                                                        "jedec,spi-nor";
                                        memory-map = <0xff800000 0x00800000>;
                                        rw-mrc-cache {
+                                               u-boot,dm-pre-reloc;
                                                label = "rw-mrc-cache";
                                                reg = <0x003e0000 0x00010000>;
                                        };
                                #size-cells = <0>;
                                u-boot,dm-pre-reloc;
                                intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
-                               cros-ec@200 {
+                               cros_ec: cros-ec {
+                                       u-boot,dm-pre-reloc;
                                        compatible = "google,cros-ec-lpc";
                                        reg = <0x204 1 0x200 1 0x880 0x80>;
 
                sata@1f,2 {
                        compatible = "intel,wildcatpoint-ahci";
                        reg = <0x0000fa00 0 0 0 0>;
-                       u-boot,dm-pre-reloc;
+                       u-boot,dm-pre-proper;
                        intel,sata-mode = "ahci";
                        intel,sata-port-map = <1>;
                        intel,sata-port0-gen3-tx = <0x72>;
        };
 
        tpm {
+               u-boot,dm-pre-reloc;
                reg = <0xfed40000 0x5000>;
                compatible = "infineon,slb9635lpc";
+               secdata {
+                       u-boot,dm-pre-reloc;
+                       compatible = "google,tpm-secdata";
+               };
        };
 
        microcode {
+               u-boot,dm-pre-reloc;
                update@0 {
+                       u-boot,dm-pre-reloc;
 #include "microcode/mc0306d4_00000018.dtsi"
                };
        };
        };
 
 };
+
+&rtc {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       nvdata {
+               u-boot,dm-pre-reloc;
+               compatible = "google,cmos-nvdata";
+               reg = <0x26>;
+       };
+};
index f979d83..555d0dd 100644 (file)
@@ -1,5 +1,5 @@
 / {
-       reset {
+       reset: reset {
                compatible = "x86,reset";
                u-boot,dm-pre-reloc;
        };
index 1797e04..d0bbd84 100644 (file)
@@ -1,5 +1,5 @@
 / {
-       rtc {
+       rtc: rtc {
                compatible = "motorola,mc146818";
                u-boot,dm-pre-reloc;
                reg = <0x70 2>;
index 1050236..daeb168 100644 (file)
 
 #include <config.h>
 
-#ifdef CONFIG_ROM_SIZE
+#ifdef CONFIG_CHROMEOS
 / {
        binman {
-               filename = "u-boot.rom";
-               end-at-4gb;
-               sort-by-offset;
-               pad-byte = <0xff>;
-               size = <CONFIG_ROM_SIZE>;
-#ifdef CONFIG_HAVE_INTEL_ME
-               intel-descriptor {
-                       filename = CONFIG_FLASH_DESCRIPTOR_FILE;
-               };
-               intel-me {
-                       filename = CONFIG_INTEL_ME_FILE;
+               multiple-images;
+               rom: rom {
                };
+       };
+};
+#else
+/ {
+       rom: binman {
+       };
+};
 #endif
-#ifdef CONFIG_SPL
-               u-boot-spl-with-ucode-ptr {
-                       offset = <CONFIG_SPL_TEXT_BASE>;
-               };
 
-               u-boot-dtb-with-ucode2 {
-                       type = "u-boot-dtb-with-ucode";
-               };
-               u-boot {
-                       offset = <0xfff00000>;
-               };
+#ifdef CONFIG_ROM_SIZE
+&rom {
+       filename = "u-boot.rom";
+       end-at-4gb;
+       sort-by-offset;
+       pad-byte = <0xff>;
+       size = <CONFIG_ROM_SIZE>;
+#ifdef CONFIG_HAVE_INTEL_ME
+       intel-descriptor {
+               filename = CONFIG_FLASH_DESCRIPTOR_FILE;
+       };
+       intel-me {
+               filename = CONFIG_INTEL_ME_FILE;
+       };
+#endif
+#ifdef CONFIG_TPL
+       u-boot-tpl-with-ucode-ptr {
+               offset = <CONFIG_TPL_TEXT_BASE>;
+       };
+       u-boot-tpl-dtb {
+       };
+       u-boot-spl {
+               offset = <CONFIG_SPL_TEXT_BASE>;
+       };
+       u-boot-spl-dtb {
+       };
+       u-boot {
+               offset = <CONFIG_SYS_TEXT_BASE>;
+       };
+#elif defined(CONFIG_SPL)
+       u-boot-spl-with-ucode-ptr {
+               offset = <CONFIG_SPL_TEXT_BASE>;
+       };
+       u-boot-dtb-with-ucode2 {
+               type = "u-boot-dtb-with-ucode";
+       };
+       u-boot {
+               /*
+                * TODO(sjg@chromium.org):
+                * Normally we use CONFIG_SYS_TEXT_BASE as the flash offset. But
+                * for boards with textbase in SDRAM we cannot do this. Just use
+                * an assumed-valid value (1MB before the end of flash) here so
+                * that we can actually build an image for coreboot, etc.
+                * We need a better solution, perhaps a separate Kconfig.
+                */
+#if CONFIG_SYS_TEXT_BASE == 0x1110000
+               offset = <0xfff00000>;
 #else
-               u-boot-with-ucode-ptr {
-                       offset = <CONFIG_SYS_TEXT_BASE>;
-               };
+               offset = <CONFIG_SYS_TEXT_BASE>;
 #endif
-               u-boot-dtb-with-ucode {
-               };
-               u-boot-ucode {
-                       align = <16>;
-               };
+       };
+#else
+       u-boot-with-ucode-ptr {
+               offset = <CONFIG_SYS_TEXT_BASE>;
+       };
+#endif
+       u-boot-dtb-with-ucode {
+       };
+       u-boot-ucode {
+               align = <16>;
+       };
 #ifdef CONFIG_HAVE_MRC
-               intel-mrc {
-                       offset = <CONFIG_X86_MRC_ADDR>;
-               };
+       intel-mrc {
+               offset = <CONFIG_X86_MRC_ADDR>;
+       };
 #endif
 #ifdef CONFIG_HAVE_FSP
-               intel-fsp {
-                       filename = CONFIG_FSP_FILE;
-                       offset = <CONFIG_FSP_ADDR>;
-               };
+       intel-fsp {
+               filename = CONFIG_FSP_FILE;
+               offset = <CONFIG_FSP_ADDR>;
+       };
 #endif
 #ifdef CONFIG_HAVE_CMC
-               intel-cmc {
-                       filename = CONFIG_CMC_FILE;
-                       offset = <CONFIG_CMC_ADDR>;
-               };
+       intel-cmc {
+               filename = CONFIG_CMC_FILE;
+               offset = <CONFIG_CMC_ADDR>;
+       };
 #endif
 #ifdef CONFIG_HAVE_VGA_BIOS
-               intel-vga {
-                       filename = CONFIG_VGA_BIOS_FILE;
-                       offset = <CONFIG_VGA_BIOS_ADDR>;
-               };
+       intel-vga {
+               filename = CONFIG_VGA_BIOS_FILE;
+               offset = <CONFIG_VGA_BIOS_ADDR>;
+       };
 #endif
 #ifdef CONFIG_HAVE_VBT
-               intel-vbt {
-                       filename = CONFIG_VBT_FILE;
-                       offset = <CONFIG_VBT_ADDR>;
-               };
+       intel-vbt {
+               filename = CONFIG_VBT_FILE;
+               offset = <CONFIG_VBT_ADDR>;
+       };
 #endif
 #ifdef CONFIG_HAVE_REFCODE
-               intel-refcode {
-                       offset = <CONFIG_X86_REFCODE_ADDR>;
-               };
+       intel-refcode {
+               offset = <CONFIG_X86_REFCODE_ADDR>;
+       };
 #endif
-#ifdef CONFIG_SPL
-               x86-start16-spl {
-                       offset = <CONFIG_SYS_X86_START16>;
-               };
+#ifdef CONFIG_TPL
+       x86-start16-tpl {
+               offset = <CONFIG_SYS_X86_START16>;
+       };
+#elif defined(CONFIG_SPL)
+       x86-start16-spl {
+               offset = <CONFIG_SYS_X86_START16>;
+       };
 #else
-               x86-start16 {
-                       offset = <CONFIG_SYS_X86_START16>;
-               };
-#endif
+       x86-start16 {
+               offset = <CONFIG_SYS_X86_START16>;
        };
+#endif
 };
 #endif
diff --git a/arch/x86/include/asm/handoff.h b/arch/x86/include/asm/handoff.h
new file mode 100644 (file)
index 0000000..4d18d59
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Architecture-specific SPL handoff information for x86
+ *
+ * Copyright 2018 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __x86_asm_handoff_h
+#define __x86_asm_handoff_h
+
+struct arch_spl_handoff {
+};
+
+#endif
index 04783cd..40fda85 100644 (file)
@@ -103,4 +103,15 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry);
  */
 int mrccache_save(void);
 
+/**
+ * mrccache_spl_save() - Save to the MRC region from SPL
+ *
+ * When SPL is used to set up the memory controller we want to save the MRC
+ * data in SPL to avoid needing to pass it up to U-Boot proper to save. This
+ * function handles that.
+ *
+ * @return 0 if saved to SPI flash successfully, other error if failed
+ */
+int mrccache_spl_save(void);
+
 #endif /* _ASM_MRCCACHE_H */
index 8cf59d1..27432b2 100644 (file)
@@ -2,6 +2,19 @@
 /*
  * Copyright (C) 2017 Google, Inc
  * Written by Simon Glass <sjg@chromium.org>
- *
- * This file is required for SPL to build, but is empty.
  */
+
+#ifndef __asm_spl_h
+#define __asm_spl_h
+
+#define CONFIG_SPL_BOARD_LOAD_IMAGE
+
+enum {
+       BOOT_DEVICE_SPI         = 10,
+       BOOT_DEVICE_BOARD,
+       BOOT_DEVICE_CROS_VBOOT,
+};
+
+void jump_to_spl(ulong entry);
+
+#endif
index 670fcdc..c252192 100644 (file)
@@ -13,7 +13,27 @@ extern char gdt_rom[];
 
 /* cpu/.../cpu.c */
 int arch_cpu_init(void);
+
+/**
+ * x86_cpu_init_f() - Set up basic features of the x86 CPU
+ *
+ * 0 on success, -ve on error
+ */
 int x86_cpu_init_f(void);
+
+/**
+ * x86_cpu_reinit_f() - Set up the CPU a second time
+ *
+ * Once cpu_init_f() has been called (e.g. in SPL) we should not call it
+ * again (e.g. in U-Boot proper) since it sets up the state from scratch.
+ * Call this function in later phases of U-Boot instead. It reads the CPU
+ * identify so that CPU functions can be used correctly, but does not change
+ * anything.
+ *
+ * @return 0 (indicating success, to mimic cpu_init_f())
+ */
+int x86_cpu_reinit_f(void);
+
 int cpu_init_f(void);
 void setup_gdt(struct global_data *id, u64 *gdt_addr);
 /*
index 56fd680..436252d 100644 (file)
@@ -43,7 +43,14 @@ ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_CMD_ZBOOT)        += zimage.o
 endif
 obj-$(CONFIG_HAVE_FSP) += fsp/
-obj-$(CONFIG_SPL_BUILD) += spl.o
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_TPL_BUILD
+obj-y += tpl.o
+else
+obj-y += spl.o
+endif
+endif
 
 lib-$(CONFIG_USE_PRIVATE_LIBGCC) += div64.o
 
index 832b1f9..5443a86 100644 (file)
@@ -35,7 +35,7 @@ void bootm_announce_and_cleanup(void)
        timestamp_add_now(TS_U_BOOT_START_KERNEL);
 #endif
        bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
-#ifdef CONFIG_BOOTSTAGE_REPORT
+#if CONFIG_IS_ENABLED(BOOTSTAGE_REPORT)
        bootstage_report();
 #endif
 
index 48edc83..8c54cea 100644 (file)
@@ -100,7 +100,7 @@ temp_ram_init_romstack:
        .long   temp_ram_init_params
 temp_ram_init_params:
 _dt_ucode_base_size:
-       /* These next two fields are filled in by ifdtool */
+       /* These next two fields are filled in by binman */
 .globl ucode_base
 ucode_base:    /* Declared in microcode.h */
        .long   0                       /* microcode base */
index 0481f45..ac85278 100644 (file)
@@ -18,7 +18,10 @@ __weak ulong board_get_usable_ram_top(ulong total_size)
 
 int init_cache_f_r(void)
 {
-#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP)
+#if (CONFIG_IS_ENABLED(X86_32BIT_INIT) || \
+     (!defined(CONFIG_SPL_BUILD) && \
+      !CONFIG_IS_ENABLED(CONFIG_X86_RUN_64BIT))) && \
+    !defined(CONFIG_HAVE_FSP)
        int ret;
 
        ret = mtrr_commit(false);
index 2a89198..be10762 100644 (file)
@@ -113,8 +113,10 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
        ulong base_addr;
        int ret;
 
-       if (!is_mrc_cache(cur))
+       if (!is_mrc_cache(cur)) {
+               debug("%s: Cache data not valid\n", __func__);
                return -EINVAL;
+       }
 
        /* Find the last used block */
        base_addr = entry->base + entry->offset;
@@ -159,18 +161,11 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
        return 0;
 }
 
-int mrccache_reserve(void)
+static void mrccache_setup(void *data)
 {
-       struct mrc_data_container *cache;
+       struct mrc_data_container *cache = data;
        u16 checksum;
 
-       if (!gd->arch.mrc_output_len)
-               return 0;
-
-       /* adjust stack pointer to store pure cache data plus the header */
-       gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE);
-       cache = (struct mrc_data_container *)gd->start_addr_sp;
-
        cache->signature = MRC_DATA_SIGNATURE;
        cache->data_size = gd->arch.mrc_output_len;
        checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size);
@@ -182,6 +177,16 @@ int mrccache_reserve(void)
 
        /* gd->arch.mrc_output now points to the container */
        gd->arch.mrc_output = (char *)cache;
+}
+
+int mrccache_reserve(void)
+{
+       if (!gd->arch.mrc_output_len)
+               return 0;
+
+       /* adjust stack pointer to store pure cache data plus the header */
+       gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE);
+       mrccache_setup((void *)gd->start_addr_sp);
 
        gd->start_addr_sp &= ~0xf;
 
@@ -202,17 +207,23 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
                return -ENOENT;
        }
 
-       if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2))
+       if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2)) {
+               debug("%s: Cannot find memory map\n", __func__);
                return -EINVAL;
+       }
        entry->base = reg[0];
 
        /* Find the place where we put the MRC cache */
        mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache");
-       if (mrc_node < 0)
+       if (mrc_node < 0) {
+               debug("%s: Cannot find node\n", __func__);
                return -EPERM;
+       }
 
-       if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2))
+       if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2)) {
+               debug("%s: Cannot find address\n", __func__);
                return -EINVAL;
+       }
        entry->offset = reg[0];
        entry->length = reg[1];
 
@@ -256,3 +267,18 @@ err_entry:
                debug("%s: Failed: %d\n", __func__, ret);
        return ret;
 }
+
+int mrccache_spl_save(void)
+{
+       void *data;
+       int size;
+
+       size = gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE;
+       data = malloc(size);
+       if (!data)
+               return log_msg_ret("Allocate MRC cache block", -ENOMEM);
+       mrccache_setup(data);
+       gd->arch.mrc_output = data;
+
+       return mrccache_save();
+}
index 7d29074..5d5d1a9 100644 (file)
@@ -5,8 +5,10 @@
 
 #include <common.h>
 #include <debug_uart.h>
+#include <malloc.h>
 #include <spl.h>
 #include <asm/cpu.h>
+#include <asm/mrccache.h>
 #include <asm/mtrr.h>
 #include <asm/processor.h>
 #include <asm-generic/sections.h>
@@ -20,6 +22,7 @@ __weak int arch_cpu_init_dm(void)
 
 static int x86_spl_init(void)
 {
+#ifndef CONFIG_TPL
        /*
         * TODO(sjg@chromium.org): We use this area of RAM for the stack
         * and global_data in SPL. Once U-Boot starts up and releocates it
@@ -27,6 +30,7 @@ static int x86_spl_init(void)
         * place it immediately below CONFIG_SYS_TEXT_BASE.
         */
        char *ptr = (char *)0x110000;
+#endif
        int ret;
 
        debug("%s starting\n", __func__);
@@ -35,27 +39,44 @@ static int x86_spl_init(void)
                debug("%s: spl_init() failed\n", __func__);
                return ret;
        }
+#ifdef CONFIG_TPL
+       /* Do a mini-init if TPL has already done the full init */
+       ret = x86_cpu_reinit_f();
+#else
        ret = arch_cpu_init();
+#endif
        if (ret) {
                debug("%s: arch_cpu_init() failed\n", __func__);
                return ret;
        }
+#ifndef CONFIG_TPL
        ret = arch_cpu_init_dm();
        if (ret) {
                debug("%s: arch_cpu_init_dm() failed\n", __func__);
                return ret;
        }
+#endif
        preloader_console_init();
+#ifndef CONFIG_TPL
        ret = print_cpuinfo();
        if (ret) {
                debug("%s: print_cpuinfo() failed\n", __func__);
                return ret;
        }
+#endif
        ret = dram_init();
        if (ret) {
                debug("%s: dram_init() failed\n", __func__);
                return ret;
        }
+       if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) {
+               ret = mrccache_spl_save();
+               if (ret)
+                       debug("%s: Failed to write to mrccache (err=%d)\n",
+                             __func__, ret);
+       }
+
+#ifndef CONFIG_TPL
        memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start);
 
        /* TODO(sjg@chromium.org): Consider calling cpu_init_r() here */
@@ -80,9 +101,11 @@ static int x86_spl_init(void)
                               (1ULL << 32) - CONFIG_XIP_ROM_SIZE,
                               CONFIG_XIP_ROM_SIZE);
        if (ret) {
-               debug("%s: SPI cache setup failed\n", __func__);
+               debug("%s: SPI cache setup failed (err=%d)\n", __func__, ret);
                return ret;
        }
+       mtrr_commit(true);
+#endif
 
        return 0;
 }
@@ -96,9 +119,17 @@ void board_init_f(ulong flags)
                debug("Error %d\n", ret);
                hang();
        }
-
+#ifdef CONFIG_TPL
+       gd->bd = malloc(sizeof(*gd->bd));
+       if (!gd->bd) {
+               printf("Out of memory for bd_info size %x\n", sizeof(*gd->bd));
+               hang();
+       }
+       board_init_r(gd, 0);
+#else
        /* Uninit CAR and jump to board_init_f_r() */
        board_init_f_r_trampoline(gd->start_addr_sp);
+#endif
 }
 
 void board_init_f_r(void)
@@ -144,6 +175,7 @@ int spl_spi_load_image(void)
        return -EPERM;
 }
 
+#ifdef CONFIG_X86_RUN_64BIT
 void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
 {
        int ret;
@@ -154,3 +186,11 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
        while (1)
                ;
 }
+#endif
+
+void spl_board_init(void)
+{
+#ifndef CONFIG_TPL
+       preloader_console_init();
+#endif
+}
diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c
new file mode 100644 (file)
index 0000000..492a2d6
--- /dev/null
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Google, Inc
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <spl.h>
+#include <asm/cpu.h>
+#include <asm/mtrr.h>
+#include <asm/processor.h>
+#include <asm-generic/sections.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+__weak int arch_cpu_init_dm(void)
+{
+       return 0;
+}
+
+static int x86_tpl_init(void)
+{
+       int ret;
+
+       debug("%s starting\n", __func__);
+       ret = spl_init();
+       if (ret) {
+               debug("%s: spl_init() failed\n", __func__);
+               return ret;
+       }
+       ret = arch_cpu_init();
+       if (ret) {
+               debug("%s: arch_cpu_init() failed\n", __func__);
+               return ret;
+       }
+       ret = arch_cpu_init_dm();
+       if (ret) {
+               debug("%s: arch_cpu_init_dm() failed\n", __func__);
+               return ret;
+       }
+       preloader_console_init();
+       ret = print_cpuinfo();
+       if (ret) {
+               debug("%s: print_cpuinfo() failed\n", __func__);
+               return ret;
+       }
+
+       return 0;
+}
+
+void board_init_f(ulong flags)
+{
+       int ret;
+
+       ret = x86_tpl_init();
+       if (ret) {
+               debug("Error %d\n", ret);
+               hang();
+       }
+
+       /* Uninit CAR and jump to board_init_f_r() */
+       board_init_r(gd, 0);
+}
+
+void board_init_f_r(void)
+{
+       /* Not used since we never call board_init_f_r_trampoline() */
+       while (1);
+}
+
+u32 spl_boot_device(void)
+{
+       return IS_ENABLED(CONFIG_CHROMEOS) ? BOOT_DEVICE_CROS_VBOOT :
+               BOOT_DEVICE_BOARD;
+}
+
+int spl_start_uboot(void)
+{
+       return 0;
+}
+
+void spl_board_announce_boot_device(void)
+{
+       printf("SPI flash");
+}
+
+static int spl_board_load_image(struct spl_image_info *spl_image,
+                               struct spl_boot_device *bootdev)
+{
+       spl_image->size = CONFIG_SYS_MONITOR_LEN;  /* We don't know SPL size */
+       spl_image->entry_point = CONFIG_SPL_TEXT_BASE;
+       spl_image->load_addr = CONFIG_SPL_TEXT_BASE;
+       spl_image->os = IH_OS_U_BOOT;
+       spl_image->name = "U-Boot";
+
+       debug("Loading to %lx\n", spl_image->load_addr);
+
+       return 0;
+}
+SPL_LOAD_IMAGE_METHOD("SPI", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
+
+int spl_spi_load_image(void)
+{
+       return -EPERM;
+}
+
+void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
+{
+       printf("Jumping to U-Boot SPL at %lx\n", (ulong)spl_image->entry_point);
+       jump_to_spl(spl_image->entry_point);
+       while (1)
+               ;
+}
+
+void spl_board_init(void)
+{
+       preloader_console_init();
+}
index d98a5e8..679a0f1 100644 (file)
@@ -52,6 +52,14 @@ config TARGET_CHROMEBOOK_SAMUS
          Chrome OS EC connected on LPC, and it provides a 2560x1700 high
          resolution touch-enabled LCD display.
 
+config TARGET_CHROMEBOOK_SAMUS_TPL
+       bool "Chromebook samus booting from TPL"
+       help
+         This is a version of Samus which boots into TPL, then to SPL and
+         U-Boot proper. This is useful where verified boot must select
+         between different A/B versions of SPL/U-Boot, to allow upgrading of
+         almost all U-Boot code in the field.
+
 endchoice
 
 source "board/google/chromebook_link/Kconfig"
index afbfe53..90c23cb 100644 (file)
@@ -1,4 +1,4 @@
-if TARGET_CHROMEBOOK_SAMUS
+if TARGET_CHROMEBOOK_SAMUS || TARGET_CHROMEBOOK_SAMUS_TPL
 
 config SYS_BOARD
        default "chromebook_samus"
@@ -10,7 +10,8 @@ config SYS_SOC
        default "broadwell"
 
 config SYS_CONFIG_NAME
-       default "chromebook_samus"
+       default "chromebook_samus" if TARGET_CHROMEBOOK_SAMUS
+       default "chromebook_samus" if TARGET_CHROMEBOOK_SAMUS_TPL
 
 config SYS_TEXT_BASE
        default 0xffe00000
@@ -39,3 +40,12 @@ config SYS_CAR_SIZE
        default 0x40000
 
 endif
+
+if TARGET_CHROMEBOOK_SAMUS_TPL
+
+config BOARD_SPECIFIC_OPTIONS_TPL # dummy
+       def_bool y
+       select SPL
+       select TPL
+
+endif
index 5500e46..ca4b165 100644 (file)
@@ -4,3 +4,10 @@ S:     Maintained
 F:     board/google/chromebook_samus/
 F:     include/configs/chromebook_samus.h
 F:     configs/chromebook_samus_defconfig
+
+CHROMEBOOK SAMUS TPL BOARD
+M:     Simon Glass <sjg@chromium.org>
+S:     Maintained
+F:     board/google/chromebook_samus/
+F:     include/configs/chromebook_samus.h
+F:     configs/chromebook_samus_tpl_defconfig
index 338f374..bdd1854 100644 (file)
@@ -166,6 +166,12 @@ M: Jagan Teki <jagan@amarulasolutions.com>
 S:     Maintained
 F:     configs/bananapi_m64_defconfig
 
+BEELINK GS1
+M:     Clément Péron <peron.clem@gmail.com>
+S:     Maintained
+F:     configs/beelink_gs1_defconfig
+F:     arch/arm/dts/sun50i-h6-beelink-gs1.dts
+
 COLOMBUS BOARD
 M:     Maxime Ripard <maxime.ripard@bootlin.com>
 S:     Maintained
@@ -352,6 +358,12 @@ S: Maintained
 F:     configs/A20-Olimex-SOM204-EVB_defconfig
 F:     configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
 
+OLIMEX TERES-I BOARD
+M:     Jonas Smedegaard <dr@jones.dk>
+M:     Icenowy Zheng <icenowy@aosc.io>
+S:     Maintained
+F:     configs/teres_i_defconfig
+
 ORANGEPI LITE2 BOARD
 M:     Jagan Teki <jagan@amarulasolutions.com>
 S:     Maintained
index f1d7d8b..52116b3 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <common.h>
-#include <bootm.h>
 #include <charset.h>
 #include <command.h>
 #include <dm.h>
@@ -17,9 +16,7 @@
 #include <linux/libfdt_env.h>
 #include <mapmem.h>
 #include <memalign.h>
-#include <asm/global_data.h>
 #include <asm-generic/sections.h>
-#include <asm-generic/unaligned.h>
 #include <linux/linkage.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -28,15 +25,6 @@ static struct efi_device_path *bootefi_image_path;
 static struct efi_device_path *bootefi_device_path;
 
 /*
- * Allow unaligned memory access.
- *
- * This routine is overridden by architectures providing this feature.
- */
-void __weak allow_unaligned(void)
-{
-}
-
-/*
  * Set the load options of an image from an environment variable.
  *
  * @handle:    the image handle
@@ -338,11 +326,6 @@ static int do_efibootmgr(const char *fdt_opt)
        efi_handle_t handle;
        efi_status_t ret;
 
-       /* Allow unaligned memory access */
-       allow_unaligned();
-
-       switch_to_non_secure_mode();
-
        /* Initialize EFI drivers */
        ret = efi_init_obj_list();
        if (ret != EFI_SUCCESS) {
@@ -391,11 +374,6 @@ static int do_bootefi_image(const char *image_opt, const char *fdt_opt)
        efi_handle_t mem_handle = NULL, handle;
        efi_status_t ret;
 
-       /* Allow unaligned memory access */
-       allow_unaligned();
-
-       switch_to_non_secure_mode();
-
        /* Initialize EFI drivers */
        ret = efi_init_obj_list();
        if (ret != EFI_SUCCESS) {
@@ -582,11 +560,6 @@ static int do_efi_selftest(const char *fdt_opt)
        struct efi_loaded_image *loaded_image_info;
        efi_status_t ret;
 
-       /* Allow unaligned memory access */
-       allow_unaligned();
-
-       switch_to_non_secure_mode();
-
        /* Initialize EFI drivers */
        ret = efi_init_obj_list();
        if (ret != EFI_SUCCESS) {
index a45ca16..ef6a9d5 100644 (file)
@@ -21,6 +21,8 @@ CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-cubietruck-plus"
+CONFIG_PHY_REALTEK=y
+CONFIG_SUN8I_EMAC=y
 CONFIG_AXP_DLDO3_VOLT=2500
 CONFIG_AXP_DLDO4_VOLT=3300
 CONFIG_AXP_FLDO1_VOLT=1200
index b57e453..5174e28 100644 (file)
@@ -22,8 +22,10 @@ CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-bananapi-m3"
+CONFIG_PHY_REALTEK=y
+CONFIG_SUN8I_EMAC=y
 CONFIG_AXP_DCDC5_VOLT=1200
-CONFIG_AXP_DLDO3_VOLT=2500
+CONFIG_AXP_DLDO3_VOLT=3300
 CONFIG_AXP_SW_ON=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_OHCI_HCD=y
diff --git a/configs/beelink_gs1_defconfig b/configs/beelink_gs1_defconfig
new file mode 100644 (file)
index 0000000..ef4dd29
--- /dev/null
@@ -0,0 +1,15 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_SPL=y
+CONFIG_MACH_SUN50I_H6=y
+CONFIG_MMC0_CD_PIN="PF6"
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+# CONFIG_PSCI_RESET is not set
+CONFIG_NR_DRAM_BANKS=1
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-beelink-gs1"
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
index d0749f1..91d9fdf 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_X86=y
 CONFIG_SYS_TEXT_BASE=0xFFE00000
-CONFIG_SYS_MALLOC_F_LEN=0x1c00
+CONFIG_SYS_MALLOC_F_LEN=0x1d00
 CONFIG_NR_DRAM_BANKS=8
 CONFIG_DEBUG_UART_BOARD_INIT=y
 CONFIG_DEBUG_UART_BASE=0x3f8
diff --git a/configs/chromebook_samus_tpl_defconfig b/configs/chromebook_samus_tpl_defconfig
new file mode 100644 (file)
index 0000000..6ebfaa8
--- /dev/null
@@ -0,0 +1,82 @@
+CONFIG_X86=y
+CONFIG_SYS_TEXT_BASE=0xffed0000
+CONFIG_SYS_MALLOC_F_LEN=0x1a00
+CONFIG_NR_DRAM_BANKS=8
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_BASE=0x3f8
+CONFIG_DEBUG_UART_CLOCK=1843200
+CONFIG_VENDOR_GOOGLE=y
+CONFIG_TARGET_CHROMEBOOK_SAMUS_TPL=y
+CONFIG_DEBUG_UART=y
+CONFIG_HAVE_MRC=y
+CONFIG_HAVE_REFCODE=y
+CONFIG_SMP=y
+CONFIG_HAVE_VGA_BIOS=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro"
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_MISC_INIT_R=y
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_LAST_STAGE_INIT=y
+CONFIG_BLOBLIST=y
+CONFIG_BLOBLIST_SIZE=0x1000
+CONFIG_BLOBLIST_ADDR=0xff7c0000
+CONFIG_HANDOFF=y
+CONFIG_SPL_TEXT_BASE=0xffe70000
+CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SPL_NET_SUPPORT=y
+CONFIG_SPL_PCI=y
+CONFIG_SPL_PCH_SUPPORT=y
+CONFIG_TPL_PCI=y
+CONFIG_TPL_PCH_SUPPORT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CPU=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_SATA=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_CMD_SOUND=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_TPM_TEST=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_MAC_PARTITION=y
+# CONFIG_SPL_MAC_PARTITION is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+CONFIG_ISO_PARTITION=y
+CONFIG_EFI_PARTITION=y
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="chromebook_samus"
+# CONFIG_NET is not set
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CPU=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_DW=y
+CONFIG_TPL_MISC=y
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_LPC=y
+CONFIG_SYS_NS16550=y
+CONFIG_SOUND=y
+CONFIG_SOUND_I8254=y
+CONFIG_SOUND_RT5677=y
+CONFIG_SPI=y
+CONFIG_TPM_TIS_LPC=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
+CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
+CONFIG_CONSOLE_SCROLL_LINES=5
+CONFIG_TPM=y
diff --git a/configs/teres_i_defconfig b/configs/teres_i_defconfig
new file mode 100644 (file)
index 0000000..421a8d3
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_SPL=y
+CONFIG_MACH_SUN50I=y
+CONFIG_DRAM_CLK=552
+CONFIG_DRAM_ZQ=3881949
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_USB1_VBUS_PIN="PL7"
+CONFIG_I2C0_ENABLE=y
+# CONFIG_CMD_FLASH is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-teres-i"
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_SUNXI=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
+# CONFIG_USB_GADGET is not set
+CONFIG_VIDEO_BRIDGE=y
+CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345=y
index fa49cb8..8e0a3f3 100644 (file)
@@ -185,6 +185,22 @@ If you are using em100, then this command will flash write -Boot:
 
    em100 -s -d filename.rom -c W25Q64CV -r
 
+Flash map for samus / broadwell:
+
+   fffff800    SYS_X86_START16
+   ffff0000    RESET_SEG_START
+   fffd8000    TPL_TEXT_BASE
+   fffa0000    X86_MRC_ADDR
+   fff90000    VGA_BIOS_ADDR
+   ffed0000    SYS_TEXT_BASE
+   ffea0000    X86_REFCODE_ADDR
+   ffe70000    SPL_TEXT_BASE
+   ffbf8000    CONFIG_ENV_OFFSET (environemnt offset)
+   ffbe0000    rw-mrc-cache (Memory-reference-code cache)
+   ffa00000    <spare>
+   ff801000    intel-me (address set by descriptor.bin)
+   ff800000    intel-descriptor
+
 ---
 
 Intel Crown Bay specific instructions for bare mode:
index 844b87c..79b3b04 100644 (file)
@@ -54,28 +54,20 @@ static int clk_of_xlate_default(struct clk *clk,
        return 0;
 }
 
-static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
-                                  int index, struct clk *clk)
+static int clk_get_by_index_tail(int ret, ofnode node,
+                                struct ofnode_phandle_args *args,
+                                const char *list_name, int index,
+                                struct clk *clk)
 {
-       int ret;
-       struct ofnode_phandle_args args;
        struct udevice *dev_clk;
        const struct clk_ops *ops;
 
-       debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
-
        assert(clk);
        clk->dev = NULL;
+       if (ret)
+               goto err;
 
-       ret = dev_read_phandle_with_args(dev, prop_name, "#clock-cells", 0,
-                                        index, &args);
-       if (ret) {
-               debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
-                     __func__, ret);
-               return ret;
-       }
-
-       ret = uclass_get_device_by_ofnode(UCLASS_CLK, args.node, &dev_clk);
+       ret = uclass_get_device_by_ofnode(UCLASS_CLK, args->node, &dev_clk);
        if (ret) {
                debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
                      __func__, ret);
@@ -87,20 +79,67 @@ static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
        ops = clk_dev_ops(dev_clk);
 
        if (ops->of_xlate)
-               ret = ops->of_xlate(clk, &args);
+               ret = ops->of_xlate(clk, args);
        else
-               ret = clk_of_xlate_default(clk, &args);
+               ret = clk_of_xlate_default(clk, args);
        if (ret) {
                debug("of_xlate() failed: %d\n", ret);
                return ret;
        }
 
        return clk_request(dev_clk, clk);
+err:
+       debug("%s: Node '%s', property '%s', failed to request CLK index %d: %d\n",
+             __func__, ofnode_get_name(node), list_name, index, ret);
+       return ret;
+}
+
+static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
+                                  int index, struct clk *clk)
+{
+       int ret;
+       struct ofnode_phandle_args args;
+
+       debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
+
+       assert(clk);
+       clk->dev = NULL;
+
+       ret = dev_read_phandle_with_args(dev, prop_name, "#clock-cells", 0,
+                                        index, &args);
+       if (ret) {
+               debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+                     __func__, ret);
+               return ret;
+       }
+
+
+       return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
+                                    index > 0, clk);
 }
 
 int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
 {
-       return clk_get_by_indexed_prop(dev, "clocks", index, clk);
+       struct ofnode_phandle_args args;
+       int ret;
+
+       ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0,
+                                        index, &args);
+
+       return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
+                                    index > 0, clk);
+}
+
+int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk)
+{
+       struct ofnode_phandle_args args;
+       int ret;
+
+       ret = ofnode_parse_phandle_with_args(node, "clocks", "#clock-cells", 0,
+                                            index > 0, &args);
+
+       return clk_get_by_index_tail(ret, node, &args, "clocks",
+                                    index > 0, clk);
 }
 
 int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
index e1b5f8e..2d47ebc 100644 (file)
  * - SiFive FU540-C000 manual v1p0, Chapter 7 "Clocking and Reset"
  */
 
+#include <common.h>
 #include <asm/io.h>
 #include <clk-uclass.h>
 #include <clk.h>
-#include <common.h>
 #include <div64.h>
 #include <dm.h>
 #include <errno.h>
index 785f5c3..cc0c031 100644 (file)
@@ -546,7 +546,7 @@ fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
                ns = of_n_size_cells(np);
                *sizep = of_read_number(prop + na, ns);
 
-               if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0)
+               if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
                        return of_translate_address(np, prop);
                else
                        return of_read_number(prop, na);
index 565de04..382f826 100644 (file)
@@ -1482,7 +1482,7 @@ int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable)
 
 UCLASS_DRIVER(cros_ec) = {
        .id             = UCLASS_CROS_EC,
-       .name           = "cros_ec",
+       .name           = "cros-ec",
        .per_device_auto_alloc_size = sizeof(struct cros_ec_dev),
        .post_bind      = dm_scan_fdt_dev,
        .flags          = DM_UC_FLAG_ALLOC_PRIV_DMA,
index 98bd7a5..c0a4408 100644 (file)
@@ -138,7 +138,9 @@ struct emac_eth_dev {
        struct phy_device *phydev;
        struct mii_dev *bus;
        struct clk tx_clk;
+       struct clk ephy_clk;
        struct reset_ctl tx_rst;
+       struct reset_ctl ephy_rst;
 #ifdef CONFIG_DM_GPIO
        struct gpio_desc reset_gpio;
 #endif
@@ -653,7 +655,6 @@ static int sun8i_eth_write_hwaddr(struct udevice *dev)
 
 static int sun8i_emac_board_setup(struct emac_eth_dev *priv)
 {
-       struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
        int ret;
 
        ret = clk_enable(&priv->tx_clk);
@@ -670,16 +671,20 @@ static int sun8i_emac_board_setup(struct emac_eth_dev *priv)
                }
        }
 
-       if (priv->variant == H3_EMAC) {
-               /* Only H3/H5 have clock controls for internal EPHY */
-               if (priv->use_internal_phy) {
-                       /* Set clock gating for ephy */
-                       setbits_le32(&ccm->bus_gate4,
-                                    BIT(AHB_GATE_OFFSET_EPHY));
-
-                       /* Deassert EPHY */
-                       setbits_le32(&ccm->ahb_reset2_cfg,
-                                    BIT(AHB_RESET_OFFSET_EPHY));
+       /* Only H3/H5 have clock controls for internal EPHY */
+       if (clk_valid(&priv->ephy_clk)) {
+               ret = clk_enable(&priv->ephy_clk);
+               if (ret) {
+                       dev_err(dev, "failed to enable EPHY TX clock\n");
+                       return ret;
+               }
+       }
+
+       if (reset_valid(&priv->ephy_rst)) {
+               ret = reset_deassert(&priv->ephy_rst);
+               if (ret) {
+                       dev_err(dev, "failed to deassert EPHY TX clock\n");
+                       return ret;
                }
        }
 
@@ -839,6 +844,44 @@ static const struct eth_ops sun8i_emac_eth_ops = {
        .stop                   = sun8i_emac_eth_stop,
 };
 
+static int sun8i_get_ephy_nodes(struct emac_eth_dev *priv)
+{
+       int node, ret;
+
+       /* look for mdio-mux node for internal PHY node */
+       node = fdt_path_offset(gd->fdt_blob,
+                       "/soc/ethernet@1c30000/mdio-mux/mdio@1/ethernet-phy@1");
+       if (node < 0) {
+               debug("failed to get mdio-mux with internal PHY\n");
+               return node;
+       }
+
+       ret = fdt_node_check_compatible(gd->fdt_blob, node,
+                                       "allwinner,sun8i-h3-mdio-internal");
+       if (ret < 0) {
+               debug("failed to find mdio-internal node\n");
+               return ret;
+       }
+
+       ret = clk_get_by_index_nodev(offset_to_ofnode(node), 0,
+                                    &priv->ephy_clk);
+       if (ret) {
+               dev_err(dev, "failed to get EPHY TX clock\n");
+               return ret;
+       }
+
+       ret = reset_get_by_index_nodev(offset_to_ofnode(node), 0,
+                                      &priv->ephy_rst);
+       if (ret) {
+               dev_err(dev, "failed to get EPHY TX reset\n");
+               return ret;
+       }
+
+       priv->use_internal_phy = true;
+
+       return 0;
+}
+
 static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
 {
        struct sun8i_eth_pdata *sun8i_pdata = dev_get_platdata(dev);
@@ -920,12 +963,9 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
        }
 
        if (priv->variant == H3_EMAC) {
-               int parent = fdt_parent_offset(gd->fdt_blob, offset);
-
-               if (parent >= 0 &&
-                   !fdt_node_check_compatible(gd->fdt_blob, parent,
-                               "allwinner,sun8i-h3-mdio-internal"))
-                       priv->use_internal_phy = true;
+               ret = sun8i_get_ephy_nodes(priv);
+               if (ret)
+                       return ret;
        }
 
        priv->interface = pdata->phy_interface;
index 7d9b75c..2cede12 100644 (file)
@@ -306,7 +306,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void),
                        goto err;
 #endif
        } else {
-#if defined(CONFIG_X86) && CONFIG_IS_ENABLED(X86_32BIT_INIT)
+#if defined(CONFIG_X86) && (CONFIG_IS_ENABLED(X86_32BIT_INIT) || CONFIG_TPL)
                bios_set_interrupt_handler(0x15, int15_handler);
 
                bios_run_on_x86(dev, (unsigned long)ram, vesa_mode,
index 89e39c6..ee1a423 100644 (file)
@@ -29,41 +29,34 @@ static int reset_of_xlate_default(struct reset_ctl *reset_ctl,
        return 0;
 }
 
-int reset_get_by_index(struct udevice *dev, int index,
-                      struct reset_ctl *reset_ctl)
+static int reset_get_by_index_tail(int ret, ofnode node,
+                                  struct ofnode_phandle_args *args,
+                                  const char *list_name, int index,
+                                  struct reset_ctl *reset_ctl)
 {
-       struct ofnode_phandle_args args;
-       int ret;
        struct udevice *dev_reset;
        struct reset_ops *ops;
 
-       debug("%s(dev=%p, index=%d, reset_ctl=%p)\n", __func__, dev, index,
-             reset_ctl);
+       assert(reset_ctl);
        reset_ctl->dev = NULL;
-
-       ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0,
-                                         index, &args);
-       if (ret) {
-               debug("%s: fdtdec_parse_phandle_with_args() failed: %d\n",
-                     __func__, ret);
+       if (ret)
                return ret;
-       }
 
-       ret = uclass_get_device_by_ofnode(UCLASS_RESET, args.node,
+       ret = uclass_get_device_by_ofnode(UCLASS_RESET, args->node,
                                          &dev_reset);
        if (ret) {
                debug("%s: uclass_get_device_by_ofnode() failed: %d\n",
                      __func__, ret);
-               debug("%s %d\n", ofnode_get_name(args.node), args.args[0]);
+               debug("%s %d\n", ofnode_get_name(args->node), args->args[0]);
                return ret;
        }
        ops = reset_dev_ops(dev_reset);
 
        reset_ctl->dev = dev_reset;
        if (ops->of_xlate)
-               ret = ops->of_xlate(reset_ctl, &args);
+               ret = ops->of_xlate(reset_ctl, args);
        else
-               ret = reset_of_xlate_default(reset_ctl, &args);
+               ret = reset_of_xlate_default(reset_ctl, args);
        if (ret) {
                debug("of_xlate() failed: %d\n", ret);
                return ret;
@@ -78,6 +71,32 @@ int reset_get_by_index(struct udevice *dev, int index,
        return 0;
 }
 
+int reset_get_by_index(struct udevice *dev, int index,
+                      struct reset_ctl *reset_ctl)
+{
+       struct ofnode_phandle_args args;
+       int ret;
+
+       ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0,
+                                        index, &args);
+
+       return reset_get_by_index_tail(ret, dev_ofnode(dev), &args, "resets",
+                                      index > 0, reset_ctl);
+}
+
+int reset_get_by_index_nodev(ofnode node, int index,
+                            struct reset_ctl *reset_ctl)
+{
+       struct ofnode_phandle_args args;
+       int ret;
+
+       ret = ofnode_parse_phandle_with_args(node, "resets", "#reset-cells", 0,
+                                            index > 0, &args);
+
+       return reset_get_by_index_tail(ret, node, &args, "resets",
+                                      index > 0, reset_ctl);
+}
+
 int reset_get_bulk(struct udevice *dev, struct reset_ctl_bulk *bulk)
 {
        int i, ret, err, count;
index 537bc7a..fdfef69 100644 (file)
@@ -3,8 +3,8 @@
  * Copyright (C) 2018 Anup Patel <anup@brainfault.org>
  */
 
-#include <clk.h>
 #include <common.h>
+#include <clk.h>
 #include <debug_uart.h>
 #include <dm.h>
 #include <errno.h>
index af96c6d..e0cc323 100644 (file)
@@ -6,8 +6,8 @@
  * Author: Rick Chen (rick@andestech.com)
  */
 
-#include <clk.h>
 #include <common.h>
+#include <clk.h>
 #include <malloc.h>
 #include <spi.h>
 #include <asm/io.h>
index 009f376..072f794 100644 (file)
@@ -7,15 +7,75 @@
 
 #include <common.h>
 #include <dm.h>
+#include <efi_loader.h>
+#include <pch.h>
 #include <sysreset.h>
+#include <asm/acpi_s3.h>
 #include <asm/io.h>
 #include <asm/processor.h>
-#include <efi_loader.h>
 
-static __efi_runtime int x86_sysreset_request(struct udevice *dev,
-                                             enum sysreset_t type)
+struct x86_sysreset_platdata {
+       struct udevice *pch;
+};
+
+/*
+ * Power down the machine by using the power management sleep control
+ * of the chipset. This will currently only work on Intel chipsets.
+ * However, adapting it to new chipsets is fairly simple. You will
+ * have to find the IO address of the power management register block
+ * in your southbridge, and look up the appropriate SLP_TYP_S5 value
+ * from your southbridge's data sheet.
+ *
+ * This function never returns.
+ */
+int pch_sysreset_power_off(struct udevice *dev)
+{
+       struct x86_sysreset_platdata *plat = dev_get_platdata(dev);
+       struct pch_pmbase_info pm;
+       u32 reg32;
+       int ret;
+
+       if (!plat->pch)
+               return -ENOENT;
+       ret = pch_ioctl(plat->pch, PCH_REQ_PMBASE_INFO, &pm, sizeof(pm));
+       if (ret)
+               return ret;
+
+       /*
+        * Mask interrupts or system might stay in a coma, not executing code
+        * anymore, but not powered off either.
+        */
+       asm("cli");
+
+       /*
+        * Avoid any GPI waking the system from S5* or the system might stay in
+        * a coma
+        */
+       outl(0x00000000, pm.base + pm.gpio0_en_ofs);
+
+       /* Clear Power Button Status */
+       outw(PWRBTN_STS, pm.base + pm.pm1_sts_ofs);
+
+       /* PMBASE + 4, Bit 10-12, Sleeping Type, * set to 111 -> S5, soft_off */
+       reg32 = inl(pm.base + pm.pm1_cnt_ofs);
+
+       /* Set Sleeping Type to S5 (poweroff) */
+       reg32 &= ~(SLP_EN | SLP_TYP);
+       reg32 |= SLP_TYP_S5;
+       outl(reg32, pm.base + pm.pm1_cnt_ofs);
+
+       /* Now set the Sleep Enable bit */
+       reg32 |= SLP_EN;
+       outl(reg32, pm.base + pm.pm1_cnt_ofs);
+
+       for (;;)
+               asm("hlt");
+}
+
+static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type)
 {
        int value;
+       int ret;
 
        switch (type) {
        case SYSRESET_WARM:
@@ -24,6 +84,11 @@ static __efi_runtime int x86_sysreset_request(struct udevice *dev,
        case SYSRESET_COLD:
                value = SYS_RST | RST_CPU | FULL_RST;
                break;
+       case SYSRESET_POWER_OFF:
+               ret = pch_sysreset_power_off(dev);
+               if (ret)
+                       return ret;
+               return -EINPROGRESS;
        default:
                return -ENOSYS;
        }
@@ -33,17 +98,29 @@ static __efi_runtime int x86_sysreset_request(struct udevice *dev,
        return -EINPROGRESS;
 }
 
+static int x86_sysreset_get_last(struct udevice *dev)
+{
+       return SYSRESET_POWER;
+}
+
 #ifdef CONFIG_EFI_LOADER
 void __efi_runtime EFIAPI efi_reset_system(
                        enum efi_reset_type reset_type,
                        efi_status_t reset_status,
                        unsigned long data_size, void *reset_data)
 {
+       int value;
+
+       /*
+        * inline this code since we are not caused in the context of a
+        * udevice and passing NULL to x86_sysreset_request() is too horrible.
+        */
        if (reset_type == EFI_RESET_COLD ||
                 reset_type == EFI_RESET_PLATFORM_SPECIFIC)
-               x86_sysreset_request(NULL, SYSRESET_COLD);
-       else if (reset_type == EFI_RESET_WARM)
-               x86_sysreset_request(NULL, SYSRESET_WARM);
+               value = SYS_RST | RST_CPU | FULL_RST;
+       else /* assume EFI_RESET_WARM since we cannot return an error */
+               value = SYS_RST | RST_CPU;
+       outb(value, IO_PORT_RESET);
 
        /* TODO EFI_RESET_SHUTDOWN */
 
@@ -51,6 +128,15 @@ void __efi_runtime EFIAPI efi_reset_system(
 }
 #endif
 
+static int x86_sysreset_probe(struct udevice *dev)
+{
+       struct x86_sysreset_platdata *plat = dev_get_platdata(dev);
+
+       /* Locate the PCH if there is one. It isn't essential */
+       uclass_first_device(UCLASS_PCH, &plat->pch);
+
+       return 0;
+}
 
 static const struct udevice_id x86_sysreset_ids[] = {
        { .compatible = "x86,reset" },
@@ -59,6 +145,7 @@ static const struct udevice_id x86_sysreset_ids[] = {
 
 static struct sysreset_ops x86_sysreset_ops = {
        .request = x86_sysreset_request,
+       .get_last = x86_sysreset_get_last,
 };
 
 U_BOOT_DRIVER(x86_sysreset) = {
@@ -66,4 +153,6 @@ U_BOOT_DRIVER(x86_sysreset) = {
        .id = UCLASS_SYSRESET,
        .of_match = x86_sysreset_ids,
        .ops = &x86_sysreset_ops,
+       .probe = x86_sysreset_probe,
+       .platdata_auto_alloc_size       = sizeof(struct x86_sysreset_platdata),
 };
index 8e36616..d24e997 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef _CLK_H_
 #define _CLK_H_
 
+#include <dm/ofnode.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 
@@ -101,6 +102,20 @@ int clk_get_by_index_platdata(struct udevice *dev, int index,
 int clk_get_by_index(struct udevice *dev, int index, struct clk *clk);
 
 /**
+ * clock_get_by_index_nodev - Get/request a clock by integer index
+ * without a device.
+ *
+ * This is a version of clk_get_by_index() that does not use a device.
+ *
+ * @node:      The client ofnode.
+ * @index:     The index of the clock to request, within the client's list of
+ *             clocks.
+ * @clock      A pointer to a clock struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk);
+
+/**
  * clock_get_bulk - Get/request all clocks of a device.
  *
  * This looks up and requests all clocks of the client device; each device is
index ca59276..f26e463 100644 (file)
@@ -18,9 +18,6 @@
 #define CONFIG_ENV_SECT_SIZE           0x1000
 #define CONFIG_ENV_OFFSET              0x003f8000
 
-#define BOOT_DEVICE_SPI                        10
-
 #define CONFIG_SPL_BOARD_LOAD_IMAGE
-#define BOOT_DEVICE_BOARD              11
 
 #endif /* __CONFIG_H */
index ccb2fe8..2f7dd69 100644 (file)
@@ -23,4 +23,6 @@
 #define CONFIG_ENV_SECT_SIZE           0x1000
 #define CONFIG_ENV_OFFSET              0x003f8000
 
+#define CONFIG_TPL_TEXT_BASE           0xfffd8000
+
 #endif /* __CONFIG_H */
index 4cd1cac..64e7a60 100644 (file)
 #define CONFIG_SYS_ATA_IDE1_OFFSET     0x170
 #define CONFIG_ATAPI
 
-/* SPI is not supported */
-
-#define BOOT_DEVICE_SPI                        10
-
 #define CONFIG_SPL_BOARD_LOAD_IMAGE
-#define BOOT_DEVICE_BOARD              11
 
 #endif /* __CONFIG_H */
index accc21f..fceb812 100644 (file)
@@ -390,6 +390,18 @@ extern int soft_i2c_gpio_scl;
 #define BOOT_TARGET_DEVICES_USB(func)
 #endif
 
+#ifdef CONFIG_CMD_PXE
+#define BOOT_TARGET_DEVICES_PXE(func) func(PXE, pxe, na)
+#else
+#define BOOT_TARGET_DEVICES_PXE(func)
+#endif
+
+#ifdef CONFIG_CMD_DHCP
+#define BOOT_TARGET_DEVICES_DHCP(func) func(DHCP, dhcp, na)
+#else
+#define BOOT_TARGET_DEVICES_DHCP(func)
+#endif
+
 /* FEL boot support, auto-execute boot.scr if a script address was provided */
 #define BOOTENV_DEV_FEL(devtypeu, devtypel, instance) \
        "bootcmd_fel=" \
@@ -405,8 +417,8 @@ extern int soft_i2c_gpio_scl;
        BOOT_TARGET_DEVICES_MMC(func) \
        BOOT_TARGET_DEVICES_SCSI(func) \
        BOOT_TARGET_DEVICES_USB(func) \
-       func(PXE, pxe, na) \
-       func(DHCP, dhcp, na)
+       BOOT_TARGET_DEVICES_PXE(func) \
+       BOOT_TARGET_DEVICES_DHCP(func)
 
 #ifdef CONFIG_OLD_SUNXI_KERNEL_COMPAT
 #define BOOTCMD_SUNXI_COMPAT \
index 4180b25..7fcf76a 100644 (file)
@@ -36,7 +36,6 @@
 /*-----------------------------------------------------------------------
  * Real Time Clock Configuration
  */
-#define CONFIG_RTC_MC146818
 #define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0
 #define CONFIG_SYS_ISA_IO      CONFIG_SYS_ISA_IO_BASE_ADDRESS
 
index 472160c..755c405 100644 (file)
@@ -128,7 +128,8 @@ struct efi_boot_services {
                                    efi_status_t exit_status,
                                    efi_uintn_t exitdata_size, u16 *exitdata);
        efi_status_t (EFIAPI *unload_image)(efi_handle_t image_handle);
-       efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long);
+       efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t image_handle,
+                                                 efi_uintn_t map_key);
 
        efi_status_t (EFIAPI *get_next_monotonic_count)(u64 *count);
        efi_status_t (EFIAPI *stall)(unsigned long usecs);
@@ -348,7 +349,7 @@ struct efi_loaded_image {
        aligned_u64 image_size;
        unsigned int image_code_type;
        unsigned int image_data_type;
-       unsigned long unload;
+       efi_status_t (EFIAPI *unload)(efi_handle_t image_handle);
 };
 
 #define EFI_DEVICE_PATH_PROTOCOL_GUID \
index 7af3f16..07ef14b 100644 (file)
@@ -180,6 +180,19 @@ struct efi_handler {
 };
 
 /**
+ * enum efi_object_type - type of EFI object
+ *
+ * In UnloadImage we must be able to identify if the handle relates to a
+ * started image.
+ */
+enum efi_object_type {
+       EFI_OBJECT_TYPE_UNDEFINED = 0,
+       EFI_OBJECT_TYPE_U_BOOT_FIRMWARE,
+       EFI_OBJECT_TYPE_LOADED_IMAGE,
+       EFI_OBJECT_TYPE_STARTED_IMAGE,
+};
+
+/**
  * struct efi_object - dereferenced EFI handle
  *
  * @link:      pointers to put the handle into a linked list
@@ -201,6 +214,7 @@ struct efi_object {
        struct list_head link;
        /* The list of protocols */
        struct list_head protocols;
+       enum efi_object_type type;
 };
 
 /**
@@ -221,6 +235,7 @@ struct efi_loaded_image_obj {
        struct jmp_buf_data exit_jmp;
        EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
                                     struct efi_system_table *st);
+       u16 image_type;
 };
 
 /**
@@ -257,6 +272,25 @@ extern struct list_head efi_obj_list;
 /* List of all events */
 extern struct list_head efi_events;
 
+/**
+ * efi_register_notify_event - event registered by RegisterProtocolNotify()
+ *
+ * The address of this structure serves as registration value.
+ *
+ * @link:              link to list of all registered events
+ * @event:             registered event. The same event may registered for
+ *                     multiple GUIDs.
+ * @protocol:          protocol for which the event is registered
+ */
+struct efi_register_notify_event {
+       struct list_head link;
+       struct efi_event *event;
+       efi_guid_t protocol;
+};
+
+/* List of all events registered by RegisterProtocolNotify() */
+extern struct list_head efi_register_notify_events;
+
 /* Initialize efi execution environment */
 efi_status_t efi_init_obj_list(void);
 /* Called by bootefi to initialize root node */
index dd42e49..eaee188 100644 (file)
@@ -93,17 +93,6 @@ u16 *efi_st_translate_char(u16 code);
 u16 *efi_st_translate_code(u16 code);
 
 /*
- * Compare memory.
- * We cannot use lib/string.c due to different CFLAGS values.
- *
- * @buf1:      first buffer
- * @buf2:      second buffer
- * @length:    number of bytes to compare
- * @return:    0 if both buffers contain the same bytes
- */
-int efi_st_memcmp(const void *buf1, const void *buf2, size_t length);
-
-/*
  * Compare an u16 string to a char string.
  *
  * @buf1:      u16 string
index 046a5fd..0b44b66 100644 (file)
@@ -16,6 +16,9 @@ enum pch_req_t {
        /* Returns HDA config info if Azalia V1CTL enabled, -ENOENT if not */
        PCH_REQ_HDA_CONFIG,
 
+       /* Fills out a struct pch_pmbase_info if available */
+       PCH_REQ_PMBASE_INFO,
+
        PCH_REQ_TEST1,          /* Test requests for sandbox driver */
        PCH_REQ_TEST2,
        PCH_REQ_TEST3,
@@ -24,6 +27,21 @@ enum pch_req_t {
 };
 
 /**
+ * struct pch_pmbase_info - Information filled in by PCH_REQ_PMBASE_INFO
+ *
+ * @pmbase: IO address of power-management controller
+ * @gpio0_en_ofs: Offset of GPIO0 enable register
+ * @pm1_sts_ofs: Offset of status register
+ * @pm1_cnt_ofs: Offset of control register
+ */
+struct pch_pmbase_info {
+       u16 base;
+       u8 gpio0_en_ofs;
+       u8 pm1_sts_ofs;
+       u8 pm1_cnt_ofs;
+};
+
+/**
  * struct pch_ops - Operations for the Platform Controller Hub
  *
  * Consider using ioctl() to add rarely used or driver-specific operations.
index 066238a..508f7bc 100644 (file)
@@ -546,11 +546,7 @@ extern void pci_cfgfunc_do_nothing(struct pci_controller* hose, pci_dev_t dev,
 extern void pci_cfgfunc_config_device(struct pci_controller* hose, pci_dev_t dev,
                                      struct pci_config_table *);
 
-#ifdef CONFIG_NR_DRAM_BANKS
-#define MAX_PCI_REGIONS (CONFIG_NR_DRAM_BANKS + 7)
-#else
-#define MAX_PCI_REGIONS 7
-#endif
+#define MAX_PCI_REGIONS                7
 
 #define INDIRECT_TYPE_NO_PCIE_LINK     1
 
index a1a9ad5..4fac4e6 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef _RESET_H
 #define _RESET_H
 
+#include <dm/ofnode.h>
 #include <linux/errno.h>
 
 /**
@@ -103,6 +104,21 @@ int reset_get_by_index(struct udevice *dev, int index,
                       struct reset_ctl *reset_ctl);
 
 /**
+ * reset_get_by_index_nodev - Get/request a reset signal by integer index
+ * without a device.
+ *
+ * This is a version of reset_get_by_index() that does not use a device.
+ *
+ * @node:      The client ofnode.
+ * @index:     The index of the reset signal to request, within the client's
+ *             list of reset signals.
+ * @reset_ctl  A pointer to a reset control struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int reset_get_by_index_nodev(ofnode node, int index,
+                            struct reset_ctl *reset_ctl);
+
+/**
  * reset_get_bulk - Get/request all reset signals of a device.
  *
  * This looks up and requests all reset signals of the client device; each
index e5c46e9..b97d55c 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/libfdt_env.h>
 #include <u-boot/crc.h>
 #include <bootm.h>
+#include <pe.h>
 #include <watchdog.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -26,6 +27,9 @@ LIST_HEAD(efi_obj_list);
 /* List of all events */
 LIST_HEAD(efi_events);
 
+/* List of all events registered by RegisterProtocolNotify() */
+LIST_HEAD(efi_register_notify_events);
+
 /* Handle of the currently executing image */
 static efi_handle_t current_image;
 
@@ -238,7 +242,7 @@ void efi_signal_event(struct efi_event *event, bool check_tpl)
                        if (evt->is_queued)
                                efi_queue_event(evt, check_tpl);
                }
-       } else if (!event->is_signaled) {
+       } else {
                event->is_signaled = true;
                if (event->type & EVT_NOTIFY_SIGNAL)
                        efi_queue_event(event, check_tpl);
@@ -263,7 +267,7 @@ static unsigned long EFIAPI efi_raise_tpl(efi_uintn_t new_tpl)
        EFI_ENTRY("0x%zx", new_tpl);
 
        if (new_tpl < efi_tpl)
-               debug("WARNING: new_tpl < current_tpl in %s\n", __func__);
+               EFI_PRINT("WARNING: new_tpl < current_tpl in %s\n", __func__);
        efi_tpl = new_tpl;
        if (efi_tpl > TPL_HIGH_LEVEL)
                efi_tpl = TPL_HIGH_LEVEL;
@@ -286,7 +290,7 @@ static void EFIAPI efi_restore_tpl(efi_uintn_t old_tpl)
        EFI_ENTRY("0x%zx", old_tpl);
 
        if (old_tpl > efi_tpl)
-               debug("WARNING: old_tpl > current_tpl in %s\n", __func__);
+               EFI_PRINT("WARNING: old_tpl > current_tpl in %s\n", __func__);
        efi_tpl = old_tpl;
        if (efi_tpl > TPL_HIGH_LEVEL)
                efi_tpl = TPL_HIGH_LEVEL;
@@ -664,10 +668,26 @@ efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl,
                                        efi_guid_t *event_group,
                                        struct efi_event **event)
 {
+       efi_status_t ret;
+
        EFI_ENTRY("%d, 0x%zx, %p, %p, %pUl", type, notify_tpl, notify_function,
                  notify_context, event_group);
-       return EFI_EXIT(efi_create_event(type, notify_tpl, notify_function,
-                                        notify_context, event_group, event));
+
+       /*
+        * The allowable input parameters are the same as in CreateEvent()
+        * except for the following two disallowed event types.
+        */
+       switch (type) {
+       case EVT_SIGNAL_EXIT_BOOT_SERVICES:
+       case EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE:
+               ret = EFI_INVALID_PARAMETER;
+               goto out;
+       }
+
+       ret = efi_create_event(type, notify_tpl, notify_function,
+                              notify_context, event_group, event);
+out:
+       return EFI_EXIT(ret);
 }
 
 /**
@@ -891,9 +911,21 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event)
  */
 static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
 {
+       struct efi_register_notify_event *item, *next;
+
        EFI_ENTRY("%p", event);
        if (efi_is_event(event) != EFI_SUCCESS)
                return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+       /* Remove protocol notify registrations for the event */
+       list_for_each_entry_safe(item, next, &efi_register_notify_events,
+                                link) {
+               if (event == item->event) {
+                       list_del(&item->link);
+                       free(item);
+               }
+       }
+
        list_del(&event->link);
        free(event);
        return EFI_EXIT(EFI_SUCCESS);
@@ -939,11 +971,13 @@ struct efi_object *efi_search_obj(const efi_handle_t handle)
 {
        struct efi_object *efiobj;
 
+       if (!handle)
+               return NULL;
+
        list_for_each_entry(efiobj, &efi_obj_list, link) {
                if (efiobj == handle)
                        return efiobj;
        }
-
        return NULL;
 }
 
@@ -997,6 +1031,7 @@ efi_status_t efi_add_protocol(const efi_handle_t handle,
        struct efi_object *efiobj;
        struct efi_handler *handler;
        efi_status_t ret;
+       struct efi_register_notify_event *event;
 
        efiobj = efi_search_obj(handle);
        if (!efiobj)
@@ -1011,6 +1046,13 @@ efi_status_t efi_add_protocol(const efi_handle_t handle,
        handler->protocol_interface = protocol_interface;
        INIT_LIST_HEAD(&handler->open_infos);
        list_add_tail(&handler->link, &efiobj->protocols);
+
+       /* Notify registered events */
+       list_for_each_entry(event, &efi_register_notify_events, link) {
+               if (!guidcmp(protocol, &event->protocol))
+                       efi_signal_event(event->event, true);
+       }
+
        if (!guidcmp(&efi_guid_device_path, protocol))
                EFI_PRINT("installed device path '%pD'\n", protocol_interface);
        return EFI_SUCCESS;
@@ -1051,11 +1093,9 @@ static efi_status_t EFIAPI efi_install_protocol_interface(
                r = efi_create_handle(handle);
                if (r != EFI_SUCCESS)
                        goto out;
-               debug("%sEFI: new handle %p\n", indent_string(nesting_level),
-                     *handle);
+               EFI_PRINT("new handle %p\n", *handle);
        } else {
-               debug("%sEFI: handle %p\n", indent_string(nesting_level),
-                     *handle);
+               EFI_PRINT("handle %p\n", *handle);
        }
        /* Add new protocol */
        r = efi_add_protocol(*handle, protocol, protocol_interface);
@@ -1274,8 +1314,30 @@ static efi_status_t EFIAPI efi_register_protocol_notify(
                                                struct efi_event *event,
                                                void **registration)
 {
+       struct efi_register_notify_event *item;
+       efi_status_t ret = EFI_SUCCESS;
+
        EFI_ENTRY("%pUl, %p, %p", protocol, event, registration);
-       return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+       if (!protocol || !event || !registration) {
+               ret = EFI_INVALID_PARAMETER;
+               goto out;
+       }
+
+       item = calloc(1, sizeof(struct efi_register_notify_event));
+       if (!item) {
+               ret = EFI_OUT_OF_RESOURCES;
+               goto out;
+       }
+
+       item->event = event;
+       memcpy(&item->protocol, protocol, sizeof(efi_guid_t));
+
+       list_add_tail(&item->link, &efi_register_notify_events);
+
+       *registration = item;
+out:
+       return EFI_EXIT(ret);
 }
 
 /**
@@ -1290,8 +1352,7 @@ static efi_status_t EFIAPI efi_register_protocol_notify(
  * Return: 0 if the handle implements the protocol
  */
 static int efi_search(enum efi_locate_search_type search_type,
-                     const efi_guid_t *protocol, void *search_key,
-                     efi_handle_t handle)
+                     const efi_guid_t *protocol, efi_handle_t handle)
 {
        efi_status_t ret;
 
@@ -1299,8 +1360,6 @@ static int efi_search(enum efi_locate_search_type search_type,
        case ALL_HANDLES:
                return 0;
        case BY_REGISTER_NOTIFY:
-               /* TODO: RegisterProtocolNotify is not implemented yet */
-               return -1;
        case BY_PROTOCOL:
                ret = efi_search_protocol(handle, protocol, NULL);
                return (ret != EFI_SUCCESS);
@@ -1312,11 +1371,12 @@ static int efi_search(enum efi_locate_search_type search_type,
 
 /**
  * efi_locate_handle() - locate handles implementing a protocol
- * @search_type: selection criterion
- * @protocol:    GUID of the protocol
- * @search_key: registration key
- * @buffer_size: size of the buffer to receive the handles in bytes
- * @buffer:      buffer to receive the relevant handles
+ *
+ * @search_type:       selection criterion
+ * @protocol:          GUID of the protocol
+ * @search_key:                registration key
+ * @buffer_size:       size of the buffer to receive the handles in bytes
+ * @buffer:            buffer to receive the relevant handles
  *
  * This function is meant for U-Boot internal calls. For the API implementation
  * of the LocateHandle service see efi_locate_handle_ext.
@@ -1330,6 +1390,7 @@ static efi_status_t efi_locate_handle(
 {
        struct efi_object *efiobj;
        efi_uintn_t size = 0;
+       struct efi_register_notify_event *item, *event = NULL;
 
        /* Check parameters */
        switch (search_type) {
@@ -1338,8 +1399,19 @@ static efi_status_t efi_locate_handle(
        case BY_REGISTER_NOTIFY:
                if (!search_key)
                        return EFI_INVALID_PARAMETER;
-               /* RegisterProtocolNotify is not implemented yet */
-               return EFI_UNSUPPORTED;
+               /* Check that the registration key is valid */
+               list_for_each_entry(item, &efi_register_notify_events, link) {
+                       if (item ==
+                           (struct efi_register_notify_event *)search_key) {
+                               event = item;
+                               break;
+                       }
+               }
+               if (!event)
+                       return EFI_INVALID_PARAMETER;
+
+               protocol = &event->protocol;
+               break;
        case BY_PROTOCOL:
                if (!protocol)
                        return EFI_INVALID_PARAMETER;
@@ -1348,32 +1420,32 @@ static efi_status_t efi_locate_handle(
                return EFI_INVALID_PARAMETER;
        }
 
-       /*
-        * efi_locate_handle_buffer uses this function for
-        * the calculation of the necessary buffer size.
-        * So do not require a buffer for buffersize == 0.
-        */
-       if (!buffer_size || (*buffer_size && !buffer))
-               return EFI_INVALID_PARAMETER;
-
        /* Count how much space we need */
        list_for_each_entry(efiobj, &efi_obj_list, link) {
-               if (!efi_search(search_type, protocol, search_key, efiobj))
+               if (!efi_search(search_type, protocol, efiobj))
                        size += sizeof(void *);
        }
 
+       if (size == 0)
+               return EFI_NOT_FOUND;
+
+       if (!buffer_size)
+               return EFI_INVALID_PARAMETER;
+
        if (*buffer_size < size) {
                *buffer_size = size;
                return EFI_BUFFER_TOO_SMALL;
        }
 
        *buffer_size = size;
-       if (size == 0)
-               return EFI_NOT_FOUND;
+
+       /* The buffer size is sufficient but there is not buffer */
+       if (!buffer)
+               return EFI_INVALID_PARAMETER;
 
        /* Then fill the array */
        list_for_each_entry(efiobj, &efi_obj_list, link) {
-               if (!efi_search(search_type, protocol, search_key, efiobj))
+               if (!efi_search(search_type, protocol, efiobj))
                        *buffer++ = efiobj;
        }
 
@@ -1538,6 +1610,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
                free(info);
                return EFI_OUT_OF_RESOURCES;
        }
+       obj->header.type = EFI_OBJECT_TYPE_LOADED_IMAGE;
 
        /* Add internal object to object list */
        efi_add_handle(&obj->header);
@@ -1687,7 +1760,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy,
        EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
                  file_path, source_buffer, source_size, image_handle);
 
-       if (!image_handle || !parent_image) {
+       if (!image_handle || !efi_search_obj(parent_image)) {
                ret = EFI_INVALID_PARAMETER;
                goto error;
        }
@@ -1696,6 +1769,11 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy,
                ret = EFI_NOT_FOUND;
                goto error;
        }
+       /* The parent image handle must refer to a loaded image */
+       if (!parent_image->type) {
+               ret = EFI_INVALID_PARAMETER;
+               goto error;
+       }
 
        if (!source_buffer) {
                ret = efi_load_image_from_path(file_path, &dest_buffer,
@@ -1703,6 +1781,10 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy,
                if (ret != EFI_SUCCESS)
                        goto error;
        } else {
+               if (!source_size) {
+                       ret = EFI_LOAD_ERROR;
+                       goto error;
+               }
                dest_buffer = source_buffer;
        }
        /* split file_path which contains both the device and file parts */
@@ -1728,29 +1810,6 @@ error:
 }
 
 /**
- * efi_unload_image() - unload an EFI image
- * @image_handle: handle of the image to be unloaded
- *
- * This function implements the UnloadImage service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * Return: status code
- */
-efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
-{
-       struct efi_object *efiobj;
-
-       EFI_ENTRY("%p", image_handle);
-       efiobj = efi_search_obj(image_handle);
-       if (efiobj)
-               list_del(&efiobj->link);
-
-       return EFI_EXIT(EFI_SUCCESS);
-}
-
-/**
  * efi_exit_caches() - fix up caches for EFI payloads if necessary
  */
 static void efi_exit_caches(void)
@@ -1782,11 +1841,11 @@ static void efi_exit_caches(void)
  * Return: status code
  */
 static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
-                                                 unsigned long map_key)
+                                                 efi_uintn_t map_key)
 {
        struct efi_event *evt;
 
-       EFI_ENTRY("%p, %ld", image_handle, map_key);
+       EFI_ENTRY("%p, %zx", image_handle, map_key);
 
        /* Check that the caller has read the current memory map */
        if (map_key != efi_memory_map_key)
@@ -1932,7 +1991,8 @@ static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle,
        EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
                  controller_handle);
 
-       if (!agent_handle) {
+       if (!efi_search_obj(agent_handle) ||
+           (controller_handle && !efi_search_obj(controller_handle))) {
                r = EFI_INVALID_PARAMETER;
                goto out;
        }
@@ -2585,8 +2645,15 @@ static efi_status_t EFIAPI efi_open_protocol
        }
 
        r = efi_search_protocol(handle, protocol, &handler);
-       if (r != EFI_SUCCESS)
+       switch (r) {
+       case EFI_SUCCESS:
+               break;
+       case EFI_NOT_FOUND:
+               r = EFI_UNSUPPORTED;
+               goto out;
+       default:
                goto out;
+       }
 
        r = efi_protocol_open(handler, protocol_interface, agent_handle,
                              controller_handle, attributes);
@@ -2653,15 +2720,15 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
                 * missed out steps of EFI_CALL.
                 */
                assert(__efi_entry_check());
-               debug("%sEFI: %lu returned by started image\n",
-                     __efi_nesting_dec(),
-                     (unsigned long)((uintptr_t)image_obj->exit_status &
-                                     ~EFI_ERROR_MASK));
+               EFI_PRINT("%lu returned by started image\n",
+                         (unsigned long)((uintptr_t)image_obj->exit_status &
+                         ~EFI_ERROR_MASK));
                current_image = parent_image;
                return EFI_EXIT(image_obj->exit_status);
        }
 
        current_image = image_handle;
+       image_obj->header.type = EFI_OBJECT_TYPE_STARTED_IMAGE;
        EFI_PRINT("Jumping into 0x%p\n", image_obj->entry);
        ret = EFI_CALL(image_obj->entry(image_handle, &systab));
 
@@ -2675,6 +2742,76 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
 }
 
 /**
+ * efi_delete_image() - delete loaded image from memory)
+ *
+ * @image_obj:                 handle of the loaded image
+ * @loaded_image_protocol:     loaded image protocol
+ */
+static void efi_delete_image(struct efi_loaded_image_obj *image_obj,
+                            struct efi_loaded_image *loaded_image_protocol)
+{
+       efi_free_pages((uintptr_t)loaded_image_protocol->image_base,
+                      efi_size_in_pages(loaded_image_protocol->image_size));
+       efi_delete_handle(&image_obj->header);
+}
+
+/**
+ * efi_unload_image() - unload an EFI image
+ * @image_handle: handle of the image to be unloaded
+ *
+ * This function implements the UnloadImage service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
+{
+       efi_status_t ret = EFI_SUCCESS;
+       struct efi_object *efiobj;
+       struct efi_loaded_image *loaded_image_protocol;
+
+       EFI_ENTRY("%p", image_handle);
+
+       efiobj = efi_search_obj(image_handle);
+       if (!efiobj) {
+               ret = EFI_INVALID_PARAMETER;
+               goto out;
+       }
+       /* Find the loaded image protocol */
+       ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
+                                        (void **)&loaded_image_protocol,
+                                        NULL, NULL,
+                                        EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+       if (ret != EFI_SUCCESS) {
+               ret = EFI_INVALID_PARAMETER;
+               goto out;
+       }
+       switch (efiobj->type) {
+       case EFI_OBJECT_TYPE_STARTED_IMAGE:
+               /* Call the unload function */
+               if (!loaded_image_protocol->unload) {
+                       ret = EFI_UNSUPPORTED;
+                       goto out;
+               }
+               ret = EFI_CALL(loaded_image_protocol->unload(image_handle));
+               if (ret != EFI_SUCCESS)
+                       goto out;
+               break;
+       case EFI_OBJECT_TYPE_LOADED_IMAGE:
+               break;
+       default:
+               ret = EFI_INVALID_PARAMETER;
+               goto out;
+       }
+       efi_delete_image((struct efi_loaded_image_obj *)efiobj,
+                        loaded_image_protocol);
+out:
+       return EFI_EXIT(ret);
+}
+
+/**
  * efi_update_exit_data() - fill exit data parameters of StartImage()
  *
  * @image_obj          image handle
@@ -2733,7 +2870,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
         *       image protocol.
         */
        efi_status_t ret;
-       void *info;
+       struct efi_loaded_image *loaded_image_protocol;
        struct efi_loaded_image_obj *image_obj =
                (struct efi_loaded_image_obj *)image_handle;
 
@@ -2741,13 +2878,33 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
                  exit_data_size, exit_data);
 
        /* Check parameters */
-       if (image_handle != current_image)
-               goto out;
        ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
-                                        &info, NULL, NULL,
+                                        (void **)&loaded_image_protocol,
+                                        NULL, NULL,
                                         EFI_OPEN_PROTOCOL_GET_PROTOCOL));
-       if (ret != EFI_SUCCESS)
+       if (ret != EFI_SUCCESS) {
+               ret = EFI_INVALID_PARAMETER;
+               goto out;
+       }
+
+       /* Unloading of unstarted images */
+       switch (image_obj->header.type) {
+       case EFI_OBJECT_TYPE_STARTED_IMAGE:
+               break;
+       case EFI_OBJECT_TYPE_LOADED_IMAGE:
+               efi_delete_image(image_obj, loaded_image_protocol);
+               ret = EFI_SUCCESS;
+               goto out;
+       default:
+               /* Handle does not refer to loaded image */
+               ret = EFI_INVALID_PARAMETER;
+               goto out;
+       }
+       /* A started image can only be unloaded it is the last one started. */
+       if (image_handle != current_image) {
+               ret = EFI_INVALID_PARAMETER;
                goto out;
+       }
 
        /* Exit data is only foreseen in case of failure. */
        if (exit_status != EFI_SUCCESS) {
@@ -2757,6 +2914,9 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
                if (ret != EFI_SUCCESS)
                        EFI_PRINT("%s: out of memory\n", __func__);
        }
+       if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION ||
+           exit_status != EFI_SUCCESS)
+               efi_delete_image(image_obj, loaded_image_protocol);
 
        /* Make sure entry/exit counts for EFI world cross-overs match */
        EFI_EXIT(exit_status);
@@ -2772,7 +2932,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
 
        panic("EFI application exited");
 out:
-       return EFI_EXIT(EFI_INVALID_PARAMETER);
+       return EFI_EXIT(ret);
 }
 
 /**
index f8092b6..13541cf 100644 (file)
@@ -273,6 +273,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
                IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
                image_base = opt->ImageBase;
                efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
+               handle->image_type = opt->Subsystem;
                efi_reloc = efi_alloc(virt_size,
                                      loaded_image_info->image_code_type);
                if (!efi_reloc) {
@@ -288,6 +289,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
                IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
                image_base = opt->ImageBase;
                efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
+               handle->image_type = opt->Subsystem;
                efi_reloc = efi_alloc(virt_size,
                                      loaded_image_info->image_code_type);
                if (!efi_reloc) {
index e0fcbb8..38514e0 100644 (file)
@@ -28,6 +28,7 @@ struct efi_root_dp {
  */
 efi_status_t efi_root_node_register(void)
 {
+       efi_status_t ret;
        struct efi_root_dp *dp;
 
        /* Create device path protocol */
@@ -47,28 +48,31 @@ efi_status_t efi_root_node_register(void)
        dp->end.length = sizeof(struct efi_device_path);
 
        /* Create root node and install protocols */
-       return EFI_CALL(efi_install_multiple_protocol_interfaces(&efi_root,
-                      /* Device path protocol */
-                      &efi_guid_device_path, dp,
-                      /* Device path to text protocol */
-                      &efi_guid_device_path_to_text_protocol,
-                      (void *)&efi_device_path_to_text,
-                      /* Device path utilities protocol */
-                      &efi_guid_device_path_utilities_protocol,
-                      (void *)&efi_device_path_utilities,
-                      /* Unicode collation protocol */
-                      &efi_guid_unicode_collation_protocol,
-                      (void *)&efi_unicode_collation_protocol,
+       ret = EFI_CALL(efi_install_multiple_protocol_interfaces
+                       (&efi_root,
+                        /* Device path protocol */
+                        &efi_guid_device_path, dp,
+                        /* Device path to text protocol */
+                        &efi_guid_device_path_to_text_protocol,
+                        (void *)&efi_device_path_to_text,
+                        /* Device path utilities protocol */
+                        &efi_guid_device_path_utilities_protocol,
+                        (void *)&efi_device_path_utilities,
+                        /* Unicode collation protocol */
+                        &efi_guid_unicode_collation_protocol,
+                        (void *)&efi_unicode_collation_protocol,
 #if CONFIG_IS_ENABLED(EFI_LOADER_HII)
-                      /* HII string protocol */
-                      &efi_guid_hii_string_protocol,
-                      (void *)&efi_hii_string,
-                      /* HII database protocol */
-                      &efi_guid_hii_database_protocol,
-                      (void *)&efi_hii_database,
-                      /* HII configuration routing protocol */
-                      &efi_guid_hii_config_routing_protocol,
-                      (void *)&efi_hii_config_routing,
+                        /* HII string protocol */
+                        &efi_guid_hii_string_protocol,
+                        (void *)&efi_hii_string,
+                        /* HII database protocol */
+                        &efi_guid_hii_database_protocol,
+                        (void *)&efi_hii_database,
+                        /* HII configuration routing protocol */
+                        &efi_guid_hii_config_routing_protocol,
+                        (void *)&efi_hii_config_routing,
 #endif
-                      NULL));
+                        NULL));
+       efi_root->type = EFI_OBJECT_TYPE_U_BOOT_FIRMWARE;
+       return ret;
 }
index 87db51c..8691d68 100644 (file)
@@ -6,12 +6,22 @@
  */
 
 #include <common.h>
+#include <bootm.h>
 #include <efi_loader.h>
 
 #define OBJ_LIST_NOT_INITIALIZED 1
 
 static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
 
+/*
+ * Allow unaligned memory access.
+ *
+ * This routine is overridden by architectures providing this feature.
+ */
+void __weak allow_unaligned(void)
+{
+}
+
 /**
  * efi_init_platform_lang() - define supported languages
  *
@@ -86,6 +96,12 @@ efi_status_t efi_init_obj_list(void)
        if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED)
                return efi_obj_list_initialized;
 
+       /* Allow unaligned memory access */
+       allow_unaligned();
+
+       /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
+       switch_to_non_secure_mode();
+
        /* Define supported languages */
        ret = efi_init_platform_lang();
        if (ret != EFI_SUCCESS)
index 4945691..c69ad7a 100644 (file)
@@ -27,6 +27,7 @@ efi_selftest_gop.o \
 efi_selftest_loaded_image.o \
 efi_selftest_manageprotocols.o \
 efi_selftest_memory.o \
+efi_selftest_register_notify.o \
 efi_selftest_rtc.o \
 efi_selftest_snp.o \
 efi_selftest_textinput.o \
index 29ac0ce..644c5ad 100644 (file)
@@ -337,7 +337,7 @@ static int execute(void)
                }
                if (len >= dp_size(dp_partition))
                        continue;
-               if (efi_st_memcmp(dp, dp_partition, len))
+               if (memcmp(dp, dp_partition, len))
                        continue;
                handle_partition = handles[i];
                break;
@@ -409,7 +409,7 @@ static int execute(void)
                             (unsigned int)buf_size);
                return EFI_ST_FAILURE;
        }
-       if (efi_st_memcmp(buf, "ello world!", 11)) {
+       if (memcmp(buf, "ello world!", 11)) {
                efi_st_error("Unexpected file content\n");
                return EFI_ST_FAILURE;
        }
@@ -480,7 +480,7 @@ static int execute(void)
                             (unsigned int)buf_size);
                return EFI_ST_FAILURE;
        }
-       if (efi_st_memcmp(buf, "U-Boot", 7)) {
+       if (memcmp(buf, "U-Boot", 7)) {
                efi_st_error("Unexpected file content %s\n", buf);
                return EFI_ST_FAILURE;
        }
index 0bc5da6..4467f49 100644 (file)
@@ -153,8 +153,8 @@ static int execute(void)
        }
        table = NULL;
        for (i = 0; i < sys_table->nr_tables; ++i) {
-               if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
-                                  sizeof(efi_guid_t)))
+               if (!memcmp(&sys_table->tables[i].guid, &table_guid,
+                           sizeof(efi_guid_t)))
                        table = sys_table->tables[i].table;
        }
        if (!table) {
@@ -192,8 +192,8 @@ static int execute(void)
        table = NULL;
        tabcnt = 0;
        for (i = 0; i < sys_table->nr_tables; ++i) {
-               if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
-                                  sizeof(efi_guid_t))) {
+               if (!memcmp(&sys_table->tables[i].guid, &table_guid,
+                           sizeof(efi_guid_t))) {
                        table = sys_table->tables[i].table;
                        ++tabcnt;
                }
@@ -235,8 +235,8 @@ static int execute(void)
        }
        table = NULL;
        for (i = 0; i < sys_table->nr_tables; ++i) {
-               if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
-                                  sizeof(efi_guid_t))) {
+               if (!memcmp(&sys_table->tables[i].guid, &table_guid,
+                           sizeof(efi_guid_t))) {
                        table = sys_table->tables[i].table;
                }
        }
index ea2b380..5889ab1 100644 (file)
@@ -60,9 +60,8 @@ static int execute(void)
        efi_st_printf("%u protocols installed on image handle\n",
                      (unsigned int)protocol_buffer_count);
        for (i = 0; i < protocol_buffer_count; ++i) {
-               if (efi_st_memcmp(protocol_buffer[i],
-                                 &loaded_image_protocol_guid,
-                                 sizeof(efi_guid_t)))
+               if (memcmp(protocol_buffer[i], &loaded_image_protocol_guid,
+                          sizeof(efi_guid_t)))
                        found = true;
        }
        if (!found) {
index 449b6bf..06a87df 100644 (file)
@@ -322,8 +322,7 @@ static efi_status_t EFIAPI getinfo
         efi_uintn_t *buffer_size, void *buffer)
 {
        if (this == &file) {
-               if (efi_st_memcmp(info_type, &guid_file_info,
-                                 sizeof(efi_guid_t)))
+               if (memcmp(info_type, &guid_file_info, sizeof(efi_guid_t)))
                        return EFI_INVALID_PARAMETER;
                if (*buffer_size >= sizeof(struct file_info)) {
                        boottime->copy_mem(buffer, file_info,
@@ -333,8 +332,8 @@ static efi_status_t EFIAPI getinfo
                        return EFI_BUFFER_TOO_SMALL;
                }
        } else if (this == &volume) {
-               if (efi_st_memcmp(info_type, &guid_file_system_info,
-                                 sizeof(efi_guid_t)))
+               if (memcmp(info_type, &guid_file_system_info,
+                          sizeof(efi_guid_t)))
                        return EFI_INVALID_PARAMETER;
                if (*buffer_size >= sizeof(struct file_system_info)) {
                        boottime->copy_mem(buffer, file_system_info,
index 0ff35ce..8edb1e4 100644 (file)
@@ -332,13 +332,13 @@ static int execute(void)
                efi_st_error("Failed to get protocols per handle\n");
                return EFI_ST_FAILURE;
        }
-       if (efi_st_memcmp(prot_buffer[0], &guid1, 16) &&
-           efi_st_memcmp(prot_buffer[1], &guid1, 16)) {
+       if (memcmp(prot_buffer[0], &guid1, 16) &&
+           memcmp(prot_buffer[1], &guid1, 16)) {
                efi_st_error("Failed to get protocols per handle\n");
                return EFI_ST_FAILURE;
        }
-       if (efi_st_memcmp(prot_buffer[0], &guid3, 16) &&
-           efi_st_memcmp(prot_buffer[1], &guid3, 16)) {
+       if (memcmp(prot_buffer[0], &guid3, 16) &&
+           memcmp(prot_buffer[1], &guid3, 16)) {
                efi_st_error("Failed to get protocols per handle\n");
                return EFI_ST_FAILURE;
        }
index 5eeb42a..e71732d 100644 (file)
@@ -33,8 +33,8 @@ static int setup(const efi_handle_t handle,
        boottime = systable->boottime;
 
        for (i = 0; i < systable->nr_tables; ++i) {
-               if (!efi_st_memcmp(&systable->tables[i].guid, &fdt_guid,
-                                  sizeof(efi_guid_t))) {
+               if (!memcmp(&systable->tables[i].guid, &fdt_guid,
+                           sizeof(efi_guid_t))) {
                        if (fdt_addr) {
                                efi_st_error("Duplicate device tree\n");
                                return EFI_ST_FAILURE;
diff --git a/lib/efi_selftest/efi_selftest_register_notify.c b/lib/efi_selftest/efi_selftest_register_notify.c
new file mode 100644 (file)
index 0000000..ee0ef39
--- /dev/null
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_register_notify
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the following protocol services:
+ * InstallProtocolInterface, UninstallProtocolInterface,
+ * RegisterProtocolNotify, CreateEvent, CloseEvent.
+ */
+
+#include <efi_selftest.h>
+
+/*
+ * The test currently does not actually call the interface function.
+ * So this is just a dummy structure.
+ */
+struct interface {
+       void (EFIAPI * inc)(void);
+};
+
+struct context {
+       void *registration_key;
+       efi_uintn_t notify_count;
+       efi_uintn_t handle_count;
+       efi_handle_t *handles;
+};
+
+static struct efi_boot_services *boottime;
+static efi_guid_t guid1 =
+       EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
+                0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
+static efi_guid_t guid2 =
+       EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
+                0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
+static struct context context;
+static struct efi_event *event;
+
+/*
+ * Notification function, increments the notification count if parameter
+ * context is provided.
+ *
+ * @event      notified event
+ * @context    pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+       struct context *cp = context;
+       efi_status_t ret;
+
+       cp->notify_count++;
+
+       ret = boottime->locate_handle_buffer(BY_REGISTER_NOTIFY, NULL,
+                                            cp->registration_key,
+                                            &cp->handle_count,
+                                            &cp->handles);
+       if (ret != EFI_SUCCESS)
+               cp->handle_count = 0;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle:    handle of the loaded image
+ * @systable:  system table
+ */
+static int setup(const efi_handle_t img_handle,
+                const struct efi_system_table *systable)
+{
+       efi_status_t ret;
+
+       boottime = systable->boottime;
+
+       ret = boottime->create_event(EVT_NOTIFY_SIGNAL,
+                                    TPL_CALLBACK, notify, &context,
+                                    &event);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not create event\n");
+               return EFI_ST_FAILURE;
+       }
+
+       ret = boottime->register_protocol_notify(&guid1, event,
+                                                &context.registration_key);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not register event\n");
+               return EFI_ST_FAILURE;
+       }
+
+       return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ */
+static int teardown(void)
+{
+       efi_status_t ret;
+
+       if (event) {
+               ret = boottime->close_event(event);
+               event = NULL;
+               if (ret != EFI_SUCCESS) {
+                       efi_st_error("could not close event\n");
+                       return EFI_ST_FAILURE;
+               }
+       }
+
+       return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ */
+static int execute(void)
+{
+       efi_status_t ret;
+       efi_handle_t handle1 = NULL, handle2 = NULL;
+       struct interface interface1, interface2;
+
+       ret = boottime->install_protocol_interface(&handle1, &guid1,
+                                                  EFI_NATIVE_INTERFACE,
+                                                  &interface1);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not install interface\n");
+               return EFI_ST_FAILURE;
+       }
+       if (!context.notify_count) {
+               efi_st_error("install was not notified\n");
+               return EFI_ST_FAILURE;
+       }
+       if (context.notify_count > 1) {
+               efi_st_error("install was notified too often\n");
+               return EFI_ST_FAILURE;
+       }
+       if (context.handle_count != 1) {
+               efi_st_error("LocateHandle failed\n");
+               return EFI_ST_FAILURE;
+       }
+       ret = boottime->free_pool(context.handles);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("FreePool failed\n");
+               return EFI_ST_FAILURE;
+       }
+       context.notify_count = 0;
+       ret = boottime->install_protocol_interface(&handle1, &guid2,
+                                                  EFI_NATIVE_INTERFACE,
+                                                  &interface1);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not install interface\n");
+               return EFI_ST_FAILURE;
+       }
+       if (context.notify_count) {
+               efi_st_error("wrong protocol was notified\n");
+               return EFI_ST_FAILURE;
+       }
+       context.notify_count = 0;
+       ret = boottime->reinstall_protocol_interface(handle1, &guid1,
+                                                    &interface1, &interface2);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not reinstall interface\n");
+               return EFI_ST_FAILURE;
+       }
+       if (!context.notify_count) {
+               efi_st_error("reinstall was not notified\n");
+               return EFI_ST_FAILURE;
+       }
+       if (context.notify_count > 1) {
+               efi_st_error("reinstall was notified too often\n");
+               return EFI_ST_FAILURE;
+       }
+       if (context.handle_count != 1) {
+               efi_st_error("LocateHandle failed\n");
+               return EFI_ST_FAILURE;
+       }
+       ret = boottime->free_pool(context.handles);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("FreePool failed\n");
+               return EFI_ST_FAILURE;
+       }
+       context.notify_count = 0;
+       ret = boottime->install_protocol_interface(&handle2, &guid1,
+                                                  EFI_NATIVE_INTERFACE,
+                                                  &interface1);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not install interface\n");
+               return EFI_ST_FAILURE;
+       }
+       if (!context.notify_count) {
+               efi_st_error("install was not notified\n");
+               return EFI_ST_FAILURE;
+       }
+       if (context.notify_count > 1) {
+               efi_st_error("install was notified too often\n");
+               return EFI_ST_FAILURE;
+       }
+       if (context.handle_count != 2) {
+               efi_st_error("LocateHandle failed\n");
+               return EFI_ST_FAILURE;
+       }
+       ret = boottime->free_pool(context.handles);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("FreePool failed\n");
+               return EFI_ST_FAILURE;
+       }
+
+       ret = boottime->uninstall_multiple_protocol_interfaces
+                       (handle1, &guid1, &interface2,
+                        &guid2, &interface1, NULL);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
+               return EFI_ST_FAILURE;
+       }
+       ret = boottime->uninstall_multiple_protocol_interfaces
+                       (handle2, &guid1, &interface1, NULL);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
+               return EFI_ST_FAILURE;
+       }
+
+       return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(regprotnot) = {
+       .name = "register protocol notify",
+       .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+       .setup = setup,
+       .execute = execute,
+       .teardown = teardown,
+};
index d7350e2..4c26619 100644 (file)
@@ -334,9 +334,8 @@ static int execute(void)
                 * Unfortunately QEMU ignores the broadcast flag.
                 * So we have to check for broadcasts too.
                 */
-               if (efi_st_memcmp(&destaddr, &net->mode->current_address,
-                                 ARP_HLEN) &&
-                   efi_st_memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
+               if (memcmp(&destaddr, &net->mode->current_address, ARP_HLEN) &&
+                   memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
                        continue;
                /*
                 * Check this is a DHCP reply
@@ -360,7 +359,7 @@ static int execute(void)
        addr = (u8 *)&buffer.p.ip_udp.ip_src;
        efi_st_printf("DHCP reply received from %u.%u.%u.%u (%pm) ",
                      addr[0], addr[1], addr[2], addr[3], &srcaddr);
-       if (!efi_st_memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
+       if (!memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
                efi_st_printf("as broadcast message.\n");
        else
                efi_st_printf("as unicast message.\n");
index 96049de..11207b8 100644 (file)
@@ -139,7 +139,7 @@ static int execute(void)
                return EFI_ST_FAILURE;
        }
        if (!exit_data || exit_data_size != sizeof(expected_text) ||
-           efi_st_memcmp(exit_data, expected_text, sizeof(expected_text))) {
+           memcmp(exit_data, expected_text, sizeof(expected_text))) {
                efi_st_error("Incorrect exit data\n");
                return EFI_ST_FAILURE;
        }
index 96a964c..ea73c25 100644 (file)
@@ -102,20 +102,6 @@ u16 *efi_st_translate_code(u16 code)
        return efi_st_unknown;
 }
 
-int efi_st_memcmp(const void *buf1, const void *buf2, size_t length)
-{
-       const u8 *pos1 = buf1;
-       const u8 *pos2 = buf2;
-
-       for (; length; --length) {
-               if (*pos1 != *pos2)
-                       return *pos1 - *pos2;
-               ++pos1;
-               ++pos2;
-       }
-       return 0;
-}
-
 int efi_st_strcmp_16_8(const u16 *buf1, const char *buf2)
 {
        for (; *buf1 || *buf2; ++buf1, ++buf2) {
index 47a8e7f..b028c64 100644 (file)
@@ -78,7 +78,7 @@ static int execute(void)
                efi_st_error("GetVariable failed\n");
                return EFI_ST_FAILURE;
        }
-       if (efi_st_memcmp(data, v + 4, 3)) {
+       if (memcmp(data, v + 4, 3)) {
                efi_st_error("GetVariable returned wrong value\n");
                return EFI_ST_FAILURE;
        }
@@ -106,7 +106,7 @@ static int execute(void)
                             (unsigned int)len);
                return EFI_ST_FAILURE;
        }
-       if (efi_st_memcmp(data, v, 8)) {
+       if (memcmp(data, v, 8)) {
                efi_st_error("GetVariable returned wrong value\n");
                return EFI_ST_FAILURE;
        }
@@ -129,7 +129,7 @@ static int execute(void)
        if (len != 15)
                efi_st_todo("GetVariable returned wrong length %u\n",
                            (unsigned int)len);
-       if (efi_st_memcmp(data, v, len))
+       if (memcmp(data, v, len))
                efi_st_todo("GetVariable returned wrong value\n");
        /* Enumerate variables */
        boottime->set_mem(&guid, 16, 0);
@@ -145,10 +145,10 @@ static int execute(void)
                                     (unsigned int)ret);
                        return EFI_ST_FAILURE;
                }
-               if (!efi_st_memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) &&
+               if (!memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) &&
                    !efi_st_strcmp_16_8(varname, "efi_st_var0"))
                        flag |= 1;
-               if (!efi_st_memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) &&
+               if (!memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) &&
                    !efi_st_strcmp_16_8(varname, "efi_st_var1"))
                        flag |= 2;
        }
index 56dbbe1..7af6b12 100644 (file)
@@ -228,7 +228,11 @@ ifeq ($(CONFIG_SYS_SOC),"at91")
 ALL-y  += $(obj)/boot.bin
 endif
 
+ifdef CONFIG_TPL_BUILD
+ALL-$(CONFIG_TPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-16bit-tpl.bin
+else
 ALL-$(CONFIG_SPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-16bit-spl.bin
+endif
 
 ALL-$(CONFIG_ARCH_ZYNQ)                += $(obj)/boot.bin
 ALL-$(CONFIG_ARCH_ZYNQMP)      += $(obj)/boot.bin
@@ -253,8 +257,20 @@ else
 FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit
 endif
 
+# Build the .dtb file if:
+#   - we are not using OF_PLATDATA
+#   - we are using OF_CONTROL
+#   - we have either OF_SEPARATE or OF_HOSTFILE
+build_dtb :=
+ifeq ($(CONFIG_$(SPL_TPL_)OF_PLATDATA),)
+ifneq ($(CONFIG_$(SPL_TPL_)OF_CONTROL),)
+ifeq ($(CONFIG_OF_SEPARATE)$(CONFIG_OF_HOSTFILE),y)
+build_dtb := y
+endif
+endif
+endif
 
-ifeq ($(CONFIG_$(SPL_TPL_)OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy)
+ifneq ($(build_dtb),)
 $(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \
                $(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \
                $(FINAL_DTB_CONTAINER)  FORCE
@@ -316,7 +332,7 @@ quiet_cmd_objcopy = OBJCOPY $@
 cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
 
 OBJCOPYFLAGS_$(SPL_BIN)-nodtb.bin = $(SPL_OBJCFLAGS) -O binary \
-               $(if $(CONFIG_SPL_X86_16BIT_INIT),-R .start16 -R .resetvec)
+               $(if $(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),-R .start16 -R .resetvec)
 
 $(obj)/$(SPL_BIN)-nodtb.bin: $(obj)/$(SPL_BIN) FORCE
        $(call if_changed,objcopy)
@@ -325,6 +341,10 @@ OBJCOPYFLAGS_u-boot-x86-16bit-spl.bin := -O binary -j .start16 -j .resetvec
 $(obj)/u-boot-x86-16bit-spl.bin: $(obj)/u-boot-spl FORCE
        $(call if_changed,objcopy)
 
+OBJCOPYFLAGS_u-boot-x86-16bit-tpl.bin := -O binary -j .start16 -j .resetvec
+$(obj)/u-boot-x86-16bit-tpl.bin: $(obj)/u-boot-tpl FORCE
+       $(call if_changed,objcopy)
+
 LDFLAGS_$(SPL_BIN) += -T u-boot-spl.lds $(LDFLAGS_FINAL)
 
 # Avoid 'Not enough room for program headers' error on binutils 2.28 onwards.
index 112d5cb..f301ecb 100644 (file)
@@ -4,12 +4,33 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <asm/clk.h>
 #include <dm/test.h>
 #include <linux/err.h>
 #include <test/ut.h>
 
+/* Base test of the clk uclass */
+static int dm_test_clk_base(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+       struct clk clk_method1;
+       struct clk clk_method2;
+
+       /* Get the device using the clk device */
+       ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test", &dev));
+
+       /* Get the same clk port in 2 different ways and compare */
+       ut_assertok(clk_get_by_index(dev, 1, &clk_method1));
+       ut_assertok(clk_get_by_index_nodev(dev_ofnode(dev), 1, &clk_method2));
+       ut_asserteq(clk_method1.id, clk_method2.id);
+
+       return 0;
+}
+
+DM_TEST(dm_test_clk_base, DM_TESTF_SCAN_FDT);
+
 static int dm_test_clk(struct unit_test_state *uts)
 {
        struct udevice *dev_fixed, *dev_fixed_factor, *dev_clk, *dev_test;
index c02866a..c61daed 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <reset.h>
 #include <dm/test.h>
 #include <asm/reset.h>
 #include <test/ut.h>
 /* This is the other reset phandle specifier handled by bulk */
 #define OTHER_RESET_ID 2
 
+/* Base test of the reset uclass */
+static int dm_test_reset_base(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+       struct reset_ctl reset_method1;
+       struct reset_ctl reset_method2;
+
+       /* Get the device using the reset device */
+       ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test",
+                                             &dev));
+
+       /* Get the same reset port in 2 different ways and compare */
+       ut_assertok(reset_get_by_index(dev, 1, &reset_method1));
+       ut_assertok(reset_get_by_index_nodev(dev_ofnode(dev), 1,
+                                            &reset_method2));
+       ut_asserteq(reset_method1.id, reset_method2.id);
+
+       return 0;
+}
+
+DM_TEST(dm_test_reset_base, DM_TESTF_SCAN_FDT);
+
 static int dm_test_reset(struct unit_test_state *uts)
 {
        struct udevice *dev_reset;
index 04ed2b7..927fa85 100644 (file)
@@ -342,6 +342,13 @@ size:
        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.
+
 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>'.
index ccf2920..0ba542e 100644 (file)
@@ -57,7 +57,7 @@ class Section(object):
         self._name = name
         self._node = node
         self._image = image
-        self._offset = 0
+        self._offset = None
         self._size = None
         self._align_size = None
         self._pad_before = 0
@@ -75,6 +75,7 @@ class Section(object):
 
     def _ReadNode(self):
         """Read properties from the section node"""
+        self._offset = fdt_util.GetInt(self._node, 'offset')
         self._size = fdt_util.GetInt(self._node, 'size')
         self._align_size = fdt_util.GetInt(self._node, 'align-size')
         if tools.NotPowerOfTwo(self._align_size):
@@ -130,7 +131,7 @@ class Section(object):
             entry.AddMissingProperties()
 
     def SetCalculatedProperties(self):
-        state.SetInt(self._node, 'offset', self._offset)
+        state.SetInt(self._node, 'offset', self._offset or 0)
         state.SetInt(self._node, 'size', self._size)
         image_pos = self._image_pos
         if self._parent_section:
@@ -424,8 +425,8 @@ class Section(object):
         Args:
             fd: File to write the map to
         """
-        Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size,
-                           self._image_pos)
+        Entry.WriteMapLine(fd, indent, self._name, self._offset or 0,
+                           self._size, self._image_pos)
         for entry in self._entries.values():
             entry.WriteMap(fd, indent + 1)
 
index 3446e2e..b32e4e1 100644 (file)
@@ -133,8 +133,8 @@ def Binman(options, args):
                     if name not in options.image:
                         del images[name]
                         skip.append(name)
-                if skip:
-                    print 'Skipping images: %s\n' % ', '.join(skip)
+                if skip and options.verbosity >= 2:
+                    print 'Skipping images: %s' % ', '.join(skip)
 
             state.Prepare(images, dtb)
 
index 7f1b413..3681a48 100644 (file)
@@ -67,7 +67,8 @@ class Entry_section(Entry):
     def Pack(self, offset):
         """Pack all entries into the section"""
         self._section.PackEntries()
-        self._section.SetOffset(offset)
+        if self._section._offset is None:
+            self._section.SetOffset(offset)
         self.size = self._section.GetSize()
         return super(Entry_section, self).Pack(offset)
 
index 6e99819..c4aa510 100644 (file)
@@ -51,10 +51,10 @@ class Entry_text(Entry):
         self.text_label, = self.GetEntryArgsOrProps(
             [EntryArg('text-label', str)])
         self.value, = self.GetEntryArgsOrProps([EntryArg(self.text_label, str)])
+
+    def ObtainContents(self):
         if not self.value:
             self.Raise("No value provided for text label '%s'" %
                        self.text_label)
-
-    def ObtainContents(self):
         self.SetContents(self.value)
         return True
index c4d970e..334ff9f 100644 (file)
@@ -18,6 +18,7 @@ class Entry_vblock(Entry):
     """An entry which contains a Chromium OS verified boot block
 
     Properties / Entry arguments:
+        - content: List of phandles to entries to sign
         - keydir: Directory containing the public keys to use
         - keyblock: Name of the key file to use (inside keydir)
         - signprivate: Name of provide key file to use (inside keydir)
index e77fce5..daea1ea 100644 (file)
@@ -187,7 +187,8 @@ class TestFunctional(unittest.TestCase):
         return control.Binman(options, args)
 
     def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
-                    entry_args=None, images=None, use_real_dtb=False):
+                    entry_args=None, images=None, use_real_dtb=False,
+                    verbosity=None):
         """Run binman with a given test file
 
         Args:
@@ -210,6 +211,8 @@ class TestFunctional(unittest.TestCase):
             args.append('-up')
         if not use_real_dtb:
             args.append('--fake-dtb')
+        if verbosity is not None:
+            args.append('-v%d' % verbosity)
         if entry_args:
             for arg, value in entry_args.iteritems():
                 args.append('-a%s=%s' % (arg, value))
@@ -1459,13 +1462,22 @@ class TestFunctional(unittest.TestCase):
 
     def testSelectImage(self):
         """Test that we can select which images to build"""
-        with test_util.capture_sys_output() as (stdout, stderr):
-            retcode = self._DoTestFile('006_dual_image.dts', images=['image2'])
-        self.assertEqual(0, retcode)
-        self.assertIn('Skipping images: image1', stdout.getvalue())
+        expected = 'Skipping images: image1'
+
+        # We should only get the expected message in verbose mode
+        for verbosity in (None, 2):
+            with test_util.capture_sys_output() as (stdout, stderr):
+                retcode = self._DoTestFile('006_dual_image.dts',
+                                           verbosity=verbosity,
+                                           images=['image2'])
+            self.assertEqual(0, retcode)
+            if verbosity:
+                self.assertIn(expected, stdout.getvalue())
+            else:
+                self.assertNotIn(expected, stdout.getvalue())
 
-        self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
-        self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
+            self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
+            self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
 
     def testUpdateFdtAll(self):
         """Test that all device trees are updated with offset/size info"""
@@ -1771,6 +1783,24 @@ class TestFunctional(unittest.TestCase):
         data = self._DoReadFile('100_intel_refcode.dts')
         self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
 
+    def testSectionOffset(self):
+        """Tests use of a section with an offset"""
+        data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
+                                                   map=True)
+        self.assertEqual('''ImagePos    Offset      Size  Name
+00000000  00000000  00000038  main-section
+00000004   00000004  00000010  section@0
+00000004    00000000  00000004  u-boot
+00000018   00000018  00000010  section@1
+00000018    00000000  00000004  u-boot
+0000002c   0000002c  00000004  section@2
+0000002c    00000000  00000004  u-boot
+''', map_data)
+        self.assertEqual(data,
+                         4 * chr(0x26) + U_BOOT_DATA + 12 * chr(0x21) +
+                         4 * chr(0x26) + U_BOOT_DATA + 12 * chr(0x61) +
+                         4 * chr(0x26) + U_BOOT_DATA + 8 * chr(0x26))
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/101_sections_offset.dts b/tools/binman/test/101_sections_offset.dts
new file mode 100644 (file)
index 0000000..46708ff
--- /dev/null
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               pad-byte = <0x26>;
+               size = <0x38>;
+               section@0 {
+                       read-only;
+                       offset = <0x4>;
+                       size = <0x10>;
+                       pad-byte = <0x21>;
+
+                       u-boot {
+                       };
+               };
+               section@1 {
+                       size = <0x10>;
+                       pad-byte = <0x61>;
+                       offset = <0x18>;
+
+                       u-boot {
+                       };
+               };
+               section@2 {
+                       offset = <0x2c>;
+                       u-boot {
+                       };
+               };
+       };
+};