summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--arch/Kconfig32
-rw-r--r--arch/arm/dts/Makefile7
-rw-r--r--arch/arm/dts/armada-388-clearfog-u-boot.dtsi4
-rw-r--r--arch/arm/dts/armada-xp-crs305-1g-4s-u-boot.dtsi13
-rw-r--r--arch/arm/dts/armada-xp-crs305-1g-4s.dts110
-rw-r--r--arch/arm/dts/sama5d3xcm.dtsi32
-rw-r--r--arch/arm/dts/sama5d3xcm_cmp.dtsi32
-rw-r--r--arch/arm/dts/socfpga_arria5_socdk.dts4
-rw-r--r--arch/arm/dts/socfpga_cyclone5_is1.dts4
-rw-r--r--arch/arm/dts/socfpga_cyclone5_socdk.dts4
-rw-r--r--arch/arm/dts/socfpga_cyclone5_sockit.dts4
-rw-r--r--arch/arm/dts/socfpga_cyclone5_vining_fpga.dts4
-rw-r--r--arch/arm/dts/sun50i-a64-teres-i-u-boot.dtsi41
-rw-r--r--arch/arm/dts/sun50i-a64-teres-i.dts270
-rw-r--r--arch/arm/dts/sun50i-h6-beelink-gs1.dts184
-rw-r--r--arch/arm/include/asm/arch-meson/usb.h12
-rw-r--r--arch/arm/mach-meson/board-g12a.c126
-rw-r--r--arch/arm/mach-mvebu/Kconfig7
-rw-r--r--arch/riscv/Kconfig7
-rw-r--r--arch/riscv/cpu/cpu.c4
-rw-r--r--arch/riscv/cpu/start.S8
-rw-r--r--arch/riscv/include/asm/global_data.h2
-rw-r--r--arch/riscv/lib/Makefile1
-rw-r--r--arch/riscv/lib/asm-offsets.c2
-rw-r--r--arch/riscv/lib/image.c55
-rw-r--r--arch/riscv/lib/smp.c2
-rw-r--r--arch/x86/Kconfig10
-rw-r--r--arch/x86/Makefile16
-rw-r--r--arch/x86/cpu/Makefile15
-rw-r--r--arch/x86/cpu/broadwell/Makefile23
-rw-r--r--arch/x86/cpu/broadwell/cpu.c676
-rw-r--r--arch/x86/cpu/broadwell/cpu_from_spl.c63
-rw-r--r--arch/x86/cpu/broadwell/cpu_full.c694
-rw-r--r--arch/x86/cpu/broadwell/northbridge.c100
-rw-r--r--arch/x86/cpu/broadwell/pch.c37
-rw-r--r--arch/x86/cpu/broadwell/sdram.c136
-rw-r--r--arch/x86/cpu/i386/cpu.c113
-rw-r--r--arch/x86/cpu/intel_common/Makefile17
-rw-r--r--arch/x86/cpu/intel_common/car.S2
-rw-r--r--arch/x86/cpu/intel_common/cpu_from_spl.c27
-rw-r--r--arch/x86/cpu/ivybridge/bd82x6x.c15
-rw-r--r--arch/x86/cpu/mp_init.c10
-rw-r--r--arch/x86/cpu/start.S13
-rw-r--r--arch/x86/cpu/start64.S2
-rw-r--r--arch/x86/cpu/start_from_spl.S71
-rw-r--r--arch/x86/cpu/start_from_tpl.S49
-rw-r--r--arch/x86/cpu/u-boot-spl.lds2
-rw-r--r--arch/x86/cpu/x86_64/cpu.c5
-rw-r--r--arch/x86/dts/chromebook_samus.dts53
-rw-r--r--arch/x86/dts/reset.dtsi2
-rw-r--r--arch/x86/dts/rtc.dtsi2
-rw-r--r--arch/x86/dts/u-boot.dtsi162
-rw-r--r--arch/x86/include/asm/handoff.h15
-rw-r--r--arch/x86/include/asm/mrccache.h11
-rw-r--r--arch/x86/include/asm/spl.h17
-rw-r--r--arch/x86/include/asm/u-boot-x86.h20
-rw-r--r--arch/x86/lib/Makefile9
-rw-r--r--arch/x86/lib/bootm.c2
-rw-r--r--arch/x86/lib/fsp/fsp_car.S2
-rw-r--r--arch/x86/lib/init_helpers.c5
-rw-r--r--arch/x86/lib/mrccache.c52
-rw-r--r--arch/x86/lib/spl.c44
-rw-r--r--arch/x86/lib/tpl.c118
-rw-r--r--board/AndesTech/ax25-ae350/MAINTAINERS2
-rw-r--r--board/AndesTech/ax25-ae350/ax25-ae350.c4
-rw-r--r--board/emulation/qemu-riscv/Kconfig3
-rw-r--r--board/google/Kconfig8
-rw-r--r--board/google/chromebook_samus/Kconfig14
-rw-r--r--board/google/chromebook_samus/MAINTAINERS7
-rw-r--r--board/mikrotik/crs305-1g-4s/.gitignore1
-rw-r--r--board/mikrotik/crs305-1g-4s/MAINTAINERS7
-rw-r--r--board/mikrotik/crs305-1g-4s/Makefile14
-rw-r--r--board/mikrotik/crs305-1g-4s/README23
-rw-r--r--board/mikrotik/crs305-1g-4s/binary.011
-rw-r--r--board/mikrotik/crs305-1g-4s/crs305-1g-4s.c75
-rw-r--r--board/mikrotik/crs305-1g-4s/kwbimage.cfg.in12
-rw-r--r--board/sunxi/MAINTAINERS12
-rw-r--r--board/ti/ks2_evm/mux-k2g.h36
-rw-r--r--cmd/Kconfig2
-rw-r--r--cmd/bootefi.c27
-rw-r--r--cmd/booti.c8
-rw-r--r--cmd/mdio.c27
-rw-r--r--configs/Cubietruck_plus_defconfig2
-rw-r--r--configs/Sinovoip_BPI_M3_defconfig4
-rw-r--r--configs/ae350_rv32_defconfig2
-rw-r--r--configs/ae350_rv32_xip_defconfig37
-rw-r--r--configs/ae350_rv64_defconfig2
-rw-r--r--configs/ae350_rv64_xip_defconfig38
-rw-r--r--configs/beelink_gs1_defconfig15
-rw-r--r--configs/chromebook_samus_defconfig2
-rw-r--r--configs/chromebook_samus_tpl_defconfig83
-rw-r--r--configs/clearfog_defconfig4
-rw-r--r--configs/crs305-1g-4s_defconfig52
-rw-r--r--configs/db-88f6720_defconfig1
-rw-r--r--configs/db-88f6820-gp_defconfig4
-rw-r--r--configs/teres_i_defconfig22
-rw-r--r--doc/README.x8616
-rw-r--r--doc/device-tree-bindings/net/micrel-ksz90x1.txt27
-rw-r--r--drivers/clk/clk-uclass.c75
-rw-r--r--drivers/clk/sifive/fu540-prci.c2
-rw-r--r--drivers/core/ofnode.c2
-rw-r--r--drivers/misc/cros_ec.c2
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_eth.c1
-rw-r--r--drivers/net/phy/Kconfig20
-rw-r--r--drivers/net/phy/aquantia.c7
-rw-r--r--drivers/net/phy/micrel_ksz90x1.c24
-rw-r--r--drivers/net/phy/phy.c21
-rw-r--r--drivers/net/phy/realtek.c19
-rw-r--r--drivers/net/phy/ti.c130
-rw-r--r--drivers/net/sun8i_emac.c74
-rw-r--r--drivers/pci/pci_rom.c2
-rw-r--r--drivers/phy/Kconfig8
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/meson-g12a-usb2.c216
-rw-r--r--drivers/phy/meson-g12a-usb3-pcie.c345
-rw-r--r--drivers/reset/reset-uclass.c53
-rw-r--r--drivers/serial/serial_sifive.c2
-rw-r--r--drivers/spi/atcspi200_spi.c2
-rw-r--r--drivers/sysreset/sysreset_x86.c101
-rw-r--r--drivers/usb/dwc3/Kconfig8
-rw-r--r--drivers/usb/dwc3/Makefile1
-rw-r--r--drivers/usb/dwc3/dwc3-meson-g12a.c456
-rw-r--r--include/clk.h15
-rw-r--r--include/configs/ax25-ae350.h2
-rw-r--r--include/configs/chromebook_link.h3
-rw-r--r--include/configs/chromebook_samus.h2
-rw-r--r--include/configs/crs305-1g-4s.h37
-rw-r--r--include/configs/qemu-riscv.h16
-rw-r--r--include/configs/qemu-x86.h5
-rw-r--r--include/configs/sunxi-common.h16
-rw-r--r--include/configs/x86-common.h1
-rw-r--r--include/efi_api.h5
-rw-r--r--include/efi_loader.h34
-rw-r--r--include/efi_selftest.h11
-rw-r--r--include/pch.h18
-rw-r--r--include/pci.h6
-rw-r--r--include/phy.h70
-rw-r--r--include/reset.h16
-rw-r--r--lib/efi_loader/efi_boottime.c304
-rw-r--r--lib/efi_loader/efi_image_loader.c2
-rw-r--r--lib/efi_loader/efi_root_node.c48
-rw-r--r--lib/efi_loader/efi_setup.c16
-rw-r--r--lib/efi_selftest/Makefile1
-rw-r--r--lib/efi_selftest/efi_selftest_block_device.c6
-rw-r--r--lib/efi_selftest/efi_selftest_config_table.c12
-rw-r--r--lib/efi_selftest/efi_selftest_loaded_image.c5
-rw-r--r--lib/efi_selftest/efi_selftest_loadimage.c7
-rw-r--r--lib/efi_selftest/efi_selftest_manageprotocols.c8
-rw-r--r--lib/efi_selftest/efi_selftest_memory.c4
-rw-r--r--lib/efi_selftest/efi_selftest_register_notify.c231
-rw-r--r--lib/efi_selftest/efi_selftest_snp.c7
-rw-r--r--lib/efi_selftest/efi_selftest_startimage_exit.c2
-rw-r--r--lib/efi_selftest/efi_selftest_util.c14
-rw-r--r--lib/efi_selftest/efi_selftest_variables.c10
-rw-r--r--scripts/Makefile.spl24
-rw-r--r--test/dm/clk.c21
-rw-r--r--test/dm/reset.c23
-rw-r--r--tools/binman/README7
-rw-r--r--tools/binman/bsection.py9
-rw-r--r--tools/binman/control.py4
-rw-r--r--tools/binman/etype/section.py3
-rw-r--r--tools/binman/etype/text.py4
-rw-r--r--tools/binman/etype/vblock.py1
-rw-r--r--tools/binman/ftest.py44
-rw-r--r--tools/binman/test/101_sections_offset.dts35
166 files changed, 5443 insertions, 1424 deletions
diff --git a/Makefile b/Makefile
index 5ae5db591ff..9fb90c0779a 100644
--- 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)
diff --git a/arch/Kconfig b/arch/Kconfig
index 03277dd2c16..239289b8856 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -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
@@ -164,6 +166,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"
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 75d4fda73e5..83058c4452f 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -181,7 +181,8 @@ dtb-$(CONFIG_ARCH_MVEBU) += \
armada-38x-controlcenterdc.dtb \
armada-385-atl-x530.dtb \
armada-385-atl-x530DP.dtb \
- armada-xp-db-xc3-24g4xg.dtb
+ armada-xp-db-xc3-24g4xg.dtb \
+ armada-xp-crs305-1g-4s.dtb
dtb-$(CONFIG_ARCH_UNIPHIER_LD11) += \
uniphier-ld11-global.dtb \
@@ -499,6 +500,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
@@ -513,7 +515,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/armada-388-clearfog-u-boot.dtsi b/arch/arm/dts/armada-388-clearfog-u-boot.dtsi
index f31691ee949..a12694e1710 100644
--- a/arch/arm/dts/armada-388-clearfog-u-boot.dtsi
+++ b/arch/arm/dts/armada-388-clearfog-u-boot.dtsi
@@ -7,3 +7,7 @@
u-boot,dm-spl;
};
};
+
+&sdhci {
+ u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/armada-xp-crs305-1g-4s-u-boot.dtsi b/arch/arm/dts/armada-xp-crs305-1g-4s-u-boot.dtsi
new file mode 100644
index 00000000000..8576a027300
--- /dev/null
+++ b/arch/arm/dts/armada-xp-crs305-1g-4s-u-boot.dtsi
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
+
+&spi0 {
+ u-boot,dm-pre-reloc;
+
+ spi-flash@0 {
+ u-boot,dm-pre-reloc;
+ };
+};
diff --git a/arch/arm/dts/armada-xp-crs305-1g-4s.dts b/arch/arm/dts/armada-xp-crs305-1g-4s.dts
new file mode 100644
index 00000000000..1116f5c96c4
--- /dev/null
+++ b/arch/arm/dts/armada-xp-crs305-1g-4s.dts
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree file for CRS305-1G-4S board
+ *
+ * Copyright (C) 2016 Allied Telesis Labs
+ *
+ * Based on armada-xp-db.dts
+ *
+ * Note: this Device Tree assumes that the bootloader has remapped the
+ * internal registers to 0xf1000000 (instead of the default
+ * 0xd0000000). The 0xf1000000 is the default used by the recent,
+ * DT-capable, U-Boot bootloaders provided by Marvell. Some earlier
+ * boards were delivered with an older version of the bootloader that
+ * left internal registers mapped at 0xd0000000. If you are in this
+ * situation, you should either update your bootloader (preferred
+ * solution) or the below Device Tree should be adjusted.
+ */
+
+/dts-v1/;
+#include "armada-xp-98dx3236.dtsi"
+#include "armada-xp-crs305-1g-4s-u-boot.dtsi"
+
+/ {
+ model = "CRS305-1G-4S";
+ compatible = "marvell,armadaxp-98dx3236", "marvell,armadaxp-mv78260", "marvell,armadaxp", "marvell,armada-370-xp";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ bootargs = "console=ttyS0,115200 earlyprintk";
+ };
+
+ aliases {
+ spi0 = &spi0;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0 0x00000000 0 0x20000000>; /* 512 MB */
+ };
+};
+
+&L2 {
+ arm,parity-enable;
+ marvell,ecc-enable;
+};
+
+&devbus_bootcs {
+ status = "okay";
+
+ /* Device Bus parameters are required */
+
+ /* Read parameters */
+ devbus,bus-width = <16>;
+ devbus,turn-off-ps = <60000>;
+ devbus,badr-skew-ps = <0>;
+ devbus,acc-first-ps = <124000>;
+ devbus,acc-next-ps = <248000>;
+ devbus,rd-setup-ps = <0>;
+ devbus,rd-hold-ps = <0>;
+
+ /* Write parameters */
+ devbus,sync-enable = <0>;
+ devbus,wr-high-ps = <60000>;
+ devbus,wr-low-ps = <60000>;
+ devbus,ale-wr-ps = <60000>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&i2c0 {
+ clock-frequency = <100000>;
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+
+ spi-flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-flash", "jedec,spi-nor";
+ reg = <0>; /* Chip select 0 */
+ spi-max-frequency = <108000000>;
+ m25p,fast-read;
+
+ partition@u-boot {
+ reg = <0x00000000 0x00100000>;
+ label = "u-boot";
+ };
+ partition@u-boot-env {
+ reg = <0x00100000 0x00040000>;
+ label = "u-boot-env";
+ };
+ partition@unused {
+ reg = <0x00140000 0x00ec0000>;
+ label = "unused";
+ };
+
+ };
+};
diff --git a/arch/arm/dts/sama5d3xcm.dtsi b/arch/arm/dts/sama5d3xcm.dtsi
index 2cf9c3611db..d123057f304 100644
--- a/arch/arm/dts/sama5d3xcm.dtsi
+++ b/arch/arm/dts/sama5d3xcm.dtsi
@@ -44,28 +44,28 @@
reg = <0x1>;
interrupt-parent = <&pioB>;
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
- txen-skew-ps = <800>;
- txc-skew-ps = <3000>;
- rxdv-skew-ps = <400>;
- rxc-skew-ps = <3000>;
- rxd0-skew-ps = <400>;
- rxd1-skew-ps = <400>;
- rxd2-skew-ps = <400>;
- rxd3-skew-ps = <400>;
+ txen-skew-ps = <480>;
+ txc-skew-ps = <1800>;
+ rxdv-skew-ps = <240>;
+ rxc-skew-ps = <1800>;
+ rxd0-skew-ps = <240>;
+ rxd1-skew-ps = <240>;
+ rxd2-skew-ps = <240>;
+ rxd3-skew-ps = <240>;
};
ethernet-phy@7 {
reg = <0x7>;
interrupt-parent = <&pioB>;
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
- txen-skew-ps = <800>;
- txc-skew-ps = <3000>;
- rxdv-skew-ps = <400>;
- rxc-skew-ps = <3000>;
- rxd0-skew-ps = <400>;
- rxd1-skew-ps = <400>;
- rxd2-skew-ps = <400>;
- rxd3-skew-ps = <400>;
+ txen-skew-ps = <480>;
+ txc-skew-ps = <1800>;
+ rxdv-skew-ps = <240>;
+ rxc-skew-ps = <1800>;
+ rxd0-skew-ps = <240>;
+ rxd1-skew-ps = <240>;
+ rxd2-skew-ps = <240>;
+ rxd3-skew-ps = <240>;
};
};
};
diff --git a/arch/arm/dts/sama5d3xcm_cmp.dtsi b/arch/arm/dts/sama5d3xcm_cmp.dtsi
index 77638c3cbea..332b057e0a9 100644
--- a/arch/arm/dts/sama5d3xcm_cmp.dtsi
+++ b/arch/arm/dts/sama5d3xcm_cmp.dtsi
@@ -43,28 +43,28 @@
reg = <0x1>;
interrupt-parent = <&pioB>;
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
- txen-skew-ps = <800>;
- txc-skew-ps = <3000>;
- rxdv-skew-ps = <400>;
- rxc-skew-ps = <3000>;
- rxd0-skew-ps = <400>;
- rxd1-skew-ps = <400>;
- rxd2-skew-ps = <400>;
- rxd3-skew-ps = <400>;
+ txen-skew-ps = <480>;
+ txc-skew-ps = <1800>;
+ rxdv-skew-ps = <240>;
+ rxc-skew-ps = <1800>;
+ rxd0-skew-ps = <240>;
+ rxd1-skew-ps = <240>;
+ rxd2-skew-ps = <240>;
+ rxd3-skew-ps = <240>;
};
ethernet-phy@7 {
reg = <0x7>;
interrupt-parent = <&pioB>;
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
- txen-skew-ps = <800>;
- txc-skew-ps = <3000>;
- rxdv-skew-ps = <400>;
- rxc-skew-ps = <3000>;
- rxd0-skew-ps = <400>;
- rxd1-skew-ps = <400>;
- rxd2-skew-ps = <400>;
- rxd3-skew-ps = <400>;
+ txen-skew-ps = <480>;
+ txc-skew-ps = <1800>;
+ rxdv-skew-ps = <240>;
+ rxc-skew-ps = <1800>;
+ rxd0-skew-ps = <240>;
+ rxd1-skew-ps = <240>;
+ rxd2-skew-ps = <240>;
+ rxd3-skew-ps = <240>;
};
};
diff --git a/arch/arm/dts/socfpga_arria5_socdk.dts b/arch/arm/dts/socfpga_arria5_socdk.dts
index 90e676e7019..fa972e287f8 100644
--- a/arch/arm/dts/socfpga_arria5_socdk.dts
+++ b/arch/arm/dts/socfpga_arria5_socdk.dts
@@ -67,9 +67,9 @@
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1560>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1200>;
};
&gpio0 {
diff --git a/arch/arm/dts/socfpga_cyclone5_is1.dts b/arch/arm/dts/socfpga_cyclone5_is1.dts
index 2d314129230..a769498791a 100644
--- a/arch/arm/dts/socfpga_cyclone5_is1.dts
+++ b/arch/arm/dts/socfpga_cyclone5_is1.dts
@@ -43,9 +43,9 @@
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1560>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1200>;
};
&gpio1 {
diff --git a/arch/arm/dts/socfpga_cyclone5_socdk.dts b/arch/arm/dts/socfpga_cyclone5_socdk.dts
index 6f138b2b261..95c7619b8d6 100644
--- a/arch/arm/dts/socfpga_cyclone5_socdk.dts
+++ b/arch/arm/dts/socfpga_cyclone5_socdk.dts
@@ -71,9 +71,9 @@
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1560>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1200>;
};
&gpio0 {
diff --git a/arch/arm/dts/socfpga_cyclone5_sockit.dts b/arch/arm/dts/socfpga_cyclone5_sockit.dts
index c155ff02eb6..90669cde45e 100644
--- a/arch/arm/dts/socfpga_cyclone5_sockit.dts
+++ b/arch/arm/dts/socfpga_cyclone5_sockit.dts
@@ -128,9 +128,9 @@
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1560>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1200>;
};
&gpio0 { /* GPIO 0..29 */
diff --git a/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts
index 355b3dbf438..ac57f41cb57 100644
--- a/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts
+++ b/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts
@@ -85,9 +85,9 @@
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1560>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1200>;
};
};
};
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
index 00000000000..1a64b7d09c2
--- /dev/null
+++ b/arch/arm/dts/sun50i-a64-teres-i-u-boot.dtsi
@@ -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
index 00000000000..c455b24dd07
--- /dev/null
+++ b/arch/arm/dts/sun50i-a64-teres-i.dts
@@ -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
index 00000000000..54b0882bedf
--- /dev/null
+++ b/arch/arm/dts/sun50i-h6-beelink-gs1.dts
@@ -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";
+};
diff --git a/arch/arm/include/asm/arch-meson/usb.h b/arch/arm/include/asm/arch-meson/usb.h
new file mode 100644
index 00000000000..b794b5ce77a
--- /dev/null
+++ b/arch/arm/include/asm/arch-meson/usb.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#ifndef __MESON_USB_H__
+#define __MESON_USB_H__
+
+int dwc3_meson_g12a_force_mode(struct udevice *dev, enum usb_dr_mode mode);
+
+#endif /* __MESON_USB_H__ */
diff --git a/arch/arm/mach-meson/board-g12a.c b/arch/arm/mach-meson/board-g12a.c
index fc3764b9604..1652970fbde 100644
--- a/arch/arm/mach-meson/board-g12a.c
+++ b/arch/arm/mach-meson/board-g12a.c
@@ -12,7 +12,12 @@
#include <asm/io.h>
#include <asm/armv8/mmu.h>
#include <linux/sizes.h>
+#include <usb.h>
+#include <linux/usb/otg.h>
+#include <asm/arch/usb.h>
+#include <usb/dwc2_udc.h>
#include <phy.h>
+#include <clk.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -148,3 +153,124 @@ void meson_eth_init(phy_interface_t mode, unsigned int flags)
/* Enable power gate */
clrbits_le32(G12A_MEM_PD_REG_0, G12A_MEM_PD_REG_0_ETH_MASK);
}
+
+#if CONFIG_IS_ENABLED(USB_DWC3_MESON_G12A) && \
+ CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
+static struct dwc2_plat_otg_data meson_g12a_dwc2_data;
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+ struct fdtdec_phandle_args args;
+ const void *blob = gd->fdt_blob;
+ int node, dwc2_node;
+ struct udevice *dev, *clk_dev;
+ struct clk clk;
+ int ret;
+
+ /* find the usb glue node */
+ node = fdt_node_offset_by_compatible(blob, -1,
+ "amlogic,meson-g12a-usb-ctrl");
+ if (node < 0) {
+ debug("Not found usb-control node\n");
+ return -ENODEV;
+ }
+
+ if (!fdtdec_get_is_enabled(blob, node)) {
+ debug("usb is disabled in the device tree\n");
+ return -ENODEV;
+ }
+
+ ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
+ if (ret) {
+ debug("Not found usb-control device\n");
+ return ret;
+ }
+
+ /* find the dwc2 node */
+ dwc2_node = fdt_node_offset_by_compatible(blob, node,
+ "amlogic,meson-g12a-usb");
+ if (dwc2_node < 0) {
+ debug("Not found dwc2 node\n");
+ return -ENODEV;
+ }
+
+ if (!fdtdec_get_is_enabled(blob, dwc2_node)) {
+ debug("dwc2 is disabled in the device tree\n");
+ return -ENODEV;
+ }
+
+ meson_g12a_dwc2_data.regs_otg = fdtdec_get_addr(blob, dwc2_node, "reg");
+ if (meson_g12a_dwc2_data.regs_otg == FDT_ADDR_T_NONE) {
+ debug("usbotg: can't get base address\n");
+ return -ENODATA;
+ }
+
+ /* Enable clock */
+ ret = fdtdec_parse_phandle_with_args(blob, dwc2_node, "clocks",
+ "#clock-cells", 0, 0, &args);
+ if (ret) {
+ debug("usbotg has no clocks defined in the device tree\n");
+ return ret;
+ }
+
+ ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &clk_dev);
+ if (ret)
+ return ret;
+
+ if (args.args_count != 1) {
+ debug("Can't find clock ID in the device tree\n");
+ return -ENODATA;
+ }
+
+ clk.dev = clk_dev;
+ clk.id = args.args[0];
+
+ ret = clk_enable(&clk);
+ if (ret) {
+ debug("Failed to enable usbotg clock\n");
+ return ret;
+ }
+
+ meson_g12a_dwc2_data.rx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+ "g-rx-fifo-size", 0);
+ meson_g12a_dwc2_data.np_tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+ "g-np-tx-fifo-size", 0);
+ meson_g12a_dwc2_data.tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+ "g-tx-fifo-size", 0);
+
+ /* Switch to peripheral mode */
+ ret = dwc3_meson_g12a_force_mode(dev, USB_DR_MODE_PERIPHERAL);
+ if (ret)
+ return ret;
+
+ return dwc2_udc_probe(&meson_g12a_dwc2_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+ const void *blob = gd->fdt_blob;
+ struct udevice *dev;
+ int node;
+ int ret;
+
+ /* find the usb glue node */
+ node = fdt_node_offset_by_compatible(blob, -1,
+ "amlogic,meson-g12a-usb-ctrl");
+ if (node < 0)
+ return -ENODEV;
+
+ if (!fdtdec_get_is_enabled(blob, node))
+ return -ENODEV;
+
+ ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
+ if (ret)
+ return ret;
+
+ /* Switch to OTG mode */
+ ret = dwc3_meson_g12a_force_mode(dev, USB_DR_MODE_HOST);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+#endif
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index a832e1dc8c9..495c48e6c74 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -164,6 +164,10 @@ config TARGET_DB_XC3_24G4XG
bool "Support DB-XC3-24G4XG"
select 98DX3336
+config TARGET_CRS305_1G_4S
+ bool "Support CRS305-1G-4S"
+ select 98DX3236
+
endchoice
config SYS_BOARD
@@ -183,6 +187,7 @@ config SYS_BOARD
default "a38x" if TARGET_CONTROLCENTERDC
default "x530" if TARGET_X530
default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG
+ default "crs305-1g-4s" if TARGET_CRS305_1G_4S
config SYS_CONFIG_NAME
default "clearfog" if TARGET_CLEARFOG
@@ -201,6 +206,7 @@ config SYS_CONFIG_NAME
default "controlcenterdc" if TARGET_CONTROLCENTERDC
default "x530" if TARGET_X530
default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG
+ default "crs305-1g-4s" if TARGET_CRS305_1G_4S
config SYS_VENDOR
default "Marvell" if TARGET_DB_MV784MP_GP
@@ -218,6 +224,7 @@ config SYS_VENDOR
default "CZ.NIC" if TARGET_TURRIS_MOX
default "gdsys" if TARGET_CONTROLCENTERDC
default "alliedtelesis" if TARGET_X530
+ default "mikrotik" if TARGET_CRS305_1G_4S
config SYS_SOC
default "mvebu"
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index ae8ff7b7657..362f3cdc655 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -162,6 +162,13 @@ config SBI_IPI
default y if RISCV_SMODE
depends on SMP
+config XIP
+ bool "XIP mode"
+ help
+ XIP (eXecute In Place) is a method for executing code directly
+ from a NOR flash memory without copying the code to ram.
+ Say yes here if U-Boot boots from flash directly.
+
config STACK_SIZE_SHIFT
int
default 13
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
index c32de8a4c3e..e9a8b437ed0 100644
--- a/arch/riscv/cpu/cpu.c
+++ b/arch/riscv/cpu/cpu.c
@@ -15,7 +15,10 @@
* The variables here must be stored in the data section since they are used
* before the bss section is available.
*/
+#ifdef CONFIG_OF_PRIOR_STAGE
phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
+#endif
+#ifndef CONFIG_XIP
u32 hart_lottery __attribute__((section(".data"))) = 0;
/*
@@ -23,6 +26,7 @@ u32 hart_lottery __attribute__((section(".data"))) = 0;
* finished initialization of global data.
*/
u32 available_harts_lock = 1;
+#endif
static inline bool supports_extension(char ext)
{
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
index a4433fbd6ba..60ac8c621e4 100644
--- a/arch/riscv/cpu/start.S
+++ b/arch/riscv/cpu/start.S
@@ -98,6 +98,7 @@ call_board_init_f_0:
mv sp, a0
#endif
+#ifndef CONFIG_XIP
/*
* Pick hart to initialize global data and run U-Boot. The other harts
* wait for initialization to complete.
@@ -106,15 +107,21 @@ call_board_init_f_0:
li s2, 1
amoswap.w s2, t1, 0(t0)
bnez s2, wait_for_gd_init
+#else
+ bnez tp, secondary_hart_loop
+#endif
+#ifdef CONFIG_OF_PRIOR_STAGE
la t0, prior_stage_fdt_address
SREG s1, 0(t0)
+#endif
jal board_init_f_init_reserve
/* save the boot hart id to global_data */
SREG tp, GD_BOOT_HART(gp)
+#ifndef CONFIG_XIP
la t0, available_harts_lock
fence rw, w
amoswap.w zero, zero, 0(t0)
@@ -141,6 +148,7 @@ wait_for_gd_init:
* secondary_hart_loop.
*/
bnez s2, secondary_hart_loop
+#endif
/* Enable cache */
jal icache_enable
diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
index dffcd45bf01..b74bd7e738b 100644
--- a/arch/riscv/include/asm/global_data.h
+++ b/arch/riscv/include/asm/global_data.h
@@ -27,7 +27,9 @@ struct arch_global_data {
#ifdef CONFIG_SMP
struct ipi_data ipi[CONFIG_NR_CPUS];
#endif
+#ifndef CONFIG_XIP
ulong available_harts;
+#endif
};
#include <asm-generic/global_data.h>
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index 1c332db436a..6ae6ebbeafd 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -7,6 +7,7 @@
# Rick Chen, Andes Technology Corporation <rick@andestech.com>
obj-$(CONFIG_CMD_BOOTM) += bootm.o
+obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o
obj-$(CONFIG_CMD_GO) += boot.o
obj-y += cache.o
obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
diff --git a/arch/riscv/lib/asm-offsets.c b/arch/riscv/lib/asm-offsets.c
index f998402bd1b..4fa4fd37147 100644
--- a/arch/riscv/lib/asm-offsets.c
+++ b/arch/riscv/lib/asm-offsets.c
@@ -14,7 +14,9 @@
int main(void)
{
DEFINE(GD_BOOT_HART, offsetof(gd_t, arch.boot_hart));
+#ifndef CONFIG_XIP
DEFINE(GD_AVAILABLE_HARTS, offsetof(gd_t, arch.available_harts));
+#endif
return 0;
}
diff --git a/arch/riscv/lib/image.c b/arch/riscv/lib/image.c
new file mode 100644
index 00000000000..d063beb7dfb
--- /dev/null
+++ b/arch/riscv/lib/image.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Western Digital Corporation or its affiliates.
+ * Authors:
+ * Atish Patra <atish.patra@wdc.com>
+ * Based on arm/lib/image.c
+ */
+
+#include <common.h>
+#include <mapmem.h>
+#include <errno.h>
+#include <linux/sizes.h>
+#include <linux/stddef.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ASCII version of "RISCV" defined in Linux kernel */
+#define LINUX_RISCV_IMAGE_MAGIC 0x5643534952
+
+struct linux_image_h {
+ uint32_t code0; /* Executable code */
+ uint32_t code1; /* Executable code */
+ uint64_t text_offset; /* Image load offset */
+ uint64_t image_size; /* Effective Image size */
+ uint64_t res1; /* reserved */
+ uint64_t res2; /* reserved */
+ uint64_t res3; /* reserved */
+ uint64_t magic; /* Magic number */
+ uint32_t res4; /* reserved */
+ uint32_t res5; /* reserved */
+};
+
+int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
+ bool force_reloc)
+{
+ struct linux_image_h *lhdr;
+
+ lhdr = (struct linux_image_h *)map_sysmem(image, 0);
+
+ if (lhdr->magic != LINUX_RISCV_IMAGE_MAGIC) {
+ puts("Bad Linux RISCV Image magic!\n");
+ return -EINVAL;
+ }
+
+ if (lhdr->image_size == 0) {
+ puts("Image lacks image_size field, error!\n");
+ return -EINVAL;
+ }
+ *size = lhdr->image_size;
+ *relocated_addr = gd->ram_base + lhdr->text_offset;
+
+ unmap_sysmem(lhdr);
+
+ return 0;
+}
diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c
index caa292ccd20..cc66f15567a 100644
--- a/arch/riscv/lib/smp.c
+++ b/arch/riscv/lib/smp.c
@@ -63,9 +63,11 @@ static int send_ipi_many(struct ipi_data *ipi)
continue;
}
+#ifndef CONFIG_XIP
/* skip if hart is not available */
if (!(gd->arch.available_harts & (1 << reg)))
continue;
+#endif
gd->arch.ipi[reg].addr = ipi->addr;
gd->arch.ipi[reg].arg0 = ipi->arg0;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e0520937751..45a533625a6 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -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
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index fec14847cc5..f1afc74fff8 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -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/
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 54668aab240..85fd5e616ea 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -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
diff --git a/arch/x86/cpu/broadwell/Makefile b/arch/x86/cpu/broadwell/Makefile
index d3785aabdf2..52d56c65be8 100644
--- a/arch/x86/cpu/broadwell/Makefile
+++ b/arch/x86/cpu/broadwell/Makefile
@@ -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
diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c
index 232fa40eb53..bb7c3614081 100644
--- a/arch/x86/cpu/broadwell/cpu.c
+++ b/arch/x86/cpu/broadwell/cpu.c
@@ -12,75 +12,15 @@
#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
index 00000000000..c3d4a8d5477
--- /dev/null
+++ b/arch/x86/cpu/broadwell/cpu_from_spl.c
@@ -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
index 00000000000..c1db1845498
--- /dev/null
+++ b/arch/x86/cpu/broadwell/cpu_full.c
@@ -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,
+};
diff --git a/arch/x86/cpu/broadwell/northbridge.c b/arch/x86/cpu/broadwell/northbridge.c
index 3055880bb77..4bcab785560 100644
--- a/arch/x86/cpu/broadwell/northbridge.c
+++ b/arch/x86/cpu/broadwell/northbridge.c
@@ -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)
{
diff --git a/arch/x86/cpu/broadwell/pch.c b/arch/x86/cpu/broadwell/pch.c
index 73d3d3b5154..a48945adf11 100644
--- a/arch/x86/cpu/broadwell/pch.c
+++ b/arch/x86/cpu/broadwell/pch.c
@@ -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[] = {
diff --git a/arch/x86/cpu/broadwell/sdram.c b/arch/x86/cpu/broadwell/sdram.c
index 03a35bcf73f..b31d78c092a 100644
--- a/arch/x86/cpu/broadwell/sdram.c
+++ b/arch/x86/cpu/broadwell/sdram.c
@@ -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 },
{ }
diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
index 3bde44ebf53..90b546e7410 100644
--- a/arch/x86/cpu/i386/cpu.c
+++ b/arch/x86/cpu/i386/cpu.c
@@ -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;
}
diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile
index bf798c287f3..07f27c29ec7 100644
--- a/arch/x86/cpu/intel_common/Makefile
+++ b/arch/x86/cpu/intel_common/Makefile
@@ -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
diff --git a/arch/x86/cpu/intel_common/car.S b/arch/x86/cpu/intel_common/car.S
index 52a77bb2d18..00308dbdef9 100644
--- a/arch/x86/cpu/intel_common/car.S
+++ b/arch/x86/cpu/intel_common/car.S
@@ -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
index 00000000000..a6233c75ce2
--- /dev/null
+++ b/arch/x86/cpu/intel_common/cpu_from_spl.c
@@ -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;
+}
diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c
index ed9bce64168..1cb6cecda9e 100644
--- a/arch/x86/cpu/ivybridge/bd82x6x.c
+++ b/arch/x86/cpu/ivybridge/bd82x6x.c
@@ -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;
}
diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c
index ea64c2ee57e..fefbf8f7282 100644
--- a/arch/x86/cpu/mp_init.c
+++ b/arch/x86/cpu/mp_init.c
@@ -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
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 30fa7def464..4a82add76b7 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -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
diff --git a/arch/x86/cpu/start64.S b/arch/x86/cpu/start64.S
index a78a3316b6d..7be834788b9 100644
--- a/arch/x86/cpu/start64.S
+++ b/arch/x86/cpu/start64.S
@@ -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
index 00000000000..4d4e5d0758d
--- /dev/null
+++ b/arch/x86/cpu/start_from_spl.S
@@ -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
index 00000000000..44b5363a685
--- /dev/null
+++ b/arch/x86/cpu/start_from_tpl.S
@@ -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
diff --git a/arch/x86/cpu/u-boot-spl.lds b/arch/x86/cpu/u-boot-spl.lds
index 4e656dc4e5a..f20c0b810d3 100644
--- a/arch/x86/cpu/u-boot-spl.lds
+++ b/arch/x86/cpu/u-boot-spl.lds
@@ -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
diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c
index 6c063e82009..42abb23a9ed 100644
--- a/arch/x86/cpu/x86_64/cpu.c
+++ b/arch/x86/cpu/x86_64/cpu.c
@@ -61,3 +61,8 @@ int print_cpuinfo(void)
{
return 0;
}
+
+int x86_cpu_reinit_f(void)
+{
+ return 0;
+}
diff --git a/arch/x86/dts/chromebook_samus.dts b/arch/x86/dts/chromebook_samus.dts
index 35211ed81b1..772ea5c91be 100644
--- a/arch/x86/dts/chromebook_samus.dts
+++ b/arch/x86/dts/chromebook_samus.dts
@@ -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;
@@ -94,12 +104,14 @@
};
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>;
@@ -107,9 +119,11 @@
};
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>;
@@ -118,6 +132,7 @@
};
gpio_out_low: gpio-out-low {
+ u-boot,dm-pre-reloc;
mode-gpio;
direction = <PIN_OUTPUT>;
output-value = <0>;
@@ -126,6 +141,7 @@
};
gpio_pirq: gpio-pirq {
+ u-boot,dm-pre-reloc;
mode-gpio;
direction = <PIN_INPUT>;
owner = <OWNER_GPIO>;
@@ -133,6 +149,7 @@
};
soc_gpio@0 {
+ u-boot,dm-pre-reloc;
config =
<0 &gpio_unused 0>, /* unused */
<1 &gpio_unused 0>, /* unused */
@@ -250,8 +267,10 @@
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
@@ -291,6 +310,7 @@
* 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
@@ -326,6 +346,7 @@
};
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
@@ -365,6 +386,7 @@
* 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
@@ -404,6 +426,7 @@
* 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
@@ -443,6 +466,7 @@
* 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
@@ -540,7 +564,7 @@
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;
@@ -559,10 +583,12 @@
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>;
@@ -570,6 +596,7 @@
"jedec,spi-nor";
memory-map = <0xff800000 0x00800000>;
rw-mrc-cache {
+ u-boot,dm-pre-reloc;
label = "rw-mrc-cache";
reg = <0x003e0000 0x00010000>;
};
@@ -609,7 +636,8 @@
#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>;
@@ -630,7 +658,7 @@
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>;
@@ -645,12 +673,19 @@
};
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"
};
};
@@ -668,3 +703,13 @@
};
};
+
+&rtc {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ nvdata {
+ u-boot,dm-pre-reloc;
+ compatible = "google,cmos-nvdata";
+ reg = <0x26>;
+ };
+};
diff --git a/arch/x86/dts/reset.dtsi b/arch/x86/dts/reset.dtsi
index f979d83757c..555d0dd9608 100644
--- a/arch/x86/dts/reset.dtsi
+++ b/arch/x86/dts/reset.dtsi
@@ -1,5 +1,5 @@
/ {
- reset {
+ reset: reset {
compatible = "x86,reset";
u-boot,dm-pre-reloc;
};
diff --git a/arch/x86/dts/rtc.dtsi b/arch/x86/dts/rtc.dtsi
index 1797e042daf..d0bbd84e509 100644
--- a/arch/x86/dts/rtc.dtsi
+++ b/arch/x86/dts/rtc.dtsi
@@ -1,5 +1,5 @@
/ {
- rtc {
+ rtc: rtc {
compatible = "motorola,mc146818";
u-boot,dm-pre-reloc;
reg = <0x70 2>;
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index 1050236330a..daeb168b65f 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -6,86 +6,128 @@
#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
index 00000000000..4d18d59efed
--- /dev/null
+++ b/arch/x86/include/asm/handoff.h
@@ -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
diff --git a/arch/x86/include/asm/mrccache.h b/arch/x86/include/asm/mrccache.h
index 04783cd3292..40fda856ff4 100644
--- a/arch/x86/include/asm/mrccache.h
+++ b/arch/x86/include/asm/mrccache.h
@@ -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 */
diff --git a/arch/x86/include/asm/spl.h b/arch/x86/include/asm/spl.h
index 8cf59d14e7c..27432b28979 100644
--- a/arch/x86/include/asm/spl.h
+++ b/arch/x86/include/asm/spl.h
@@ -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
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 670fcdc0093..c252192bf41 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -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);
/*
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 56fd680033b..436252dd831 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -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
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
index 832b1f901c6..5443a862ab5 100644
--- a/arch/x86/lib/bootm.c
+++ b/arch/x86/lib/bootm.c
@@ -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
diff --git a/arch/x86/lib/fsp/fsp_car.S b/arch/x86/lib/fsp/fsp_car.S
index 48edc8362a7..8c54cea3db4 100644
--- a/arch/x86/lib/fsp/fsp_car.S
+++ b/arch/x86/lib/fsp/fsp_car.S
@@ -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 */
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index 0481f453ca6..ac85278cdf0 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -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);
diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
index 2a8919885b7..be107627b80 100644
--- a/arch/x86/lib/mrccache.c
+++ b/arch/x86/lib/mrccache.c
@@ -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();
+}
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index 7d290740bfa..5d5d1a9ca74 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -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
index 00000000000..492a2d65216
--- /dev/null
+++ b/arch/x86/lib/tpl.c
@@ -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();
+}
diff --git a/board/AndesTech/ax25-ae350/MAINTAINERS b/board/AndesTech/ax25-ae350/MAINTAINERS
index b0a99e4ac40..feed5d1298f 100644
--- a/board/AndesTech/ax25-ae350/MAINTAINERS
+++ b/board/AndesTech/ax25-ae350/MAINTAINERS
@@ -5,3 +5,5 @@ F: board/AndesTech/ax25-ae350/
F: include/configs/ax25-ae350.h
F: configs/ae350_rv32_defconfig
F: configs/ae350_rv64_defconfig
+F: configs/ae350_rv32_xip_defconfig
+F: configs/ae350_rv64_xip_defconfig
diff --git a/board/AndesTech/ax25-ae350/ax25-ae350.c b/board/AndesTech/ax25-ae350/ax25-ae350.c
index d343453f22d..3d65ce7b754 100644
--- a/board/AndesTech/ax25-ae350/ax25-ae350.c
+++ b/board/AndesTech/ax25-ae350/ax25-ae350.c
@@ -67,10 +67,6 @@ ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
void *board_fdt_blob_setup(void)
{
- void **ptr = (void *)&prior_stage_fdt_address;
- if (fdt_magic(*ptr) == FDT_MAGIC)
- return (void *)*ptr;
-
return (void *)CONFIG_SYS_FDT_BASE;
}
diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig
index cf057e7de6a..20ea6dc59b7 100644
--- a/board/emulation/qemu-riscv/Kconfig
+++ b/board/emulation/qemu-riscv/Kconfig
@@ -14,7 +14,8 @@ config SYS_CONFIG_NAME
config SYS_TEXT_BASE
default 0x80000000 if !RISCV_SMODE
- default 0x80200000 if RISCV_SMODE
+ default 0x80200000 if RISCV_SMODE && ARCH_RV64I
+ default 0x80400000 if RISCV_SMODE && ARCH_RV32I
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
diff --git a/board/google/Kconfig b/board/google/Kconfig
index d98a5e818fc..679a0f10239 100644
--- a/board/google/Kconfig
+++ b/board/google/Kconfig
@@ -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"
diff --git a/board/google/chromebook_samus/Kconfig b/board/google/chromebook_samus/Kconfig
index afbfe53deb4..90c23cba1be 100644
--- a/board/google/chromebook_samus/Kconfig
+++ b/board/google/chromebook_samus/Kconfig
@@ -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
diff --git a/board/google/chromebook_samus/MAINTAINERS b/board/google/chromebook_samus/MAINTAINERS
index 5500e46b408..ca4b16500af 100644
--- a/board/google/chromebook_samus/MAINTAINERS
+++ b/board/google/chromebook_samus/MAINTAINERS
@@ -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
diff --git a/board/mikrotik/crs305-1g-4s/.gitignore b/board/mikrotik/crs305-1g-4s/.gitignore
new file mode 100644
index 00000000000..775b9346b85
--- /dev/null
+++ b/board/mikrotik/crs305-1g-4s/.gitignore
@@ -0,0 +1 @@
+kwbimage.cfg
diff --git a/board/mikrotik/crs305-1g-4s/MAINTAINERS b/board/mikrotik/crs305-1g-4s/MAINTAINERS
new file mode 100644
index 00000000000..38234896002
--- /dev/null
+++ b/board/mikrotik/crs305-1g-4s/MAINTAINERS
@@ -0,0 +1,7 @@
+CRS305-1G-4S BOARD
+M: Luka Kovacic <me@lukakovacic.xyz>
+S: Maintained
+F: board/mikrotik/crs305-1g-4s/
+F: include/configs/crs305-1g-4s.h
+F: configs/crs305-1g-4s_defconfig
+F: arch/arm/dts/armada-xp-crs305-1g-4s.dts
diff --git a/board/mikrotik/crs305-1g-4s/Makefile b/board/mikrotik/crs305-1g-4s/Makefile
new file mode 100644
index 00000000000..895331beb86
--- /dev/null
+++ b/board/mikrotik/crs305-1g-4s/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015 Stefan Roese <sr@denx.de>
+
+obj-y := crs305-1g-4s.o
+extra-y := kwbimage.cfg
+
+quiet_cmd_sed = SED $@
+ cmd_sed = sed $(SEDFLAGS_$(@F)) $< >$(dir $<)$(@F)
+
+SEDFLAGS_kwbimage.cfg =-e "s|^BINARY.*|BINARY $(srctree)/$(@D)/binary.0 0000005b 00000068|"
+$(src)/kwbimage.cfg: $(src)/kwbimage.cfg.in include/autoconf.mk \
+ include/config/auto.conf
+ $(call if_changed,sed)
diff --git a/board/mikrotik/crs305-1g-4s/README b/board/mikrotik/crs305-1g-4s/README
new file mode 100644
index 00000000000..f420aabfbf8
--- /dev/null
+++ b/board/mikrotik/crs305-1g-4s/README
@@ -0,0 +1,23 @@
+MikroTik CRS305-1G-4S+IN
+========================
+
+CRS305-1G-4S+IN is a 4x SFP+ switch with a Gigabit Ethernet port for management.
+Specifications:
+ - Marvell Prestera 98DX3236 switch with an integrated ARMv7 CPU
+ - 512 MB DDR3 RAM
+ - UART @ 115200bps
+ - 4x SFP+
+ - Gigabit Ethernet (AR8033)
+ - 16 MB SPI flash (Winbond 25Q128JVSM)
+
+Currently supported hardware:
+ - UART boot (using kwboot) and console
+ - SPI boot, environment and load kernel
+
+Planned:
+ - Gigabit Ethernet support
+
+Getting binary.0
+================
+binary.0 (DDR3 init phase) can be retrieved/extracted from the integrated bootloader on the SPI flash.
+Then binary.0 can be replaced with the extracted blob.
diff --git a/board/mikrotik/crs305-1g-4s/binary.0 b/board/mikrotik/crs305-1g-4s/binary.0
new file mode 100644
index 00000000000..8dd687286a0
--- /dev/null
+++ b/board/mikrotik/crs305-1g-4s/binary.0
@@ -0,0 +1,11 @@
+--------
+WARNING:
+--------
+This file should contain the bin_hdr generated by the original Marvell
+U-Boot implementation. As this is currently not included in this
+U-Boot version, we have added this placeholder, so that the U-Boot
+image can be generated without errors.
+
+If you have a known to be working bin_hdr for your board, then you
+just need to replace this text file here with the binary header
+and recompile U-Boot.
diff --git a/board/mikrotik/crs305-1g-4s/crs305-1g-4s.c b/board/mikrotik/crs305-1g-4s/crs305-1g-4s.c
new file mode 100644
index 00000000000..d1d1f40092d
--- /dev/null
+++ b/board/mikrotik/crs305-1g-4s/crs305-1g-4s.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/gpio.h>
+#include <linux/mbus.h>
+#include <linux/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * These values and defines are taken from the Marvell U-Boot version
+ * "u-boot-2013.01-2016_T1.0.eng_drop_v6"
+ */
+#define DB_DX_AC3_GPP_OUT_ENA_LOW (~(BIT(0) | BIT(2) | BIT(3) | BIT(4) \
+ | BIT(6) | BIT(12) | BIT(13) \
+ | BIT(16) | BIT(17) | BIT(20) \
+ | BIT(29) | BIT(30)))
+#define DB_DX_AC3_GPP_OUT_ENA_MID (~(0))
+#define DB_DX_AC3_GPP_OUT_VAL_LOW (BIT(0) | BIT(2) | BIT(3) | BIT(4) \
+ | BIT(6) | BIT(12) | BIT(13) \
+ | BIT(16) | BIT(17) | BIT(20) \
+ | BIT(29) | BIT(30))
+#define DB_DX_AC3_GPP_OUT_VAL_MID 0x0
+#define DB_DX_AC3_GPP_POL_LOW 0x0
+#define DB_DX_AC3_GPP_POL_MID 0x0
+
+int board_early_init_f(void)
+{
+ /* Configure MPP */
+ writel(0x00142222, MVEBU_MPP_BASE + 0x00);
+ writel(0x11122000, MVEBU_MPP_BASE + 0x04);
+ writel(0x44444004, MVEBU_MPP_BASE + 0x08);
+ writel(0x14444444, MVEBU_MPP_BASE + 0x0c);
+ writel(0x00000001, MVEBU_MPP_BASE + 0x10);
+
+ /*
+ * MVEBU_GPIO0_BASE is the User LED
+ * MVEBU_GPIO1_BASE is the Reset Button (currently not used)
+ */
+
+ /* Set GPP Out value */
+ writel(DB_DX_AC3_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
+ /* writel(DB_DX_AC3_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00); */
+
+ /* Set GPP Polarity */
+ writel(DB_DX_AC3_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
+ /* writel(DB_DX_AC3_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c); */
+
+ /* Set GPP Out Enable */
+ writel(DB_DX_AC3_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
+ /* writel(DB_DX_AC3_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04); */
+
+ return 0;
+}
+
+int board_init(void)
+{
+ /* address of boot parameters */
+ gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+ return 0;
+}
+
+int checkboard(void)
+{
+ puts("Board: " CONFIG_SYS_BOARD "\n");
+
+ return 0;
+}
diff --git a/board/mikrotik/crs305-1g-4s/kwbimage.cfg.in b/board/mikrotik/crs305-1g-4s/kwbimage.cfg.in
new file mode 100644
index 00000000000..2dbbbd0246d
--- /dev/null
+++ b/board/mikrotik/crs305-1g-4s/kwbimage.cfg.in
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2014 Stefan Roese <sr@denx.de>
+#
+
+# Armada XP uses version 1 image format
+VERSION 1
+
+# Boot Media configurations
+BOOT_FROM spi
+
+# Binary Header (bin_hdr) with DDR3 training code
+BINARY board/mikrotik/crs305-1g-4s/binary.0 0000005b 00000068
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index 338f374e56e..bdd1854197a 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -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
diff --git a/board/ti/ks2_evm/mux-k2g.h b/board/ti/ks2_evm/mux-k2g.h
index 89c49f9e4fc..6aa785ea425 100644
--- a/board/ti/ks2_evm/mux-k2g.h
+++ b/board/ti/ks2_evm/mux-k2g.h
@@ -126,22 +126,22 @@ struct pin_cfg k2g_evm_pin_cfg[] = {
{ 71, MODE(0) }, /* MMC1POW TP124 */
/* EMAC */
- { 79, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD1 */
- { 78, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD2 */
+ { 72, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXC */
{ 77, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD3 */
+ { 78, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD2 */
+ { 79, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD1 */
{ 80, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD0 */
- { 94, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD0 */
- { 93, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD1 */
- { 92, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD2 */
- { 91, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD3 */
+ { 81, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXCTL */
{ 85, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXC */
+ { 91, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD3 */
+ { 92, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD2 */
+ { 93, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD1 */
+ { 94, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD0 */
{ 95, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXCTL */
- { 72, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXC */
- { 81, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXCTL */
/* MDIO */
- { 99, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_CLK */
{ 98, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_DATA */
+ { 99, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_CLK */
/* PWM */
{ 73, MODE(4) }, /* SOC_EHRPWM3A */
@@ -350,22 +350,22 @@ struct pin_cfg k2g_ice_evm_pin_cfg[] = {
{ 135, MODE(0) }, /* SOC_QSPI_CSN0 */
/* EMAC */
- { 79, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD1 */
- { 78, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD2 */
+ { 72, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXC */
{ 77, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD3 */
+ { 78, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD2 */
+ { 79, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD1 */
{ 80, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD0 */
- { 94, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD0 */
- { 93, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD1 */
- { 92, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD2 */
- { 91, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD3 */
+ { 81, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXCTL */
{ 85, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXC */
+ { 91, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD3 */
+ { 92, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD2 */
+ { 93, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD1 */
+ { 94, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD0 */
{ 95, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXCTL */
- { 72, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXC */
- { 81, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXCTL */
/* MDIO */
- { 99, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_CLK */
{ 98, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_DATA */
+ { 99, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_CLK */
{ MAX_PIN_N, }
};
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 069e0ea7300..4e11e0f404c 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -223,7 +223,7 @@ config CMD_BOOTZ
config CMD_BOOTI
bool "booti"
- depends on ARM64
+ depends on ARM64 || RISCV
default y
help
Boot an AArch64 Linux Kernel image from memory.
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index f1d7d8bc663..52116b308cc 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -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) {
diff --git a/cmd/booti.c b/cmd/booti.c
index 04353b68ecc..c36b0235df8 100644
--- a/cmd/booti.c
+++ b/cmd/booti.c
@@ -77,7 +77,11 @@ int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
bootm_disable_interrupts();
images.os.os = IH_OS_LINUX;
+#ifdef CONFIG_RISCV_SMODE
+ images.os.arch = IH_ARCH_RISCV;
+#elif CONFIG_ARM64
images.os.arch = IH_ARCH_ARM64;
+#endif
ret = do_bootm_states(cmdtp, flag, argc, argv,
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
BOOTM_STATE_RAMDISK |
@@ -92,7 +96,7 @@ int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#ifdef CONFIG_SYS_LONGHELP
static char booti_help_text[] =
"[addr [initrd[:size]] [fdt]]\n"
- " - boot arm64 Linux Image stored in memory\n"
+ " - boot Linux 'Image' stored at 'addr'\n"
"\tThe argument 'initrd' is optional and specifies the address\n"
"\tof an initrd in memory. The optional parameter ':size' allows\n"
"\tspecifying the size of a RAW initrd.\n"
@@ -107,5 +111,5 @@ static char booti_help_text[] =
U_BOOT_CMD(
booti, CONFIG_SYS_MAXARGS, 1, do_booti,
- "boot arm64 Linux Image image from memory", booti_help_text
+ "boot Linux kernel 'Image' format from memory", booti_help_text
);
diff --git a/cmd/mdio.c b/cmd/mdio.c
index 184868063ab..efe8c9ef095 100644
--- a/cmd/mdio.c
+++ b/cmd/mdio.c
@@ -39,21 +39,24 @@ static int extract_range(char *input, int *plo, int *phi)
return 0;
}
-static int mdio_write_ranges(struct phy_device *phydev, struct mii_dev *bus,
+static int mdio_write_ranges(struct mii_dev *bus,
int addrlo,
int addrhi, int devadlo, int devadhi,
int reglo, int reghi, unsigned short data,
int extended)
{
+ struct phy_device *phydev;
int addr, devad, reg;
int err = 0;
for (addr = addrlo; addr <= addrhi; addr++) {
+ phydev = bus->phymap[addr];
+
for (devad = devadlo; devad <= devadhi; devad++) {
for (reg = reglo; reg <= reghi; reg++) {
if (!extended)
- err = bus->write(bus, addr, devad,
- reg, data);
+ err = phy_write_mmd(phydev, devad,
+ reg, data);
else
err = phydev->drv->writeext(phydev,
addr, devad, reg, data);
@@ -68,15 +71,17 @@ err_out:
return err;
}
-static int mdio_read_ranges(struct phy_device *phydev, struct mii_dev *bus,
+static int mdio_read_ranges(struct mii_dev *bus,
int addrlo,
int addrhi, int devadlo, int devadhi,
int reglo, int reghi, int extended)
{
int addr, devad, reg;
+ struct phy_device *phydev;
printf("Reading from bus %s\n", bus->name);
for (addr = addrlo; addr <= addrhi; addr++) {
+ phydev = bus->phymap[addr];
printf("PHY at address %x:\n", addr);
for (devad = devadlo; devad <= devadhi; devad++) {
@@ -84,7 +89,7 @@ static int mdio_read_ranges(struct phy_device *phydev, struct mii_dev *bus,
int val;
if (!extended)
- val = bus->read(bus, addr, devad, reg);
+ val = phy_read_mmd(phydev, devad, reg);
else
val = phydev->drv->readext(phydev, addr,
devad, reg);
@@ -222,14 +227,14 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
bus = phydev->bus;
extended = 1;
} else {
- return -1;
+ return CMD_RET_FAILURE;
}
if (!phydev->drv ||
(!phydev->drv->writeext && (op[0] == 'w')) ||
(!phydev->drv->readext && (op[0] == 'r'))) {
puts("PHY does not have extended functions\n");
- return -1;
+ return CMD_RET_FAILURE;
}
}
}
@@ -242,13 +247,13 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (pos > 1)
if (extract_reg_range(argv[pos--], &devadlo, &devadhi,
&reglo, &reghi))
- return -1;
+ return CMD_RET_FAILURE;
default:
if (pos > 1)
if (extract_phy_range(&argv[2], pos - 1, &bus,
&phydev, &addrlo, &addrhi))
- return -1;
+ return CMD_RET_FAILURE;
break;
}
@@ -264,12 +269,12 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
switch (op[0]) {
case 'w':
- mdio_write_ranges(phydev, bus, addrlo, addrhi, devadlo, devadhi,
+ mdio_write_ranges(bus, addrlo, addrhi, devadlo, devadhi,
reglo, reghi, data, extended);
break;
case 'r':
- mdio_read_ranges(phydev, bus, addrlo, addrhi, devadlo, devadhi,
+ mdio_read_ranges(bus, addrlo, addrhi, devadlo, devadhi,
reglo, reghi, extended);
break;
}
diff --git a/configs/Cubietruck_plus_defconfig b/configs/Cubietruck_plus_defconfig
index a45ca1680ed..ef6a9d5d370 100644
--- a/configs/Cubietruck_plus_defconfig
+++ b/configs/Cubietruck_plus_defconfig
@@ -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
diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig
index b57e4534205..5174e287230 100644
--- a/configs/Sinovoip_BPI_M3_defconfig
+++ b/configs/Sinovoip_BPI_M3_defconfig
@@ -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/ae350_rv32_defconfig b/configs/ae350_rv32_defconfig
index 2f759e4d2c8..a31027016b5 100644
--- a/configs/ae350_rv32_defconfig
+++ b/configs/ae350_rv32_defconfig
@@ -14,7 +14,7 @@ CONFIG_CMD_SF_TEST=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_BOOTP_PREFER_SERVERIP=y
CONFIG_CMD_CACHE=y
-CONFIG_OF_BOARD=y
+CONFIG_OF_PRIOR_STAGE=y
CONFIG_DEFAULT_DEVICE_TREE="ae350_32"
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/ae350_rv32_xip_defconfig b/configs/ae350_rv32_xip_defconfig
new file mode 100644
index 00000000000..07f1ecc2fc6
--- /dev/null
+++ b/configs/ae350_rv32_xip_defconfig
@@ -0,0 +1,37 @@
+CONFIG_RISCV=y
+CONFIG_SYS_TEXT_BASE=0x80000000
+CONFIG_XIP=y
+CONFIG_TARGET_AX25_AE350=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_OF_SEPARATE=y
+CONFIG_DEFAULT_DEVICE_TREE="ae350_32"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_CFI_FLASH=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH=y
+CONFIG_SF_DEFAULT_MODE=0x0
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y
diff --git a/configs/ae350_rv64_defconfig b/configs/ae350_rv64_defconfig
index 287769d5b18..d425252ec8e 100644
--- a/configs/ae350_rv64_defconfig
+++ b/configs/ae350_rv64_defconfig
@@ -15,7 +15,7 @@ CONFIG_CMD_SF_TEST=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_BOOTP_PREFER_SERVERIP=y
CONFIG_CMD_CACHE=y
-CONFIG_OF_BOARD=y
+CONFIG_OF_PRIOR_STAGE=y
CONFIG_DEFAULT_DEVICE_TREE="ae350_64"
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/ae350_rv64_xip_defconfig b/configs/ae350_rv64_xip_defconfig
new file mode 100644
index 00000000000..28afd81fc8a
--- /dev/null
+++ b/configs/ae350_rv64_xip_defconfig
@@ -0,0 +1,38 @@
+CONFIG_RISCV=y
+CONFIG_SYS_TEXT_BASE=0x80000000
+CONFIG_XIP=y
+CONFIG_TARGET_AX25_AE350=y
+CONFIG_ARCH_RV64I=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_OF_SEPARATE=y
+CONFIG_DEFAULT_DEVICE_TREE="ae350_64"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_CFI_FLASH=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH=y
+CONFIG_SF_DEFAULT_MODE=0x0
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y
diff --git a/configs/beelink_gs1_defconfig b/configs/beelink_gs1_defconfig
new file mode 100644
index 00000000000..ef4dd295491
--- /dev/null
+++ b/configs/beelink_gs1_defconfig
@@ -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
diff --git a/configs/chromebook_samus_defconfig b/configs/chromebook_samus_defconfig
index d0749f14fc9..91d9fdf9615 100644
--- a/configs/chromebook_samus_defconfig
+++ b/configs/chromebook_samus_defconfig
@@ -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
index 00000000000..40f6bb9830f
--- /dev/null
+++ b/configs/chromebook_samus_tpl_defconfig
@@ -0,0 +1,83 @@
+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_TPL_SYSRESET=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/clearfog_defconfig b/configs/clearfog_defconfig
index ee3fb149e46..1806d950159 100644
--- a/configs/clearfog_defconfig
+++ b/configs/clearfog_defconfig
@@ -15,6 +15,7 @@ CONFIG_SPL=y
CONFIG_DEBUG_UART_BASE=0xd0012000
CONFIG_DEBUG_UART_CLOCK=250000000
CONFIG_DEBUG_UART=y
+CONFIG_AHCI=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_BOOTDELAY=3
CONFIG_SYS_CONSOLE_INFO_QUIET=y
@@ -40,12 +41,13 @@ CONFIG_DEFAULT_DEVICE_TREE="armada-388-clearfog"
CONFIG_ENV_IS_IN_MMC=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_SCSI_AHCI=y
+CONFIG_AHCI_MVEBU=y
CONFIG_DM_GPIO=y
CONFIG_DM_PCA953X=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_MVTWSI=y
CONFIG_SUPPORT_EMMC_BOOT=y
+CONFIG_DM_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SDMA=y
CONFIG_MMC_SDHCI_MV=y
diff --git a/configs/crs305-1g-4s_defconfig b/configs/crs305-1g-4s_defconfig
new file mode 100644
index 00000000000..66ba04ede85
--- /dev/null
+++ b/configs/crs305-1g-4s_defconfig
@@ -0,0 +1,52 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_TEXT_BASE=0x00800000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TARGET_CRS305_1G_4S=y
+CONFIG_BUILD_TARGET="u-boot.kwb"
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_SYS_ALT_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_I2C=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+# CONFIG_CMD_USB is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_UBI=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-xp-crs305-1g-4s"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_BLK=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+# CONFIG_MMC is not set
+CONFIG_MTD=y
+CONFIG_MTD_DEVICE=y
+# CONFIG_NAND is not set
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
+# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
+CONFIG_SYS_NS16550=y
+CONFIG_KIRKWOOD_SPI=y
+# CONFIG_USB is not set
+# CONFIG_DM_USB is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_HOST_ETHER is not set
diff --git a/configs/db-88f6720_defconfig b/configs/db-88f6720_defconfig
index 25421407e27..c1a430cf3bd 100644
--- a/configs/db-88f6720_defconfig
+++ b/configs/db-88f6720_defconfig
@@ -44,6 +44,7 @@ CONFIG_USE_ENV_SPI_MAX_HZ=y
CONFIG_ENV_SPI_MAX_HZ=50000000
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_BLK=y
CONFIG_MISC=y
# CONFIG_MMC is not set
CONFIG_SPI_FLASH=y
diff --git a/configs/db-88f6820-gp_defconfig b/configs/db-88f6820-gp_defconfig
index 6ee3151861e..b8f036e317b 100644
--- a/configs/db-88f6820-gp_defconfig
+++ b/configs/db-88f6820-gp_defconfig
@@ -13,6 +13,7 @@ CONFIG_DEBUG_UART_CLOCK=250000000
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI_SUPPORT=y
CONFIG_DEBUG_UART=y
+CONFIG_AHCI=y
CONFIG_BOOTDELAY=3
CONFIG_SYS_CONSOLE_INFO_QUIET=y
# CONFIG_DISPLAY_BOARDINFO is not set
@@ -47,7 +48,8 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_USE_ENV_SPI_MAX_HZ=y
CONFIG_ENV_SPI_MAX_HZ=50000000
CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_SCSI_AHCI=y
+CONFIG_AHCI_MVEBU=y
+CONFIG_DM_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SDMA=y
CONFIG_MMC_SDHCI_MV=y
diff --git a/configs/teres_i_defconfig b/configs/teres_i_defconfig
new file mode 100644
index 00000000000..421a8d3d408
--- /dev/null
+++ b/configs/teres_i_defconfig
@@ -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
diff --git a/doc/README.x86 b/doc/README.x86
index fa49cb8b8a2..8e0a3f36edf 100644
--- a/doc/README.x86
+++ b/doc/README.x86
@@ -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:
diff --git a/doc/device-tree-bindings/net/micrel-ksz90x1.txt b/doc/device-tree-bindings/net/micrel-ksz90x1.txt
index 307f53f726c..a214d35fc90 100644
--- a/doc/device-tree-bindings/net/micrel-ksz90x1.txt
+++ b/doc/device-tree-bindings/net/micrel-ksz90x1.txt
@@ -14,6 +14,33 @@ KSZ9021:
value is 0, the maximum value is 1800, and it is incremented by 120ps
steps.
+ The KSZ9021 hardware supports a range of skew values from negative to
+ positive, where the specific range is property dependent. All values
+ specified in the devicetree are offset by the minimum value so they
+ can be represented as positive integers in the devicetree since it's
+ difficult to represent a negative number in the devictree.
+
+ The following 4-bit values table applies to all the skew properties:
+
+ Pad Skew Value Delay (ps) Devicetree Value
+ ------------------------------------------------------
+ 0000 -840ps 0
+ 0001 -720ps 120
+ 0010 -600ps 240
+ 0011 -480ps 360
+ 0100 -360ps 480
+ 0101 -240ps 600
+ 0110 -120ps 720
+ 0111 0ps 840
+ 1000 120ps 960
+ 1001 240ps 1080
+ 1010 360ps 1200
+ 1011 480ps 1320
+ 1100 600ps 1440
+ 1101 720ps 1560
+ 1110 840ps 1680
+ 1111 960ps 1800
+
Optional properties:
- rxc-skew-ps : Skew control of RXC pad
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 844b87cc337..79b3b0494c6 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -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)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
index e1b5f8e6a99..2d47ebc6b1e 100644
--- a/drivers/clk/sifive/fu540-prci.c
+++ b/drivers/clk/sifive/fu540-prci.c
@@ -28,10 +28,10 @@
* - 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>
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 785f5c3acf7..cc0c031e0d7 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -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);
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
index 565de040fe9..382f8262863 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -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,
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c
index 73b7ba29dfd..34253e39249 100644
--- a/drivers/net/ldpaa_eth/ldpaa_eth.c
+++ b/drivers/net/ldpaa_eth/ldpaa_eth.c
@@ -1074,6 +1074,7 @@ int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if)
priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
if (!priv) {
printf("ldpaa_eth_priv malloc() failed\n");
+ free(net_dev);
return -ENOMEM;
}
memset(priv, 0, sizeof(struct ldpaa_eth_priv));
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3dc0822d9c2..631b52b1cfe 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -202,6 +202,26 @@ config RTL8211X_PHY_FORCE_MASTER
If unsure, say N.
+config RTL8211F_PHY_FORCE_EEE_RXC_ON
+ bool "Ethernet PHY RTL8211F: do not stop receiving the xMII clock during LPI"
+ depends on PHY_REALTEK
+ default n
+ help
+ The IEEE 802.3az-2010 (EEE) standard provides a protocol to coordinate
+ transitions to/from a lower power consumption level (Low Power Idle
+ mode) based on link utilization. When no packets are being
+ transmitted, the system goes to Low Power Idle mode to save power.
+
+ Under particular circumstances this setting can cause issues where
+ the PHY is unable to transmit or receive any packet when in LPI mode.
+ The problem is caused when the PHY is configured to stop receiving
+ the xMII clock while it is signaling LPI. For some PHYs the bit
+ configuring this behavior is set by the Linux kernel, causing the
+ issue in U-Boot on reboot if the PHY retains the register value.
+
+ Default n, which means that the PHY state is not changed. To work
+ around the issues, change this setting to y.
+
config PHY_SMSC
bool "Microchip(SMSC) Ethernet PHYs support"
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index 12df09877de..5c3298d612c 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -303,9 +303,14 @@ int aquantia_config(struct phy_device *phydev)
AQUANTIA_SYSTEM_INTERFACE_SR);
/* If SI is USXGMII then start USXGMII autoneg */
if ((val & AQUANTIA_SI_IN_USE_MASK) == AQUANTIA_SI_USXGMII) {
+ reg_val1 = phy_read(phydev, MDIO_MMD_PHYXS,
+ AQUANTIA_VENDOR_PROVISIONING_REG);
+
+ reg_val1 |= AQUANTIA_USX_AUTONEG_CONTROL_ENA;
+
phy_write(phydev, MDIO_MMD_PHYXS,
AQUANTIA_VENDOR_PROVISIONING_REG,
- AQUANTIA_USX_AUTONEG_CONTROL_ENA);
+ reg_val1);
printf("%s: system interface USXGMII\n",
phydev->dev->name);
} else {
diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c
index 63e7b0242b9..8dec9f23678 100644
--- a/drivers/net/phy/micrel_ksz90x1.c
+++ b/drivers/net/phy/micrel_ksz90x1.c
@@ -33,10 +33,14 @@
#define CTRL1000_CONFIG_MASTER (1 << 11)
#define CTRL1000_MANUAL_CONFIG (1 << 12)
+#define KSZ9021_PS_TO_REG 120
+
/* KSZ9031 PHY Registers */
#define MII_KSZ9031_MMD_ACCES_CTRL 0x0d
#define MII_KSZ9031_MMD_REG_DATA 0x0e
+#define KSZ9031_PS_TO_REG 60
+
static int ksz90xx_startup(struct phy_device *phydev)
{
unsigned phy_ctl;
@@ -102,20 +106,28 @@ static const struct ksz90x1_reg_field ksz9031_clk_grp[] = {
};
static int ksz90x1_of_config_group(struct phy_device *phydev,
- struct ksz90x1_ofcfg *ofcfg)
+ struct ksz90x1_ofcfg *ofcfg,
+ int ps_to_regval)
{
struct udevice *dev = phydev->dev;
struct phy_driver *drv = phydev->drv;
- const int ps_to_regval = 60;
int val[4];
int i, changed = 0, offset, max;
u16 regval = 0;
+ ofnode node;
if (!drv || !drv->writeext)
return -EOPNOTSUPP;
+ /* Look for a PHY node under the Ethernet node */
+ node = dev_read_subnode(dev, "ethernet-phy");
+ if (!ofnode_valid(node)) {
+ /* No node found, look in the Ethernet node */
+ node = dev_ofnode(dev);
+ }
+
for (i = 0; i < ofcfg->grpsz; i++) {
- val[i] = dev_read_u32_default(dev, ofcfg->grp[i].name, ~0);
+ val[i] = ofnode_read_u32_default(node, ofcfg->grp[i].name, ~0);
offset = ofcfg->grp[i].off;
if (val[i] == -1) {
/* Default register value for KSZ9021 */
@@ -148,7 +160,8 @@ static int ksz9021_of_config(struct phy_device *phydev)
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
- ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
+ ret = ksz90x1_of_config_group(phydev, &ofcfg[i],
+ KSZ9021_PS_TO_REG);
if (ret)
return ret;
}
@@ -167,7 +180,8 @@ static int ksz9031_of_config(struct phy_device *phydev)
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
- ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
+ ret = ksz90x1_of_config_group(phydev, &ofcfg[i],
+ KSZ9031_PS_TO_REG);
if (ret)
return ret;
}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 4e8d2943eee..c1c1af9abdb 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -462,6 +462,18 @@ static LIST_HEAD(phy_drivers);
int phy_init(void)
{
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+ /*
+ * The pointers inside phy_drivers also needs to be updated incase of
+ * manual reloc, without which these points to some invalid
+ * pre reloc address and leads to invalid accesses, hangs.
+ */
+ struct list_head *head = &phy_drivers;
+
+ head->next = (void *)head->next + gd->reloc_off;
+ head->prev = (void *)head->prev + gd->reloc_off;
+#endif
+
#ifdef CONFIG_B53_SWITCH
phy_b53_init();
#endif
@@ -549,6 +561,10 @@ int phy_register(struct phy_driver *drv)
drv->readext += gd->reloc_off;
if (drv->writeext)
drv->writeext += gd->reloc_off;
+ if (drv->read_mmd)
+ drv->read_mmd += gd->reloc_off;
+ if (drv->write_mmd)
+ drv->write_mmd += gd->reloc_off;
#endif
return 0;
}
@@ -655,7 +671,10 @@ static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
dev->drv = get_phy_driver(dev, interface);
- phy_probe(dev);
+ if (phy_probe(dev)) {
+ printf("%s, PHY probe failed\n", __func__);
+ return NULL;
+ }
if (addr >= 0 && addr < PHY_MAX_ADDR)
bus->phymap[addr] = dev;
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index dd45e11b3ad..8f1d7596325 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -12,6 +12,7 @@
#define PHY_RTL8211x_FORCE_MASTER BIT(1)
#define PHY_RTL8211E_PINE64_GIGABIT_FIX BIT(2)
+#define PHY_RTL8211F_FORCE_EEE_RXC_ON BIT(3)
#define PHY_AUTONEGOTIATE_TIMEOUT 5000
@@ -102,6 +103,15 @@ static int rtl8211e_probe(struct phy_device *phydev)
return 0;
}
+static int rtl8211f_probe(struct phy_device *phydev)
+{
+#ifdef CONFIG_RTL8211F_PHY_FORCE_EEE_RXC_ON
+ phydev->flags |= PHY_RTL8211F_FORCE_EEE_RXC_ON;
+#endif
+
+ return 0;
+}
+
/* RealTek RTL8211x */
static int rtl8211x_config(struct phy_device *phydev)
{
@@ -151,6 +161,14 @@ static int rtl8211f_config(struct phy_device *phydev)
{
u16 reg;
+ if (phydev->flags & PHY_RTL8211F_FORCE_EEE_RXC_ON) {
+ unsigned int reg;
+
+ reg = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1);
+ reg &= ~MDIO_PCS_CTRL1_CLKSTOP_EN;
+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+ }
+
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
phy_write(phydev, MDIO_DEVAD_NONE,
@@ -360,6 +378,7 @@ static struct phy_driver RTL8211F_driver = {
.uid = 0x1cc916,
.mask = 0xffffff,
.features = PHY_GBIT_FEATURES,
+ .probe = &rtl8211f_probe,
.config = &rtl8211f_config,
.startup = &rtl8211f_startup,
.shutdown = &genphy_shutdown,
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c
index 6db6edd0d0c..6ac890a7f5c 100644
--- a/drivers/net/phy/ti.c
+++ b/drivers/net/phy/ti.c
@@ -73,16 +73,6 @@
#define MII_DP83867_CFG2_SPEEDOPT_INTLOW 0x2000
#define MII_DP83867_CFG2_MASK 0x003F
-#define MII_MMD_CTRL 0x0d /* MMD Access Control Register */
-#define MII_MMD_DATA 0x0e /* MMD Access Data Register */
-
-/* MMD Access Control register fields */
-#define MII_MMD_CTRL_DEVAD_MASK 0x1f /* Mask MMD DEVAD*/
-#define MII_MMD_CTRL_ADDR 0x0000 /* Address */
-#define MII_MMD_CTRL_NOINCR 0x4000 /* no post increment */
-#define MII_MMD_CTRL_INCR_RDWT 0x8000 /* post increment on reads & writes */
-#define MII_MMD_CTRL_INCR_ON_WT 0xC000 /* post increment on writes only */
-
/* User setting - can be taken from DTS */
#define DEFAULT_RX_ID_DELAY DP83867_RGMIIDCTL_2_25_NS
#define DEFAULT_TX_ID_DELAY DP83867_RGMIIDCTL_2_75_NS
@@ -116,88 +106,20 @@ struct dp83867_private {
int clk_output_sel;
};
-/**
- * phy_read_mmd_indirect - reads data from the MMD registers
- * @phydev: The PHY device bus
- * @prtad: MMD Address
- * @devad: MMD DEVAD
- * @addr: PHY address on the MII bus
- *
- * Description: it reads data from the MMD registers (clause 22 to access to
- * clause 45) of the specified phy address.
- * To read these registers we have:
- * 1) Write reg 13 // DEVAD
- * 2) Write reg 14 // MMD Address
- * 3) Write reg 13 // MMD Data Command for MMD DEVAD
- * 3) Read reg 14 // Read MMD data
- */
-int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
- int devad, int addr)
-{
- int value = -1;
-
- /* Write the desired MMD Devad */
- phy_write(phydev, addr, MII_MMD_CTRL, devad);
-
- /* Write the desired MMD register address */
- phy_write(phydev, addr, MII_MMD_DATA, prtad);
-
- /* Select the Function : DATA with no post increment */
- phy_write(phydev, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
-
- /* Read the content of the MMD's selected register */
- value = phy_read(phydev, addr, MII_MMD_DATA);
- return value;
-}
-
-/**
- * phy_write_mmd_indirect - writes data to the MMD registers
- * @phydev: The PHY device
- * @prtad: MMD Address
- * @devad: MMD DEVAD
- * @addr: PHY address on the MII bus
- * @data: data to write in the MMD register
- *
- * Description: Write data from the MMD registers of the specified
- * phy address.
- * To write these registers we have:
- * 1) Write reg 13 // DEVAD
- * 2) Write reg 14 // MMD Address
- * 3) Write reg 13 // MMD Data Command for MMD DEVAD
- * 3) Write reg 14 // Write MMD data
- */
-void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
- int devad, int addr, u32 data)
-{
- /* Write the desired MMD Devad */
- phy_write(phydev, addr, MII_MMD_CTRL, devad);
-
- /* Write the desired MMD register address */
- phy_write(phydev, addr, MII_MMD_DATA, prtad);
-
- /* Select the Function : DATA with no post increment */
- phy_write(phydev, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
-
- /* Write the data into MMD's selected register */
- phy_write(phydev, addr, MII_MMD_DATA, data);
-}
-
static int dp83867_config_port_mirroring(struct phy_device *phydev)
{
struct dp83867_private *dp83867 =
(struct dp83867_private *)phydev->priv;
u16 val;
- val = phy_read_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR,
- phydev->addr);
+ val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
if (dp83867->port_mirroring == DP83867_PORT_MIRRORING_EN)
val |= DP83867_CFG4_PORT_MIRROR_EN;
else
val &= ~DP83867_CFG4_PORT_MIRROR_EN;
- phy_write_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR,
- phydev->addr, val);
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
return 0;
}
@@ -257,13 +179,13 @@ static int dp83867_of_init(struct phy_device *phydev)
/* Clock output selection if muxing property is set */
if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) {
- val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
- DP83867_DEVADDR, phydev->addr);
+ val = phy_read_mmd(phydev, DP83867_DEVADDR,
+ DP83867_IO_MUX_CFG);
val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK;
val |= (dp83867->clk_output_sel <<
DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT);
- phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
- DP83867_DEVADDR, phydev->addr, val);
+ phy_write_mmd(phydev, DP83867_DEVADDR,
+ DP83867_IO_MUX_CFG, val);
}
return 0;
@@ -308,11 +230,11 @@ static int dp83867_config(struct phy_device *phydev)
/* Mode 1 or 2 workaround */
if (dp83867->rxctrl_strap_quirk) {
- val = phy_read_mmd_indirect(phydev, DP83867_CFG4,
- DP83867_DEVADDR, phydev->addr);
+ val = phy_read_mmd(phydev, DP83867_DEVADDR,
+ DP83867_CFG4);
val &= ~BIT(7);
- phy_write_mmd_indirect(phydev, DP83867_CFG4,
- DP83867_DEVADDR, phydev->addr, val);
+ phy_write_mmd(phydev, DP83867_DEVADDR,
+ DP83867_CFG4, val);
}
if (phy_interface_is_rgmii(phydev)) {
@@ -332,8 +254,8 @@ static int dp83867_config(struct phy_device *phydev)
* register's bit 11 (marked as RESERVED).
*/
- bs = phy_read_mmd_indirect(phydev, DP83867_STRAP_STS1,
- DP83867_DEVADDR, phydev->addr);
+ bs = phy_read_mmd(phydev, DP83867_DEVADDR,
+ DP83867_STRAP_STS1);
val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL);
if (bs & DP83867_STRAP_STS1_RESERVED) {
val &= ~DP83867_PHYCR_RESERVED_MASK;
@@ -354,8 +276,8 @@ static int dp83867_config(struct phy_device *phydev)
MII_DP83867_CFG2_SPEEDOPT_INTLOW);
phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_CFG2, cfg2);
- phy_write_mmd_indirect(phydev, DP83867_RGMIICTL,
- DP83867_DEVADDR, phydev->addr, 0x0);
+ phy_write_mmd(phydev, DP83867_DEVADDR,
+ DP83867_RGMIICTL, 0x0);
phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
DP83867_PHYCTRL_SGMIIEN |
@@ -367,8 +289,8 @@ static int dp83867_config(struct phy_device *phydev)
}
if (phy_interface_is_rgmii(phydev)) {
- val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL,
- DP83867_DEVADDR, phydev->addr);
+ val = phy_read_mmd(phydev, DP83867_DEVADDR,
+ DP83867_RGMIICTL);
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
val |= (DP83867_RGMII_TX_CLK_DELAY_EN |
@@ -380,26 +302,24 @@ static int dp83867_config(struct phy_device *phydev)
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
val |= DP83867_RGMII_RX_CLK_DELAY_EN;
- phy_write_mmd_indirect(phydev, DP83867_RGMIICTL,
- DP83867_DEVADDR, phydev->addr, val);
+ phy_write_mmd(phydev, DP83867_DEVADDR,
+ DP83867_RGMIICTL, val);
delay = (dp83867->rx_id_delay |
(dp83867->tx_id_delay << DP83867_RGMII_TX_CLK_DELAY_SHIFT));
- phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL,
- DP83867_DEVADDR, phydev->addr, delay);
+ phy_write_mmd(phydev, DP83867_DEVADDR,
+ DP83867_RGMIIDCTL, delay);
if (dp83867->io_impedance >= 0) {
- val = phy_read_mmd_indirect(phydev,
- DP83867_IO_MUX_CFG,
- DP83867_DEVADDR,
- phydev->addr);
+ val = phy_read_mmd(phydev,
+ DP83867_DEVADDR,
+ DP83867_IO_MUX_CFG);
val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
val |= dp83867->io_impedance &
DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
- phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
- DP83867_DEVADDR, phydev->addr,
- val);
+ phy_write_mmd(phydev, DP83867_DEVADDR,
+ DP83867_IO_MUX_CFG, val);
}
}
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index 98bd7a58232..c0a440886e2 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -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;
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index 7d9b75c2c45..2cede1211bb 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -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,
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 102fb91fffd..957efb3984b 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -147,6 +147,14 @@ config MESON_GXL_USB_PHY
This is the generic phy driver for the Amlogic Meson GXL
USB2 and USB3 PHYS.
+config MESON_G12A_USB_PHY
+ bool "Amlogic Meson G12A USB PHYs"
+ depends on PHY && ARCH_MESON && MESON_G12A
+ imply REGMAP
+ help
+ This is the generic phy driver for the Amlogic Meson G12A
+ USB2 and USB3 PHYS.
+
config MSM8916_USB_PHY
bool "Qualcomm MSM8916 USB PHY support"
depends on PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index b55917bce1a..90646ca55b9 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
obj-$(CONFIG_PHY_RCAR_GEN3) += phy-rcar-gen3.o
obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o
+obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o
obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o
diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
new file mode 100644
index 00000000000..ad1a77fcfca
--- /dev/null
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Meson G12A USB2 PHY driver
+ *
+ * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ * Copyright (C) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstron@baylibre.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <bitfield.h>
+#include <dm.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <regmap.h>
+#include <power/regulator.h>
+#include <reset.h>
+#include <clk.h>
+
+#include <linux/bitops.h>
+#include <linux/compat.h>
+
+#define PHY_CTRL_R0 0x0
+#define PHY_CTRL_R1 0x4
+#define PHY_CTRL_R2 0x8
+#define PHY_CTRL_R3 0xc
+#define PHY_CTRL_R4 0x10
+#define PHY_CTRL_R5 0x14
+#define PHY_CTRL_R6 0x18
+#define PHY_CTRL_R7 0x1c
+#define PHY_CTRL_R8 0x20
+#define PHY_CTRL_R9 0x24
+#define PHY_CTRL_R10 0x28
+#define PHY_CTRL_R11 0x2c
+#define PHY_CTRL_R12 0x30
+#define PHY_CTRL_R13 0x34
+#define PHY_CTRL_R14 0x38
+#define PHY_CTRL_R15 0x3c
+#define PHY_CTRL_R16 0x40
+#define PHY_CTRL_R17 0x44
+#define PHY_CTRL_R18 0x48
+#define PHY_CTRL_R19 0x4c
+#define PHY_CTRL_R20 0x50
+#define PHY_CTRL_R21 0x54
+#define PHY_CTRL_R22 0x58
+#define PHY_CTRL_R23 0x5c
+
+#define RESET_COMPLETE_TIME 1000
+#define PLL_RESET_COMPLETE_TIME 100
+
+struct phy_meson_g12a_usb2_priv {
+ struct regmap *regmap;
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ struct udevice *phy_supply;
+#endif
+#if CONFIG_IS_ENABLED(CLK)
+ struct clk clk;
+#endif
+ struct reset_ctl reset;
+};
+
+
+static int phy_meson_g12a_usb2_power_on(struct phy *phy)
+{
+ struct udevice *dev = phy->dev;
+ struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ if (priv->phy_supply) {
+ int ret = regulator_set_enable(priv->phy_supply, true);
+ if (ret)
+ return ret;
+ }
+#endif
+
+ return 0;
+}
+
+static int phy_meson_g12a_usb2_power_off(struct phy *phy)
+{
+ struct udevice *dev = phy->dev;
+ struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ if (priv->phy_supply) {
+ int ret = regulator_set_enable(priv->phy_supply, false);
+ if (ret) {
+ pr_err("Error disabling PHY supply\n");
+ return ret;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+static int phy_meson_g12a_usb2_init(struct phy *phy)
+{
+ struct udevice *dev = phy->dev;
+ struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = reset_assert(&priv->reset);
+ udelay(1);
+ ret |= reset_deassert(&priv->reset);
+ if (ret)
+ return ret;
+
+ udelay(RESET_COMPLETE_TIME);
+
+ /* usb2_otg_aca_en == 0 */
+ regmap_update_bits(priv->regmap, PHY_CTRL_R21, BIT(2), 0);
+
+ /* PLL Setup : 24MHz * 20 / 1 = 480MHz */
+ regmap_write(priv->regmap, PHY_CTRL_R16, 0x39400414);
+ regmap_write(priv->regmap, PHY_CTRL_R17, 0x927e0000);
+ regmap_write(priv->regmap, PHY_CTRL_R18, 0xac5f49e5);
+
+ udelay(PLL_RESET_COMPLETE_TIME);
+
+ /* UnReset PLL */
+ regmap_write(priv->regmap, PHY_CTRL_R16, 0x19400414);
+
+ /* PHY Tuning */
+ regmap_write(priv->regmap, PHY_CTRL_R20, 0xfe18);
+ regmap_write(priv->regmap, PHY_CTRL_R4, 0x8000fff);
+
+ /* Tuning Disconnect Threshold */
+ regmap_write(priv->regmap, PHY_CTRL_R3, 0x34);
+
+ /* Analog Settings */
+ regmap_write(priv->regmap, PHY_CTRL_R14, 0);
+ regmap_write(priv->regmap, PHY_CTRL_R13, 0x78000);
+
+ return 0;
+}
+
+static int phy_meson_g12a_usb2_exit(struct phy *phy)
+{
+ struct udevice *dev = phy->dev;
+ struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = reset_assert(&priv->reset);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+struct phy_ops meson_g12a_usb2_phy_ops = {
+ .init = phy_meson_g12a_usb2_init,
+ .exit = phy_meson_g12a_usb2_exit,
+ .power_on = phy_meson_g12a_usb2_power_on,
+ .power_off = phy_meson_g12a_usb2_power_off,
+};
+
+int meson_g12a_usb2_phy_probe(struct udevice *dev)
+{
+ struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
+ if (ret)
+ return ret;
+
+ ret = reset_get_by_index(dev, 0, &priv->reset);
+ if (ret == -ENOTSUPP)
+ return 0;
+ else if (ret)
+ return ret;
+
+ ret = reset_deassert(&priv->reset);
+ if (ret) {
+ reset_release_all(&priv->reset, 1);
+ return ret;
+ }
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_get_by_index(dev, 0, &priv->clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(&priv->clk);
+ if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
+ pr_err("failed to enable PHY clock\n");
+ clk_free(&priv->clk);
+ return ret;
+ }
+#endif
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ ret = device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply);
+ if (ret && ret != -ENOENT) {
+ pr_err("Failed to get PHY regulator\n");
+ return ret;
+ }
+#endif
+
+ return 0;
+}
+
+static const struct udevice_id meson_g12a_usb2_phy_ids[] = {
+ { .compatible = "amlogic,g12a-usb2-phy" },
+ { }
+};
+
+U_BOOT_DRIVER(meson_g12a_usb2_phy) = {
+ .name = "meson_g12a_usb2_phy",
+ .id = UCLASS_PHY,
+ .of_match = meson_g12a_usb2_phy_ids,
+ .probe = meson_g12a_usb2_phy_probe,
+ .ops = &meson_g12a_usb2_phy_ops,
+ .priv_auto_alloc_size = sizeof(struct phy_meson_g12a_usb2_priv),
+};
diff --git a/drivers/phy/meson-g12a-usb3-pcie.c b/drivers/phy/meson-g12a-usb3-pcie.c
new file mode 100644
index 00000000000..920675dc999
--- /dev/null
+++ b/drivers/phy/meson-g12a-usb3-pcie.c
@@ -0,0 +1,345 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Meson G12A USB3+PCIE Combo PHY driver
+ *
+ * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ * Copyright (C) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstron@baylibre.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <regmap.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <reset.h>
+#include <bitfield.h>
+#include <generic-phy.h>
+
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/bitfield.h>
+
+#define PHY_R0 0x00
+ #define PHY_R0_PCIE_POWER_STATE GENMASK(4, 0)
+ #define PHY_R0_PCIE_USB3_SWITCH GENMASK(6, 5)
+
+#define PHY_R1 0x04
+ #define PHY_R1_PHY_TX1_TERM_OFFSET GENMASK(4, 0)
+ #define PHY_R1_PHY_TX0_TERM_OFFSET GENMASK(9, 5)
+ #define PHY_R1_PHY_RX1_EQ GENMASK(12, 10)
+ #define PHY_R1_PHY_RX0_EQ GENMASK(15, 13)
+ #define PHY_R1_PHY_LOS_LEVEL GENMASK(20, 16)
+ #define PHY_R1_PHY_LOS_BIAS GENMASK(23, 21)
+ #define PHY_R1_PHY_REF_CLKDIV2 BIT(24)
+ #define PHY_R1_PHY_MPLL_MULTIPLIER GENMASK(31, 25)
+
+#define PHY_R2 0x08
+ #define PHY_R2_PCS_TX_DEEMPH_GEN2_6DB GENMASK(5, 0)
+ #define PHY_R2_PCS_TX_DEEMPH_GEN2_3P5DB GENMASK(11, 6)
+ #define PHY_R2_PCS_TX_DEEMPH_GEN1 GENMASK(17, 12)
+ #define PHY_R2_PHY_TX_VBOOST_LVL GENMASK(20, 18)
+
+#define PHY_R4 0x10
+ #define PHY_R4_PHY_CR_WRITE BIT(0)
+ #define PHY_R4_PHY_CR_READ BIT(1)
+ #define PHY_R4_PHY_CR_DATA_IN GENMASK(17, 2)
+ #define PHY_R4_PHY_CR_CAP_DATA BIT(18)
+ #define PHY_R4_PHY_CR_CAP_ADDR BIT(19)
+
+#define PHY_R5 0x14
+ #define PHY_R5_PHY_CR_DATA_OUT GENMASK(15, 0)
+ #define PHY_R5_PHY_CR_ACK BIT(16)
+ #define PHY_R5_PHY_BS_OUT BIT(17)
+
+struct phy_g12a_usb3_pcie_priv {
+ struct regmap *regmap;
+#if CONFIG_IS_ENABLED(CLK)
+ struct clk clk;
+#endif
+ struct reset_ctl_bulk resets;
+};
+
+static int phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv *priv,
+ unsigned int addr)
+{
+ unsigned int val, reg;
+ int ret;
+
+ reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, addr);
+
+ regmap_write(priv->regmap, PHY_R4, reg);
+ regmap_write(priv->regmap, PHY_R4, reg);
+
+ regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_ADDR);
+
+ ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
+ (val & PHY_R5_PHY_CR_ACK),
+ 5, 1000);
+ if (ret)
+ return ret;
+
+ regmap_write(priv->regmap, PHY_R4, reg);
+
+ ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
+ !(val & PHY_R5_PHY_CR_ACK),
+ 5, 1000);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int
+phy_g12a_usb3_pcie_cr_bus_read(struct phy_g12a_usb3_pcie_priv *priv,
+ unsigned int addr, unsigned int *data)
+{
+ unsigned int val;
+ int ret;
+
+ ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr);
+ if (ret)
+ return ret;
+
+ regmap_write(priv->regmap, PHY_R4, 0);
+ regmap_write(priv->regmap, PHY_R4, PHY_R4_PHY_CR_READ);
+
+ ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
+ (val & PHY_R5_PHY_CR_ACK),
+ 5, 1000);
+ if (ret)
+ return ret;
+
+ *data = FIELD_GET(PHY_R5_PHY_CR_DATA_OUT, val);
+
+ regmap_write(priv->regmap, PHY_R4, 0);
+
+ ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
+ !(val & PHY_R5_PHY_CR_ACK),
+ 5, 1000);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int
+phy_g12a_usb3_pcie_cr_bus_write(struct phy_g12a_usb3_pcie_priv *priv,
+ unsigned int addr, unsigned int data)
+{
+ unsigned int val, reg;
+ int ret;
+
+ ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr);
+ if (ret)
+ return ret;
+
+ reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, data);
+
+ regmap_write(priv->regmap, PHY_R4, reg);
+ regmap_write(priv->regmap, PHY_R4, reg);
+
+ regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_DATA);
+
+ ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
+ (val & PHY_R5_PHY_CR_ACK),
+ 5, 1000);
+ if (ret)
+ return ret;
+
+ regmap_write(priv->regmap, PHY_R4, reg);
+
+ ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
+ (val & PHY_R5_PHY_CR_ACK) == 0,
+ 5, 1000);
+ if (ret)
+ return ret;
+
+ regmap_write(priv->regmap, PHY_R4, reg);
+
+ regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_WRITE);
+
+ ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
+ (val & PHY_R5_PHY_CR_ACK),
+ 5, 1000);
+ if (ret)
+ return ret;
+
+ regmap_write(priv->regmap, PHY_R4, reg);
+
+ ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
+ (val & PHY_R5_PHY_CR_ACK) == 0,
+ 5, 1000);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int
+phy_g12a_usb3_pcie_cr_bus_update_bits(struct phy_g12a_usb3_pcie_priv *priv,
+ uint offset, uint mask, uint val)
+{
+ uint reg;
+ int ret;
+
+ ret = phy_g12a_usb3_pcie_cr_bus_read(priv, offset, &reg);
+ if (ret)
+ return ret;
+
+ reg &= ~mask;
+
+ return phy_g12a_usb3_pcie_cr_bus_write(priv, offset, reg | val);
+}
+
+static int phy_meson_g12a_usb3_init(struct phy *phy)
+{
+ struct udevice *dev = phy->dev;
+ struct phy_g12a_usb3_pcie_priv *priv = dev_get_priv(dev);
+ unsigned int data;
+ int ret;
+
+ /* TOFIX Handle PCIE mode */
+
+ ret = reset_assert_bulk(&priv->resets);
+ udelay(1);
+ ret |= reset_deassert_bulk(&priv->resets);
+ if (ret)
+ return ret;
+
+ /* Switch PHY to USB3 */
+ regmap_update_bits(priv->regmap, PHY_R0,
+ PHY_R0_PCIE_USB3_SWITCH,
+ PHY_R0_PCIE_USB3_SWITCH);
+
+ /*
+ * WORKAROUND: There is SSPHY suspend bug due to
+ * which USB enumerates
+ * in HS mode instead of SS mode. Workaround it by asserting
+ * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus
+ * mode
+ */
+ ret = phy_g12a_usb3_pcie_cr_bus_update_bits(priv, 0x102d,
+ BIT(7), BIT(7));
+ if (ret)
+ return ret;
+
+ ret = phy_g12a_usb3_pcie_cr_bus_update_bits(priv, 0x1010, 0xff0, 20);
+ if (ret)
+ return ret;
+
+ /*
+ * Fix RX Equalization setting as follows
+ * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0
+ * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1
+ * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
+ * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
+ */
+ ret = phy_g12a_usb3_pcie_cr_bus_read(priv, 0x1006, &data);
+ if (ret)
+ return ret;
+
+ data &= ~BIT(6);
+ data |= BIT(7);
+ data &= ~(0x7 << 8);
+ data |= (0x3 << 8);
+ data |= (1 << 11);
+ ret = phy_g12a_usb3_pcie_cr_bus_write(priv, 0x1006, data);
+ if (ret)
+ return ret;
+
+ /*
+ * Set EQ and TX launch amplitudes as follows
+ * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22
+ * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
+ * LANE0.TX_OVRD_DRV_LO.EN set to 1.
+ */
+ ret = phy_g12a_usb3_pcie_cr_bus_read(priv, 0x1002, &data);
+ if (ret)
+ return ret;
+
+ data &= ~0x3f80;
+ data |= (0x16 << 7);
+ data &= ~0x7f;
+ data |= (0x7f | BIT(14));
+ ret = phy_g12a_usb3_pcie_cr_bus_write(priv, 0x1002, data);
+ if (ret)
+ return ret;
+
+ /*
+ * MPLL_LOOP_CTL.PROP_CNTRL = 8
+ */
+ ret = phy_g12a_usb3_pcie_cr_bus_update_bits(priv, 0x30,
+ 0xf << 4, 8 << 4);
+ if (ret)
+ return ret;
+
+ regmap_update_bits(priv->regmap, PHY_R2,
+ PHY_R2_PHY_TX_VBOOST_LVL,
+ FIELD_PREP(PHY_R2_PHY_TX_VBOOST_LVL, 0x4));
+
+ regmap_update_bits(priv->regmap, PHY_R1,
+ PHY_R1_PHY_LOS_BIAS | PHY_R1_PHY_LOS_LEVEL,
+ FIELD_PREP(PHY_R1_PHY_LOS_BIAS, 4) |
+ FIELD_PREP(PHY_R1_PHY_LOS_LEVEL, 9));
+
+ return ret;
+}
+
+static int phy_meson_g12a_usb3_exit(struct phy *phy)
+{
+ struct phy_g12a_usb3_pcie_priv *priv = dev_get_priv(phy->dev);
+
+ return reset_assert_bulk(&priv->resets);
+}
+
+struct phy_ops meson_g12a_usb3_pcie_phy_ops = {
+ .init = phy_meson_g12a_usb3_init,
+ .exit = phy_meson_g12a_usb3_exit,
+};
+
+int meson_g12a_usb3_pcie_phy_probe(struct udevice *dev)
+{
+ struct phy_g12a_usb3_pcie_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
+ if (ret)
+ return ret;
+
+ ret = reset_get_bulk(dev, &priv->resets);
+ if (ret == -ENOTSUPP)
+ return 0;
+ else if (ret)
+ return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_get_by_index(dev, 0, &priv->clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(&priv->clk);
+ if (ret && ret != -ENOENT && ret != -ENOTSUPP) {
+ pr_err("failed to enable PHY clock\n");
+ clk_free(&priv->clk);
+ return ret;
+ }
+#endif
+
+ return 0;
+}
+
+static const struct udevice_id meson_g12a_usb3_pcie_phy_ids[] = {
+ { .compatible = "amlogic,g12a-usb3-pcie-phy" },
+ { }
+};
+
+U_BOOT_DRIVER(meson_g12a_usb3_pcie_phy) = {
+ .name = "meson_g12a_usb3_pcie_phy",
+ .id = UCLASS_PHY,
+ .of_match = meson_g12a_usb3_pcie_phy_ids,
+ .probe = meson_g12a_usb3_pcie_phy_probe,
+ .ops = &meson_g12a_usb3_pcie_phy_ops,
+ .priv_auto_alloc_size = sizeof(struct phy_g12a_usb3_pcie_priv),
+};
diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c
index 89e39c6b5aa..ee1a423ffbc 100644
--- a/drivers/reset/reset-uclass.c
+++ b/drivers/reset/reset-uclass.c
@@ -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;
diff --git a/drivers/serial/serial_sifive.c b/drivers/serial/serial_sifive.c
index 537bc7a975b..fdfef69aaae 100644
--- a/drivers/serial/serial_sifive.c
+++ b/drivers/serial/serial_sifive.c
@@ -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>
diff --git a/drivers/spi/atcspi200_spi.c b/drivers/spi/atcspi200_spi.c
index af96c6d21e5..e0cc3234440 100644
--- a/drivers/spi/atcspi200_spi.c
+++ b/drivers/spi/atcspi200_spi.c
@@ -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>
diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c
index 009f3766027..072f7948efa 100644
--- a/drivers/sysreset/sysreset_x86.c
+++ b/drivers/sysreset/sysreset_x86.c
@@ -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),
};
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index bbd8105c06f..25e1a38aee0 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -44,6 +44,14 @@ config USB_DWC3_GENERIC
Select this for Xilinx ZynqMP and similar Platforms.
This wrapper supports Host and Peripheral operation modes.
+config USB_DWC3_MESON_G12A
+ bool "Amlogic Meson G12A USB wrapper"
+ depends on DM_USB && USB_DWC3 && ARCH_MESON
+ imply PHY
+ help
+ Select this for Amlogic Meson G12A Platforms.
+ This wrapper supports Host and Peripheral operation modes.
+
config USB_DWC3_UNIPHIER
bool "DesignWare USB3 Host Support on UniPhier Platforms"
depends on ARCH_UNIPHIER && USB_XHCI_DWC3
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 60b5515a67d..0b652a6f364 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -7,6 +7,7 @@ dwc3-y := core.o
obj-$(CONFIG_USB_DWC3_GADGET) += gadget.o ep0.o
obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o
+obj-$(CONFIG_USB_DWC3_MESON_G12A) += dwc3-meson-g12a.o
obj-$(CONFIG_USB_DWC3_GENERIC) += dwc3-generic.o
obj-$(CONFIG_USB_DWC3_UNIPHIER) += dwc3-uniphier.o
obj-$(CONFIG_USB_DWC3_PHY_OMAP) += ti_usb_phy.o
diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
new file mode 100644
index 00000000000..832bcd70ff0
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -0,0 +1,456 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Amlogic G12A DWC3 Glue layer
+ *
+ * Copyright (C) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <common.h>
+#include <asm-generic/io.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dwc3-uboot.h>
+#include <generic-phy.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <malloc.h>
+#include <regmap.h>
+#include <usb.h>
+#include "core.h"
+#include "gadget.h"
+#include <reset.h>
+#include <clk.h>
+#include <power/regulator.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
+
+/* USB2 Ports Control Registers */
+
+#define U2P_REG_SIZE 0x20
+
+#define U2P_R0 0x0
+ #define U2P_R0_HOST_DEVICE BIT(0)
+ #define U2P_R0_POWER_OK BIT(1)
+ #define U2P_R0_HAST_MODE BIT(2)
+ #define U2P_R0_POWER_ON_RESET BIT(3)
+ #define U2P_R0_ID_PULLUP BIT(4)
+ #define U2P_R0_DRV_VBUS BIT(5)
+
+#define U2P_R1 0x4
+ #define U2P_R1_PHY_READY BIT(0)
+ #define U2P_R1_ID_DIG BIT(1)
+ #define U2P_R1_OTG_SESSION_VALID BIT(2)
+ #define U2P_R1_VBUS_VALID BIT(3)
+
+/* USB Glue Control Registers */
+
+#define USB_R0 0x80
+ #define USB_R0_P30_LANE0_TX2RX_LOOPBACK BIT(17)
+ #define USB_R0_P30_LANE0_EXT_PCLK_REQ BIT(18)
+ #define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK GENMASK(28, 19)
+ #define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK GENMASK(30, 29)
+ #define USB_R0_U2D_ACT BIT(31)
+
+#define USB_R1 0x84
+ #define USB_R1_U3H_BIGENDIAN_GS BIT(0)
+ #define USB_R1_U3H_PME_ENABLE BIT(1)
+ #define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK GENMASK(4, 2)
+ #define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK GENMASK(9, 7)
+ #define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK GENMASK(13, 12)
+ #define USB_R1_U3H_HOST_U3_PORT_DISABLE BIT(16)
+ #define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT BIT(17)
+ #define USB_R1_U3H_HOST_MSI_ENABLE BIT(18)
+ #define USB_R1_U3H_FLADJ_30MHZ_REG_MASK GENMASK(24, 19)
+ #define USB_R1_P30_PCS_TX_SWING_FULL_MASK GENMASK(31, 25)
+
+#define USB_R2 0x88
+ #define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(25, 20)
+ #define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK GENMASK(31, 26)
+
+#define USB_R3 0x8c
+ #define USB_R3_P30_SSC_ENABLE BIT(0)
+ #define USB_R3_P30_SSC_RANGE_MASK GENMASK(3, 1)
+ #define USB_R3_P30_SSC_REF_CLK_SEL_MASK GENMASK(12, 4)
+ #define USB_R3_P30_REF_SSP_EN BIT(13)
+
+#define USB_R4 0x90
+ #define USB_R4_P21_PORT_RESET_0 BIT(0)
+ #define USB_R4_P21_SLEEP_M0 BIT(1)
+ #define USB_R4_MEM_PD_MASK GENMASK(3, 2)
+ #define USB_R4_P21_ONLY BIT(4)
+
+#define USB_R5 0x94
+ #define USB_R5_ID_DIG_SYNC BIT(0)
+ #define USB_R5_ID_DIG_REG BIT(1)
+ #define USB_R5_ID_DIG_CFG_MASK GENMASK(3, 2)
+ #define USB_R5_ID_DIG_EN_0 BIT(4)
+ #define USB_R5_ID_DIG_EN_1 BIT(5)
+ #define USB_R5_ID_DIG_CURR BIT(6)
+ #define USB_R5_ID_DIG_IRQ BIT(7)
+ #define USB_R5_ID_DIG_TH_MASK GENMASK(15, 8)
+ #define USB_R5_ID_DIG_CNT_MASK GENMASK(23, 16)
+
+enum {
+ USB2_HOST_PHY = 0,
+ USB2_OTG_PHY,
+ USB3_HOST_PHY,
+ PHY_COUNT,
+};
+
+static const char *phy_names[PHY_COUNT] = {
+ "usb2-phy0", "usb2-phy1", "usb3-phy0",
+};
+
+struct dwc3_meson_g12a {
+ struct udevice *dev;
+ struct regmap *regmap;
+ struct clk clk;
+ struct reset_ctl reset;
+ struct phy phys[PHY_COUNT];
+ enum usb_dr_mode otg_mode;
+ enum usb_dr_mode otg_phy_mode;
+ unsigned int usb2_ports;
+ unsigned int usb3_ports;
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ struct udevice *vbus_supply;
+#endif
+};
+
+#define U2P_REG_SIZE 0x20
+#define USB_REG_OFFSET 0x80
+
+static void dwc3_meson_g12a_usb2_set_mode(struct dwc3_meson_g12a *priv,
+ int i, enum usb_dr_mode mode)
+{
+ switch (mode) {
+ case USB_DR_MODE_HOST:
+ case USB_DR_MODE_OTG:
+ case USB_DR_MODE_UNKNOWN:
+ regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
+ U2P_R0_HOST_DEVICE,
+ U2P_R0_HOST_DEVICE);
+ break;
+
+ case USB_DR_MODE_PERIPHERAL:
+ regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
+ U2P_R0_HOST_DEVICE, 0);
+ break;
+ }
+}
+
+static int dwc3_meson_g12a_usb2_init(struct dwc3_meson_g12a *priv)
+{
+ int i;
+
+ if (priv->otg_mode == USB_DR_MODE_PERIPHERAL)
+ priv->otg_phy_mode = USB_DR_MODE_PERIPHERAL;
+ else
+ priv->otg_phy_mode = USB_DR_MODE_HOST;
+
+ for (i = 0 ; i < USB3_HOST_PHY ; ++i) {
+ if (!priv->phys[i].dev)
+ continue;
+
+ regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
+ U2P_R0_POWER_ON_RESET,
+ U2P_R0_POWER_ON_RESET);
+
+ if (i == USB2_OTG_PHY) {
+ regmap_update_bits(priv->regmap,
+ U2P_R0 + (U2P_REG_SIZE * i),
+ U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS,
+ U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS);
+
+ dwc3_meson_g12a_usb2_set_mode(priv, i,
+ priv->otg_phy_mode);
+ } else
+ dwc3_meson_g12a_usb2_set_mode(priv, i,
+ USB_DR_MODE_HOST);
+
+ regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
+ U2P_R0_POWER_ON_RESET, 0);
+ }
+
+ return 0;
+}
+
+static void dwc3_meson_g12a_usb3_init(struct dwc3_meson_g12a *priv)
+{
+ regmap_update_bits(priv->regmap, USB_R3,
+ USB_R3_P30_SSC_RANGE_MASK |
+ USB_R3_P30_REF_SSP_EN,
+ USB_R3_P30_SSC_ENABLE |
+ FIELD_PREP(USB_R3_P30_SSC_RANGE_MASK, 2) |
+ USB_R3_P30_REF_SSP_EN);
+ udelay(2);
+
+ regmap_update_bits(priv->regmap, USB_R2,
+ USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK,
+ FIELD_PREP(USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK, 0x15));
+
+ regmap_update_bits(priv->regmap, USB_R2,
+ USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK,
+ FIELD_PREP(USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK, 0x20));
+
+ udelay(2);
+
+ regmap_update_bits(priv->regmap, USB_R1,
+ USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT,
+ USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT);
+
+ regmap_update_bits(priv->regmap, USB_R1,
+ USB_R1_P30_PCS_TX_SWING_FULL_MASK,
+ FIELD_PREP(USB_R1_P30_PCS_TX_SWING_FULL_MASK, 127));
+}
+
+static void dwc3_meson_g12a_usb_init_mode(struct dwc3_meson_g12a *priv)
+{
+ if (priv->otg_phy_mode == USB_DR_MODE_PERIPHERAL) {
+ regmap_update_bits(priv->regmap, USB_R0,
+ USB_R0_U2D_ACT, USB_R0_U2D_ACT);
+ regmap_update_bits(priv->regmap, USB_R0,
+ USB_R0_U2D_SS_SCALEDOWN_MODE_MASK, 0);
+ regmap_update_bits(priv->regmap, USB_R4,
+ USB_R4_P21_SLEEP_M0, USB_R4_P21_SLEEP_M0);
+ } else {
+ regmap_update_bits(priv->regmap, USB_R0,
+ USB_R0_U2D_ACT, 0);
+ regmap_update_bits(priv->regmap, USB_R4,
+ USB_R4_P21_SLEEP_M0, 0);
+ }
+}
+
+static int dwc3_meson_g12a_usb_init(struct dwc3_meson_g12a *priv)
+{
+ int ret;
+
+ ret = dwc3_meson_g12a_usb2_init(priv);
+ if (ret)
+ return ret;
+
+ regmap_update_bits(priv->regmap, USB_R1,
+ USB_R1_U3H_FLADJ_30MHZ_REG_MASK,
+ FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20));
+
+ regmap_update_bits(priv->regmap, USB_R5,
+ USB_R5_ID_DIG_EN_0,
+ USB_R5_ID_DIG_EN_0);
+ regmap_update_bits(priv->regmap, USB_R5,
+ USB_R5_ID_DIG_EN_1,
+ USB_R5_ID_DIG_EN_1);
+ regmap_update_bits(priv->regmap, USB_R5,
+ USB_R5_ID_DIG_TH_MASK,
+ FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff));
+
+ /* If we have an actual SuperSpeed port, initialize it */
+ if (priv->usb3_ports)
+ dwc3_meson_g12a_usb3_init(priv);
+
+ dwc3_meson_g12a_usb_init_mode(priv);
+
+ return 0;
+}
+
+int dwc3_meson_g12a_force_mode(struct udevice *dev, enum usb_dr_mode mode)
+{
+ struct dwc3_meson_g12a *priv = dev_get_platdata(dev);
+
+ if (!priv)
+ return -EINVAL;
+
+ if (mode != USB_DR_MODE_HOST && mode != USB_DR_MODE_PERIPHERAL)
+ return -EINVAL;
+
+ if (!priv->phys[USB2_OTG_PHY].dev)
+ return -EINVAL;
+
+ if (mode == priv->otg_mode)
+ return 0;
+
+ if (mode == USB_DR_MODE_HOST)
+ debug("%s: switching to Host Mode\n", __func__);
+ else
+ debug("%s: switching to Device Mode\n", __func__);
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ if (priv->vbus_supply) {
+ int ret = regulator_set_enable(priv->vbus_supply,
+ (mode == USB_DR_MODE_PERIPHERAL));
+ if (ret)
+ return ret;
+ }
+#endif
+ priv->otg_phy_mode = mode;
+
+ dwc3_meson_g12a_usb2_set_mode(priv, USB2_OTG_PHY, mode);
+
+ dwc3_meson_g12a_usb_init_mode(priv);
+
+ return 0;
+}
+
+static int dwc3_meson_g12a_get_phys(struct dwc3_meson_g12a *priv)
+{
+ int i, ret;
+
+ for (i = 0 ; i < PHY_COUNT ; ++i) {
+ ret = generic_phy_get_by_name(priv->dev, phy_names[i],
+ &priv->phys[i]);
+ if (ret == -ENOENT)
+ continue;
+
+ if (ret)
+ return ret;
+
+ if (i == USB3_HOST_PHY)
+ priv->usb3_ports++;
+ else
+ priv->usb2_ports++;
+ }
+
+ debug("%s: usb2 ports: %d\n", __func__, priv->usb2_ports);
+ debug("%s: usb3 ports: %d\n", __func__, priv->usb3_ports);
+
+ return 0;
+}
+
+static int dwc3_meson_g12a_reset_init(struct dwc3_meson_g12a *priv)
+{
+ int ret;
+
+ ret = reset_get_by_index(priv->dev, 0, &priv->reset);
+ if (ret)
+ return ret;
+
+ ret = reset_assert(&priv->reset);
+ udelay(1);
+ ret |= reset_deassert(&priv->reset);
+ if (ret) {
+ reset_free(&priv->reset);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int dwc3_meson_g12a_clk_init(struct dwc3_meson_g12a *priv)
+{
+ int ret;
+
+ ret = clk_get_by_index(priv->dev, 0, &priv->clk);
+ if (ret)
+ return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_enable(&priv->clk);
+ if (ret) {
+ clk_free(&priv->clk);
+ return ret;
+ }
+#endif
+
+ return 0;
+}
+
+static int dwc3_meson_g12a_probe(struct udevice *dev)
+{
+ struct dwc3_meson_g12a *priv = dev_get_platdata(dev);
+ int ret, i;
+
+ priv->dev = dev;
+
+ ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
+ if (ret)
+ return ret;
+
+ ret = dwc3_meson_g12a_clk_init(priv);
+ if (ret)
+ return ret;
+
+ ret = dwc3_meson_g12a_reset_init(priv);
+ if (ret)
+ return ret;
+
+ ret = dwc3_meson_g12a_get_phys(priv);
+ if (ret)
+ return ret;
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ ret = device_get_supply_regulator(dev, "vbus-supply",
+ &priv->vbus_supply);
+ if (ret && ret != -ENOENT) {
+ pr_err("Failed to get PHY regulator\n");
+ return ret;
+ }
+
+ if (priv->vbus_supply) {
+ ret = regulator_set_enable(priv->vbus_supply, true);
+ if (ret)
+ return ret;
+ }
+#endif
+
+ priv->otg_mode = usb_get_dr_mode(dev_of_offset(dev));
+
+ ret = dwc3_meson_g12a_usb_init(priv);
+ if (ret)
+ return ret;
+
+ for (i = 0 ; i < PHY_COUNT ; ++i) {
+ if (!priv->phys[i].dev)
+ continue;
+
+ ret = generic_phy_init(&priv->phys[i]);
+ if (ret)
+ goto err_phy_init;
+ }
+
+ return 0;
+
+err_phy_init:
+ for (i = 0 ; i < PHY_COUNT ; ++i) {
+ if (!priv->phys[i].dev)
+ continue;
+
+ generic_phy_exit(&priv->phys[i]);
+ }
+
+ return ret;
+}
+
+static int dwc3_meson_g12a_remove(struct udevice *dev)
+{
+ struct dwc3_meson_g12a *priv = dev_get_platdata(dev);
+ int i;
+
+ reset_release_all(&priv->reset, 1);
+
+ clk_release_all(&priv->clk, 1);
+
+ for (i = 0 ; i < PHY_COUNT ; ++i) {
+ if (!priv->phys[i].dev)
+ continue;
+
+ generic_phy_exit(&priv->phys[i]);
+ }
+
+ return dm_scan_fdt_dev(dev);
+}
+
+static const struct udevice_id dwc3_meson_g12a_ids[] = {
+ { .compatible = "amlogic,meson-g12a-usb-ctrl" },
+ { }
+};
+
+U_BOOT_DRIVER(dwc3_generic_wrapper) = {
+ .name = "dwc3-meson-g12a",
+ .id = UCLASS_SIMPLE_BUS,
+ .of_match = dwc3_meson_g12a_ids,
+ .probe = dwc3_meson_g12a_probe,
+ .remove = dwc3_meson_g12a_remove,
+ .platdata_auto_alloc_size = sizeof(struct dwc3_meson_g12a),
+
+};
diff --git a/include/clk.h b/include/clk.h
index 8e366163f95..d24e99713a3 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -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
diff --git a/include/configs/ax25-ae350.h b/include/configs/ax25-ae350.h
index 395f3a442da..a4037f33dd2 100644
--- a/include/configs/ax25-ae350.h
+++ b/include/configs/ax25-ae350.h
@@ -40,7 +40,7 @@
#define CONFIG_SYS_MALLOC_LEN (512 << 10)
/* DT blob (fdt) address */
-#define CONFIG_SYS_FDT_BASE 0x000f0000
+#define CONFIG_SYS_FDT_BASE 0x800f0000
/*
* Physical Memory Map
diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h
index ca592768925..f26e463fe53 100644
--- a/include/configs/chromebook_link.h
+++ b/include/configs/chromebook_link.h
@@ -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 */
diff --git a/include/configs/chromebook_samus.h b/include/configs/chromebook_samus.h
index ccb2fe8caad..2f7dd69fb82 100644
--- a/include/configs/chromebook_samus.h
+++ b/include/configs/chromebook_samus.h
@@ -23,4 +23,6 @@
#define CONFIG_ENV_SECT_SIZE 0x1000
#define CONFIG_ENV_OFFSET 0x003f8000
+#define CONFIG_TPL_TEXT_BASE 0xfffd8000
+
#endif /* __CONFIG_H */
diff --git a/include/configs/crs305-1g-4s.h b/include/configs/crs305-1g-4s.h
new file mode 100644
index 00000000000..c73cb99b1b6
--- /dev/null
+++ b/include/configs/crs305-1g-4s.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ */
+
+#ifndef _CONFIG_CRS305_1G_4S_H
+#define _CONFIG_CRS305_1G_4S_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+
+#define CONFIG_SYS_KWD_CONFIG $(CONFIG_BOARDDIR)/kwbimage.cfg
+#define CONFIG_SYS_TCLK 200000000 /* 200MHz */
+
+/* USB/EHCI configuration */
+#define CONFIG_EHCI_IS_TDI
+
+/* Environment in SPI NOR flash */
+#define CONFIG_ENV_OFFSET (1 << 20) /* 1MiB in */
+#define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE (256 << 10) /* 256KiB sectors */
+
+/* Keep device tree and initrd in lower memory so the kernel can access them */
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "fdt_high=0x10000000\0" \
+ "initrd_high=0x10000000\0"
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+#undef CONFIG_SYS_MAXARGS
+#define CONFIG_SYS_MAXARGS 96
+
+#endif /* _CONFIG_CRS305_1G_4S_H */
diff --git a/include/configs/qemu-riscv.h b/include/configs/qemu-riscv.h
index 2588c5a0b25..b7110edebcb 100644
--- a/include/configs/qemu-riscv.h
+++ b/include/configs/qemu-riscv.h
@@ -15,7 +15,7 @@
#define CONFIG_SYS_MALLOC_LEN SZ_8M
-#define CONFIG_SYS_BOOTM_LEN SZ_16M
+#define CONFIG_SYS_BOOTM_LEN SZ_64M
#define CONFIG_STANDALONE_LOAD_ADDR 0x80200000
@@ -41,11 +41,15 @@
#define CONFIG_EXTRA_ENV_SETTINGS \
"fdt_high=0xffffffffffffffff\0" \
"initrd_high=0xffffffffffffffff\0" \
- "kernel_addr_r=0x81000000\0" \
- "fdt_addr_r=0x82000000\0" \
- "scriptaddr=0x82100000\0" \
- "pxefile_addr_r=0x82200000\0" \
- "ramdisk_addr_r=0x82300000\0" \
+ "kernel_addr_r=0x84000000\0" \
+ "fdt_addr_r=0x88000000\0" \
+ "scriptaddr=0x88100000\0" \
+ "pxefile_addr_r=0x88200000\0" \
+ "ramdisk_addr_r=0x88300000\0" \
BOOTENV
+#define CONFIG_PREBOOT \
+ "setenv fdt_addr ${fdtcontroladdr};" \
+ "fdt addr ${fdtcontroladdr};"
+
#endif /* __CONFIG_H */
diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h
index 4cd1cac3bd2..64e7a60b8a0 100644
--- a/include/configs/qemu-x86.h
+++ b/include/configs/qemu-x86.h
@@ -33,11 +33,6 @@
#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 */
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index accc21f56fc..fceb812448f 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -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 \
diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h
index 4180b25f977..7fcf76a6bf2 100644
--- a/include/configs/x86-common.h
+++ b/include/configs/x86-common.h
@@ -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
diff --git a/include/efi_api.h b/include/efi_api.h
index 472160cb300..755c4057939 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -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 \
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 7af3f16ef84..07ef14ba1cd 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -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 */
diff --git a/include/efi_selftest.h b/include/efi_selftest.h
index dd42e49023c..eaee188de7e 100644
--- a/include/efi_selftest.h
+++ b/include/efi_selftest.h
@@ -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
diff --git a/include/pch.h b/include/pch.h
index 046a5fde3ab..0b44b66df9f 100644
--- a/include/pch.h
+++ b/include/pch.h
@@ -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.
diff --git a/include/pci.h b/include/pci.h
index 066238a9c3c..508f7bca81c 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -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
diff --git a/include/phy.h b/include/phy.h
index f23ca63f3b8..d01435d1aa1 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -101,6 +101,14 @@ struct phy_driver {
int (*readext)(struct phy_device *phydev, int addr, int devad, int reg);
int (*writeext)(struct phy_device *phydev, int addr, int devad, int reg,
u16 val);
+
+ /* Phy specific driver override for reading a MMD register */
+ int (*read_mmd)(struct phy_device *phydev, int devad, int reg);
+
+ /* Phy specific driver override for writing a MMD register */
+ int (*write_mmd)(struct phy_device *phydev, int devad, int reg,
+ u16 val);
+
struct list_head list;
};
@@ -165,6 +173,68 @@ static inline int phy_write(struct phy_device *phydev, int devad, int regnum,
return bus->write(bus, phydev->addr, devad, regnum, val);
}
+static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad,
+ int regnum)
+{
+ /* Write the desired MMD Devad */
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, devad);
+
+ /* Write the desired MMD register address */
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, regnum);
+
+ /* Select the Function : DATA with no post increment */
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL,
+ (devad | MII_MMD_CTRL_NOINCR));
+}
+
+static inline int phy_read_mmd(struct phy_device *phydev, int devad,
+ int regnum)
+{
+ struct phy_driver *drv = phydev->drv;
+
+ if (regnum > (u16)~0 || devad > 32)
+ return -EINVAL;
+
+ /* driver-specific access */
+ if (drv->read_mmd)
+ return drv->read_mmd(phydev, devad, regnum);
+
+ /* direct C45 / C22 access */
+ if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
+ devad == MDIO_DEVAD_NONE || !devad)
+ return phy_read(phydev, devad, regnum);
+
+ /* indirect C22 access */
+ phy_mmd_start_indirect(phydev, devad, regnum);
+
+ /* Read the content of the MMD's selected register */
+ return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA);
+}
+
+static inline int phy_write_mmd(struct phy_device *phydev, int devad,
+ int regnum, u16 val)
+{
+ struct phy_driver *drv = phydev->drv;
+
+ if (regnum > (u16)~0 || devad > 32)
+ return -EINVAL;
+
+ /* driver-specific access */
+ if (drv->write_mmd)
+ return drv->write_mmd(phydev, devad, regnum, val);
+
+ /* direct C45 / C22 access */
+ if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
+ devad == MDIO_DEVAD_NONE || !devad)
+ return phy_write(phydev, devad, regnum, val);
+
+ /* indirect C22 access */
+ phy_mmd_start_indirect(phydev, devad, regnum);
+
+ /* Write the data into MMD's selected register */
+ return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val);
+}
+
#ifdef CONFIG_PHYLIB_10G
extern struct phy_driver gen10g_driver;
diff --git a/include/reset.h b/include/reset.h
index a1a9ad5603d..4fac4e6a202 100644
--- a/include/reset.h
+++ b/include/reset.h
@@ -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
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index e5c46e9f081..b97d55cb451 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -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);
}
/**
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index f8092b62026..13541cfa7a2 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -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) {
diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c
index e0fcbb85a4d..38514e08209 100644
--- a/lib/efi_loader/efi_root_node.c
+++ b/lib/efi_loader/efi_root_node.c
@@ -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;
}
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 87db51cbb74..8691d686d29 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -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)
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 4945691e673..c69ad7a9c0b 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -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 \
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c
index 29ac0ce6510..644c5ade213 100644
--- a/lib/efi_selftest/efi_selftest_block_device.c
+++ b/lib/efi_selftest/efi_selftest_block_device.c
@@ -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;
}
diff --git a/lib/efi_selftest/efi_selftest_config_table.c b/lib/efi_selftest/efi_selftest_config_table.c
index 0bc5da6b0ce..4467f492ac5 100644
--- a/lib/efi_selftest/efi_selftest_config_table.c
+++ b/lib/efi_selftest/efi_selftest_config_table.c
@@ -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;
}
}
diff --git a/lib/efi_selftest/efi_selftest_loaded_image.c b/lib/efi_selftest/efi_selftest_loaded_image.c
index ea2b380a777..5889ab12617 100644
--- a/lib/efi_selftest/efi_selftest_loaded_image.c
+++ b/lib/efi_selftest/efi_selftest_loaded_image.c
@@ -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) {
diff --git a/lib/efi_selftest/efi_selftest_loadimage.c b/lib/efi_selftest/efi_selftest_loadimage.c
index 449b6bfcace..06a87df8620 100644
--- a/lib/efi_selftest/efi_selftest_loadimage.c
+++ b/lib/efi_selftest/efi_selftest_loadimage.c
@@ -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,
diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c
index 0ff35cec8a7..8edb1e4d467 100644
--- a/lib/efi_selftest/efi_selftest_manageprotocols.c
+++ b/lib/efi_selftest/efi_selftest_manageprotocols.c
@@ -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;
}
diff --git a/lib/efi_selftest/efi_selftest_memory.c b/lib/efi_selftest/efi_selftest_memory.c
index 5eeb42a9be3..e71732dc6db 100644
--- a/lib/efi_selftest/efi_selftest_memory.c
+++ b/lib/efi_selftest/efi_selftest_memory.c
@@ -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
index 00000000000..ee0ef395de4
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_register_notify.c
@@ -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,
+};
diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c
index d7350e2158d..4c266190012 100644
--- a/lib/efi_selftest/efi_selftest_snp.c
+++ b/lib/efi_selftest/efi_selftest_snp.c
@@ -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");
diff --git a/lib/efi_selftest/efi_selftest_startimage_exit.c b/lib/efi_selftest/efi_selftest_startimage_exit.c
index 96049dea868..11207b8162f 100644
--- a/lib/efi_selftest/efi_selftest_startimage_exit.c
+++ b/lib/efi_selftest/efi_selftest_startimage_exit.c
@@ -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;
}
diff --git a/lib/efi_selftest/efi_selftest_util.c b/lib/efi_selftest/efi_selftest_util.c
index 96a964c863e..ea73c25220f 100644
--- a/lib/efi_selftest/efi_selftest_util.c
+++ b/lib/efi_selftest/efi_selftest_util.c
@@ -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) {
diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c
index 47a8e7fb95c..b028c64bbc8 100644
--- a/lib/efi_selftest/efi_selftest_variables.c
+++ b/lib/efi_selftest/efi_selftest_variables.c
@@ -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;
}
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 56dbbe127ba..7af6b120b6c 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -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.
diff --git a/test/dm/clk.c b/test/dm/clk.c
index 112d5cbbc91..f301ecbb459 100644
--- a/test/dm/clk.c
+++ b/test/dm/clk.c
@@ -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;
diff --git a/test/dm/reset.c b/test/dm/reset.c
index c02866a2f0a..c61daed4903 100644
--- a/test/dm/reset.c
+++ b/test/dm/reset.c
@@ -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>
@@ -15,6 +16,28 @@
/* 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;
diff --git a/tools/binman/README b/tools/binman/README
index 04ed2b799c8..927fa856acf 100644
--- a/tools/binman/README
+++ b/tools/binman/README
@@ -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>'.
diff --git a/tools/binman/bsection.py b/tools/binman/bsection.py
index ccf2920c5bd..0ba542ee987 100644
--- a/tools/binman/bsection.py
+++ b/tools/binman/bsection.py
@@ -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)
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 3446e2e79c5..b32e4e1996f 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -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)
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 7f1b4136049..3681a484689 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -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)
diff --git a/tools/binman/etype/text.py b/tools/binman/etype/text.py
index 6e99819487f..c4aa510a87b 100644
--- a/tools/binman/etype/text.py
+++ b/tools/binman/etype/text.py
@@ -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
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py
index c4d970ed160..334ff9f966a 100644
--- a/tools/binman/etype/vblock.py
+++ b/tools/binman/etype/vblock.py
@@ -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)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index e77fce5a26f..daea1ea1382 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -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
index 00000000000..46708ff9b6b
--- /dev/null
+++ b/tools/binman/test/101_sections_offset.dts
@@ -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 {
+ };
+ };
+ };
+};