]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
Merge git://git.denx.de/u-boot-usb
authorTom Rini <trini@konsulko.com>
Sun, 1 Oct 2017 22:06:53 +0000 (18:06 -0400)
committerTom Rini <trini@konsulko.com>
Sun, 1 Oct 2017 22:06:53 +0000 (18:06 -0400)
176 files changed:
MAINTAINERS
arch/arm/Kconfig
arch/arm/dts/am3517-evm-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/am3517-evm.dts [new file with mode: 0644]
arch/arm/dts/am3517-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/am3517.dtsi [new file with mode: 0644]
arch/arm/dts/am35xx-clocks.dtsi [new file with mode: 0644]
arch/arm/dts/da850-evm-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/da850-evm.dts [new file with mode: 0644]
arch/arm/dts/da850.dtsi [new file with mode: 0644]
arch/arm/dts/omap3.dtsi
arch/arm/dts/omap5-u-boot.dtsi
arch/arm/dts/rk3229-evb.dts
arch/arm/dts/rk3288-popmetal.dtsi
arch/arm/dts/rk3328-evb.dts
arch/arm/dts/rk3368-px5-evb.dts
arch/arm/dts/rk3368-sheep.dts
arch/arm/dts/rk3399-evb.dts
arch/arm/dts/rk3399-puma.dtsi
arch/arm/dts/rv1108-evb.dts
arch/arm/dts/rv1108.dtsi
arch/arm/dts/tps6507x.dtsi [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/bootrom.h
arch/arm/include/asm/arch-rockchip/cru_rk3368.h
arch/arm/include/asm/arch-rockchip/cru_rv1108.h
arch/arm/include/asm/arch-rockchip/grf_rk3036.h
arch/arm/include/asm/arch-rockchip/sdram_rk322x.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/sys_proto.h
arch/arm/include/asm/armv7.h
arch/arm/mach-omap2/omap3/Kconfig
arch/arm/mach-omap2/sec-common.c
arch/arm/mach-rockchip/Makefile
arch/arm/mach-rockchip/rk3188/Makefile
arch/arm/mach-rockchip/rk322x-board.c
arch/arm/mach-rockchip/rk3288-board-spl.c
arch/arm/mach-rockchip/rk3288-board-tpl.c [new file with mode: 0644]
arch/arm/mach-rockchip/rk3288/Kconfig
arch/arm/mach-rockchip/rk3288/Makefile
arch/arm/mach-rockchip/rk3328/Makefile
arch/arm/mach-rockchip/rk3399-board-spl.c
arch/arm/mach-rockchip/rk3399/Makefile
arch/arm/mach-rockchip/spl-boot-order.c
arch/nds32/include/asm/io.h
board/amarula/vyasa-rk3288/vyasa-rk3288.c
board/davinci/da8xxevm/Kconfig
board/davinci/da8xxevm/da850evm.c
board/logicpd/am3517evm/am3517evm.c
board/rockchip/evb_rk3399/evb-rk3399.c
board/theobroma-systems/lion_rk3368/fit_spl_atf.its
board/theobroma-systems/puma_rk3399/puma-rk3399.c
cmd/Kconfig
cmd/bootefi.c
common/spl/Kconfig
common/spl/spl_mmc.c
configs/am335x_baltos_defconfig
configs/am335x_boneblack_defconfig
configs/am335x_boneblack_vboot_defconfig
configs/am335x_evm_defconfig
configs/am335x_evm_nor_defconfig
configs/am335x_evm_spiboot_defconfig
configs/am335x_evm_usbspl_defconfig
configs/am335x_hs_evm_defconfig
configs/am335x_hs_evm_uart_defconfig [new file with mode: 0644]
configs/am335x_igep003x_defconfig
configs/am335x_shc_defconfig
configs/am335x_shc_ict_defconfig
configs/am335x_shc_netboot_defconfig
configs/am335x_shc_prompt_defconfig
configs/am335x_shc_sdboot_defconfig
configs/am335x_shc_sdboot_prompt_defconfig
configs/am335x_sl50_defconfig
configs/am3517_evm_defconfig
configs/am43xx_evm_defconfig
configs/am43xx_evm_usbhost_boot_defconfig
configs/am43xx_hs_evm_defconfig
configs/am57xx_evm_defconfig
configs/am57xx_hs_evm_defconfig
configs/chiliboard_defconfig
configs/da850_am18xxevm_defconfig
configs/da850evm_defconfig
configs/da850evm_direct_nor_defconfig
configs/dra7xx_evm_defconfig
configs/dra7xx_hs_evm_defconfig
configs/evb-rk3328_defconfig
configs/lion-rk3368_defconfig
configs/omap3_evm_defconfig
configs/omap3_logic_defconfig
configs/omap3_overo_defconfig
configs/puma-rk3399_defconfig
configs/ti816x_evm_defconfig
configs/vyasa-rk3288_defconfig
disk/part_dos.c
disk/part_efi.c
doc/README.rockchip
doc/device-tree-bindings/chosen.txt
drivers/adc/Kconfig
drivers/adc/Makefile
drivers/adc/rockchip-saradc.c [new file with mode: 0644]
drivers/clk/clk_stm32f7.c
drivers/clk/rockchip/clk_rk322x.c
drivers/clk/rockchip/clk_rk3288.c
drivers/clk/rockchip/clk_rk3328.c
drivers/clk/rockchip/clk_rk3368.c
drivers/clk/rockchip/clk_rk3399.c
drivers/clk/rockchip/clk_rv1108.c
drivers/i2c/rk_i2c.c
drivers/mmc/Kconfig
drivers/mmc/Makefile
drivers/mmc/sdhci-cadence.c
drivers/mmc/stm32_sdmmc2.c [new file with mode: 0644]
drivers/mmc/uniphier-sd.c
drivers/pinctrl/rockchip/pinctrl_rk3368.c
drivers/power/regulator/Kconfig
drivers/ram/rockchip/Makefile
drivers/ram/rockchip/sdram_rk3188.c [moved from arch/arm/mach-rockchip/rk3188/sdram_rk3188.c with 99% similarity]
drivers/ram/rockchip/sdram_rk322x.c [new file with mode: 0644]
drivers/ram/rockchip/sdram_rk3288.c [moved from arch/arm/mach-rockchip/rk3288/sdram_rk3288.c with 100% similarity]
drivers/ram/rockchip/sdram_rk3328.c [moved from arch/arm/mach-rockchip/rk3328/sdram_rk3328.c with 100% similarity]
drivers/ram/rockchip/sdram_rk3399.c [moved from arch/arm/mach-rockchip/rk3399/sdram_rk3399.c with 100% similarity]
drivers/spi/davinci_spi.c
include/asm-generic/sections.h
include/blk.h
include/config_distro_bootcmd.h
include/configs/am3517_evm.h
include/configs/am43xx_evm.h
include/configs/am57xx_evm.h
include/configs/da850evm.h
include/configs/dra7xx_evm.h
include/configs/evb_rk3399.h
include/configs/k2g_evm.h
include/configs/rk3288_common.h
include/configs/ti_armv7_keystone2.h
include/configs/vyasa-rk3288.h
include/dt-bindings/clock/rv1108-cru.h
include/efi.h
include/efi_api.h
include/efi_loader.h
include/efi_selftest.h [new file with mode: 0644]
include/environment/ti/boot.h
include/part.h
include/part_efi.h
include/pe.h
lib/Makefile
lib/efi_loader/Makefile
lib/efi_loader/efi_bootmgr.c [new file with mode: 0644]
lib/efi_loader/efi_boottime.c
lib/efi_loader/efi_console.c
lib/efi_loader/efi_device_path.c [new file with mode: 0644]
lib/efi_loader/efi_device_path_to_text.c
lib/efi_loader/efi_disk.c
lib/efi_loader/efi_file.c [new file with mode: 0644]
lib/efi_loader/efi_image_loader.c
lib/efi_loader/efi_memory.c
lib/efi_loader/efi_net.c
lib/efi_loader/efi_runtime.c
lib/efi_loader/efi_variable.c [new file with mode: 0644]
lib/efi_selftest/Kconfig [new file with mode: 0644]
lib/efi_selftest/Makefile [new file with mode: 0644]
lib/efi_selftest/efi_selftest.c [new file with mode: 0644]
lib/efi_selftest/efi_selftest_console.c [new file with mode: 0644]
lib/efi_selftest/efi_selftest_events.c [new file with mode: 0644]
lib/efi_selftest/efi_selftest_exitbootservices.c [new file with mode: 0644]
lib/efi_selftest/efi_selftest_tpl.c [new file with mode: 0644]
scripts/Makefile.lib
scripts/spelling.txt [new file with mode: 0644]
test/py/README.md
test/py/conftest.py
test/py/multiplexed_log.py
test/py/tests/test_dfu.py
test/py/tests/test_efi_selftest.py [new file with mode: 0644]
test/py/tests/test_fit.py
test/py/tests/test_gpt.py
test/py/tests/test_vboot.py
tools/buildman/kconfiglib.py
tools/moveconfig.py
tools/rkcommon.c

index 04acf2b89dcbb17112e58085e9a853003a0f635f..b167b028ecf1c6cc0c01d719f83ca1d3299fbcce 100644 (file)
@@ -259,8 +259,9 @@ EFI PAYLOAD
 M:     Alexander Graf <agraf@suse.de>
 S:     Maintained
 T:     git git://github.com/agraf/u-boot.git
-F:     include/efi_loader.h
-F:     lib/efi_loader/
+F:     include/efi*
+F:     lib/efi*
+F:     test/py/tests/test_efi*
 F:     cmd/bootefi.c
 
 FLATTENED DEVICE TREE
@@ -419,6 +420,7 @@ F:  arch/arm/mach-omap2/omap5/sec-fxns.c
 F:     arch/arm/mach-omap2/sec-common.c
 F:     arch/arm/mach-omap2/config_secure.mk
 F:     configs/am335x_hs_evm_defconfig
+F:     configs/am335x_hs_evm_uart_defconfig
 F:     configs/am43xx_hs_evm_defconfig
 F:     configs/am57xx_hs_evm_defconfig
 F:     configs/dra7xx_hs_evm_defconfig
index bb64b9c160aeb37fa5fe10bb2e1f89606aacc33e..d6d9558c69560017e3891da5a085964685cff9d5 100644 (file)
@@ -588,6 +588,7 @@ config ARCH_OMAP2PLUS
        bool "TI OMAP2+"
        select CPU_V7
        select SPL_BOARD_INIT if SPL
+       select SPL_STACK_R if SPL
        select SUPPORT_SPL
        imply FIT
 
@@ -1114,6 +1115,9 @@ config ARCH_ROCKCHIP
        imply FAT_WRITE
        imply USB_FUNCTION_FASTBOOT
        imply SPL_SYSRESET
+       imply TPL_SYSRESET
+       imply ADC
+       imply SARADC_ROCKCHIP
 
 config TARGET_THUNDERX_88XX
        bool "Support ThunderX 88xx"
diff --git a/arch/arm/dts/am3517-evm-u-boot.dtsi b/arch/arm/dts/am3517-evm-u-boot.dtsi
new file mode 100644 (file)
index 0000000..24a67db
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2017
+ * Logic PD - http://www.logicpd.com
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+/ {
+       chosen {
+               stdout-path = &uart3;
+       };
+};
diff --git a/arch/arm/dts/am3517-evm.dts b/arch/arm/dts/am3517-evm.dts
new file mode 100644 (file)
index 0000000..0e4a125
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am3517.dtsi"
+
+/ {
+       model = "TI AM3517 EVM (AM3517/05 TMDSEVM3517)";
+       compatible = "ti,am3517-evm", "ti,am3517", "ti,omap3";
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x10000000>; /* 256 MB */
+       };
+
+        vmmc_fixed: vmmc {
+                compatible = "regulator-fixed";
+                regulator-name = "vmmc_fixed";
+                regulator-min-microvolt = <3300000>;
+                regulator-max-microvolt = <3300000>;
+        };
+};
+
+&davinci_emac {
+            status = "okay";
+};
+
+&davinci_mdio {
+            status = "okay";
+};
+
+&i2c1 {
+       clock-frequency = <400000>;
+};
+
+&i2c2 {
+       clock-frequency = <400000>;
+};
+
+&i2c3 {
+       clock-frequency = <400000>;
+};
+
+&mmc1 {
+       vmmc-supply = <&vmmc_fixed>;
+       bus-width = <4>;
+};
+
+&mmc2 {
+      status = "disabled";
+};
+
+&mmc3 {
+      status = "disabled";
+};
+
diff --git a/arch/arm/dts/am3517-u-boot.dtsi b/arch/arm/dts/am3517-u-boot.dtsi
new file mode 100644 (file)
index 0000000..2190052
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2017
+ * Logic PD - http://www.logicpd.com
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+&uart4 {
+       reg-shift = <2>;
+};
diff --git a/arch/arm/dts/am3517.dtsi b/arch/arm/dts/am3517.dtsi
new file mode 100644 (file)
index 0000000..00da3f2
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Device Tree Source for am3517 SoC
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include "omap3.dtsi"
+
+/ {
+       aliases {
+               serial3 = &uart4;
+               can = &hecc;
+       };
+
+       ocp@68000000 {
+               am35x_otg_hs: am35x_otg_hs@5c040000 {
+                       compatible = "ti,omap3-musb";
+                       ti,hwmods = "am35x_otg_hs";
+                       status = "disabled";
+                       reg = <0x5c040000 0x1000>;
+                       interrupts = <71>;
+                       interrupt-names = "mc";
+               };
+
+               davinci_emac: ethernet@0x5c000000 {
+                       compatible = "ti,am3517-emac";
+                       ti,hwmods = "davinci_emac";
+                       status = "disabled";
+                       reg = <0x5c000000 0x30000>;
+                       interrupts = <67 68 69 70>;
+                       syscon = <&scm_conf>;
+                       ti,davinci-ctrl-reg-offset = <0x10000>;
+                       ti,davinci-ctrl-mod-reg-offset = <0>;
+                       ti,davinci-ctrl-ram-offset = <0x20000>;
+                       ti,davinci-ctrl-ram-size = <0x2000>;
+                       ti,davinci-rmii-en = /bits/ 8 <1>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+               };
+
+               davinci_mdio: ethernet@0x5c030000 {
+                       compatible = "ti,davinci_mdio";
+                       ti,hwmods = "davinci_mdio";
+                       status = "disabled";
+                       reg = <0x5c030000 0x1000>;
+                       bus_freq = <1000000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               uart4: serial@4809e000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart4";
+                       status = "disabled";
+                       reg = <0x4809e000 0x400>;
+                       interrupts = <84>;
+                       dmas = <&sdma 55 &sdma 54>;
+                       dma-names = "tx", "rx";
+                       clock-frequency = <48000000>;
+               };
+
+               omap3_pmx_core2: pinmux@480025d8 {
+                       compatible = "ti,omap3-padconf", "pinctrl-single";
+                       reg = <0x480025d8 0x24>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       #pinctrl-cells = <1>;
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+                       pinctrl-single,register-width = <16>;
+                       pinctrl-single,function-mask = <0xff1f>;
+               };
+
+               hecc: can@5c050000 {
+                       compatible = "ti,am3517-hecc";
+                       status = "disabled";
+                       reg = <0x5c050000 0x80>,
+                             <0x5c053000 0x180>,
+                             <0x5c052000 0x200>;
+                       reg-names = "hecc", "hecc-ram", "mbx";
+                       interrupts = <24>;
+                       clocks = <&hecc_ck>;
+               };
+       };
+};
+
+&iva {
+       status = "disabled";
+};
+
+&mailbox {
+       status = "disabled";
+};
+
+&mmu_isp {
+       status = "disabled";
+};
+
+&smartreflex_mpu_iva {
+       status = "disabled";
+};
+
+/include/ "am35xx-clocks.dtsi"
+/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
diff --git a/arch/arm/dts/am35xx-clocks.dtsi b/arch/arm/dts/am35xx-clocks.dtsi
new file mode 100644 (file)
index 0000000..00dd1f0
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Device Tree Source for OMAP3 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+&scm_clocks {
+       emac_ick: emac_ick@32c {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-gate-clock";
+               clocks = <&ipss_ick>;
+               reg = <0x032c>;
+               ti,bit-shift = <1>;
+       };
+
+       emac_fck: emac_fck@32c {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&rmii_ck>;
+               reg = <0x032c>;
+               ti,bit-shift = <9>;
+       };
+
+       vpfe_ick: vpfe_ick@32c {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-gate-clock";
+               clocks = <&ipss_ick>;
+               reg = <0x032c>;
+               ti,bit-shift = <2>;
+       };
+
+       vpfe_fck: vpfe_fck@32c {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&pclk_ck>;
+               reg = <0x032c>;
+               ti,bit-shift = <10>;
+       };
+
+       hsotgusb_ick_am35xx: hsotgusb_ick_am35xx@32c {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-gate-clock";
+               clocks = <&ipss_ick>;
+               reg = <0x032c>;
+               ti,bit-shift = <0>;
+       };
+
+       hsotgusb_fck_am35xx: hsotgusb_fck_am35xx@32c {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_ck>;
+               reg = <0x032c>;
+               ti,bit-shift = <8>;
+       };
+
+       hecc_ck: hecc_ck@32c {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-gate-clock";
+               clocks = <&sys_ck>;
+               reg = <0x032c>;
+               ti,bit-shift = <3>;
+       };
+};
+&cm_clocks {
+       ipss_ick: ipss_ick@a10 {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-interface-clock";
+               clocks = <&core_l3_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <4>;
+       };
+
+       rmii_ck: rmii_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <50000000>;
+       };
+
+       pclk_ck: pclk_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <27000000>;
+       };
+
+       uart4_ick_am35xx: uart4_ick_am35xx@a10 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <23>;
+       };
+
+       uart4_fck_am35xx: uart4_fck_am35xx@a00 {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_48m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <23>;
+       };
+};
+
+&cm_clockdomains {
+       core_l3_clkdm: core_l3_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&sdrc_ick>, <&ipss_ick>, <&emac_ick>, <&vpfe_ick>,
+                        <&hsotgusb_ick_am35xx>, <&hsotgusb_fck_am35xx>,
+                        <&hecc_ck>;
+       };
+
+       core_l4_clkdm: core_l4_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&cpefuse_fck>, <&ts_fck>, <&usbtll_fck>,
+                        <&usbtll_ick>, <&mmchs3_ick>, <&mmchs3_fck>,
+                        <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>,
+                        <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>,
+                        <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>,
+                        <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>,
+                        <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>,
+                        <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>,
+                        <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>,
+                        <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>,
+                        <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>,
+                        <&uart4_ick_am35xx>, <&uart4_fck_am35xx>;
+       };
+};
diff --git a/arch/arm/dts/da850-evm-u-boot.dtsi b/arch/arm/dts/da850-evm-u-boot.dtsi
new file mode 100644 (file)
index 0000000..5cc5a81
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * da850-evm U-Boot Additions
+ *
+ * Copyright (C) 2017 Logic PD, Inc.
+ * Copyright (C) Adam Ford
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+/ {
+       chosen {
+               stdout-path = &serial2;
+       };
+
+       aliases {
+               i2c0 = &i2c0;
+               spi0 = &spi1;
+       };
+};
+
+&flash {
+       compatible = "m25p64", "spi-flash";
+};
diff --git a/arch/arm/dts/da850-evm.dts b/arch/arm/dts/da850-evm.dts
new file mode 100644 (file)
index 0000000..67e72bc
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Device Tree for DA850 EVM board
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation, version 2.
+ */
+/dts-v1/;
+#include "da850.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       compatible = "ti,da850-evm", "ti,da850";
+       model = "DA850/AM1808/OMAP-L138 EVM";
+
+       soc@1c00000 {
+               pmx_core: pinmux@14120 {
+                       status = "okay";
+
+                       mcasp0_pins: pinmux_mcasp0_pins {
+                               pinctrl-single,bits = <
+                                       /*
+                                        * AHCLKX, ACLKX, AFSX, AHCLKR, ACLKR,
+                                        * AFSR, AMUTE
+                                        */
+                                       0x00 0x11111111 0xffffffff
+                                       /* AXR11, AXR12 */
+                                       0x04 0x00011000 0x000ff000
+                               >;
+                       };
+                       nand_pins: nand_pins {
+                               pinctrl-single,bits = <
+                                       /* EMA_WAIT[0], EMA_OE, EMA_WE, EMA_CS[4], EMA_CS[3] */
+                                       0x1c 0x10110110  0xf0ff0ff0
+                                       /*
+                                        * EMA_D[0], EMA_D[1], EMA_D[2],
+                                        * EMA_D[3], EMA_D[4], EMA_D[5],
+                                        * EMA_D[6], EMA_D[7]
+                                        */
+                                       0x24 0x11111111  0xffffffff
+                                       /* EMA_A[1], EMA_A[2] */
+                                       0x30 0x01100000  0x0ff00000
+                               >;
+                       };
+               };
+               serial0: serial@42000 {
+                       status = "okay";
+               };
+               serial1: serial@10c000 {
+                       status = "okay";
+               };
+               serial2: serial@10d000 {
+                       status = "okay";
+               };
+               rtc0: rtc@23000 {
+                       status = "okay";
+               };
+               i2c0: i2c@22000 {
+                       status = "okay";
+                       clock-frequency = <100000>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c0_pins>;
+
+                       tps: tps@48 {
+                               reg = <0x48>;
+                       };
+                       tlv320aic3106: tlv320aic3106@18 {
+                               #sound-dai-cells = <0>;
+                               compatible = "ti,tlv320aic3106";
+                               reg = <0x18>;
+                               status = "okay";
+
+                               /* Regulators */
+                               IOVDD-supply = <&vdcdc2_reg>;
+                               /* Derived from VBAT: Baseboard 3.3V / 1.8V */
+                               AVDD-supply = <&vbat>;
+                               DRVDD-supply = <&vbat>;
+                               DVDD-supply = <&vbat>;
+                       };
+                       tca6416: gpio@20 {
+                               compatible = "ti,tca6416";
+                               reg = <0x20>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                       };
+               };
+               wdt: wdt@21000 {
+                       status = "okay";
+               };
+               mmc0: mmc@40000 {
+                       max-frequency = <50000000>;
+                       bus-width = <4>;
+                       status = "okay";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mmc0_pins>;
+               };
+               spi1: spi@30e000 {
+                       status = "okay";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&spi1_pins &spi1_cs0_pin>;
+                       flash: m25p80@0 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "m25p64";
+                               spi-max-frequency = <30000000>;
+                               m25p,fast-read;
+                               reg = <0>;
+                               partition@0 {
+                                       label = "U-Boot-SPL";
+                                       reg = <0x00000000 0x00010000>;
+                                       read-only;
+                               };
+                               partition@1 {
+                                       label = "U-Boot";
+                                       reg = <0x00010000 0x00080000>;
+                                       read-only;
+                               };
+                               partition@2 {
+                                       label = "U-Boot-Env";
+                                       reg = <0x00090000 0x00010000>;
+                                       read-only;
+                               };
+                               partition@3 {
+                                       label = "Kernel";
+                                       reg = <0x000a0000 0x00280000>;
+                               };
+                               partition@4 {
+                                       label = "Filesystem";
+                                       reg = <0x00320000 0x00400000>;
+                               };
+                               partition@5 {
+                                       label = "MAC-Address";
+                                       reg = <0x007f0000 0x00010000>;
+                                       read-only;
+                               };
+                       };
+               };
+               mdio: mdio@224000 {
+                       status = "okay";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mdio_pins>;
+                       bus_freq = <2200000>;
+               };
+               eth0: ethernet@220000 {
+                       status = "okay";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mii_pins>;
+               };
+               gpio: gpio@226000 {
+                       status = "okay";
+               };
+       };
+       vbat: fixedregulator0 {
+               compatible = "regulator-fixed";
+               regulator-name = "vbat";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+       };
+
+       sound {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "DA850/OMAP-L138 EVM";
+               simple-audio-card,widgets =
+                       "Line", "Line In",
+                       "Line", "Line Out";
+               simple-audio-card,routing =
+                       "LINE1L", "Line In",
+                       "LINE1R", "Line In",
+                       "Line Out", "LLOUT",
+                       "Line Out", "RLOUT";
+               simple-audio-card,format = "dsp_b";
+               simple-audio-card,bitclock-master = <&link0_codec>;
+               simple-audio-card,frame-master = <&link0_codec>;
+               simple-audio-card,bitclock-inversion;
+
+               simple-audio-card,cpu {
+                       sound-dai = <&mcasp0>;
+                       system-clock-frequency = <24576000>;
+               };
+
+               link0_codec: simple-audio-card,codec {
+                       sound-dai = <&tlv320aic3106>;
+                       system-clock-frequency = <24576000>;
+               };
+       };
+};
+
+/include/ "tps6507x.dtsi"
+
+&tps {
+       vdcdc1_2-supply = <&vbat>;
+       vdcdc3-supply = <&vbat>;
+       vldo1_2-supply = <&vbat>;
+
+       regulators {
+               vdcdc1_reg: regulator@0 {
+                       regulator-name = "VDCDC1_3.3V";
+                       regulator-min-microvolt = <3150000>;
+                       regulator-max-microvolt = <3450000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               vdcdc2_reg: regulator@1 {
+                       regulator-name = "VDCDC2_3.3V";
+                       regulator-min-microvolt = <1710000>;
+                       regulator-max-microvolt = <3450000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       ti,defdcdc_default = <1>;
+               };
+
+               vdcdc3_reg: regulator@2 {
+                       regulator-name = "VDCDC3_1.2V";
+                       regulator-min-microvolt = <950000>;
+                       regulator-max-microvolt = <1350000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       ti,defdcdc_default = <1>;
+               };
+
+               ldo1_reg: regulator@3 {
+                       regulator-name = "LDO1_1.8V";
+                       regulator-min-microvolt = <1710000>;
+                       regulator-max-microvolt = <1890000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               ldo2_reg: regulator@4 {
+                       regulator-name = "LDO2_1.2V";
+                       regulator-min-microvolt = <1140000>;
+                       regulator-max-microvolt = <1320000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+       };
+};
+
+&mcasp0 {
+       #sound-dai-cells = <0>;
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mcasp0_pins>;
+
+       op-mode = <0>;          /* MCASP_IIS_MODE */
+       tdm-slots = <2>;
+       /* 4 serializer */
+       serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+               0 0 0 0
+               0 0 0 0
+               0 0 0 1
+               2 0 0 0
+       >;
+       tx-num-evt = <32>;
+       rx-num-evt = <32>;
+};
+
+&edma0 {
+       ti,edma-reserved-slot-ranges = <32 50>;
+};
+
+&edma1 {
+       ti,edma-reserved-slot-ranges = <32 90>;
+};
+
+&aemif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&nand_pins>;
+       status = "ok";
+       cs3 {
+               #address-cells = <2>;
+               #size-cells = <1>;
+               clock-ranges;
+               ranges;
+
+               ti,cs-chipselect = <3>;
+
+               nand@2000000,0 {
+                       compatible = "ti,davinci-nand";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0 0x02000000 0x02000000
+                              1 0x00000000 0x00008000>;
+
+                       ti,davinci-chipselect = <1>;
+                       ti,davinci-mask-ale = <0>;
+                       ti,davinci-mask-cle = <0>;
+                       ti,davinci-mask-chipsel = <0>;
+                       ti,davinci-ecc-mode = "hw";
+                       ti,davinci-ecc-bits = <4>;
+                       ti,davinci-nand-use-bbt;
+               };
+       };
+};
+
+&vpif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&vpif_capture_pins>, <&vpif_display_pins>;
+       status = "okay";
+};
diff --git a/arch/arm/dts/da850.dtsi b/arch/arm/dts/da850.dtsi
new file mode 100644 (file)
index 0000000..02e2f8f
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * Copyright 2012 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+       arm {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               intc: interrupt-controller@fffee000 {
+                       compatible = "ti,cp-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+                       ti,intc-size = <101>;
+                       reg = <0xfffee000 0x2000>;
+               };
+       };
+
+       aliases {
+               spi0 = &spi0;
+       };
+
+       soc@1c00000 {
+               compatible = "simple-bus";
+               model = "da850";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x0 0x01c00000 0x400000>;
+               interrupt-parent = <&intc>;
+
+               pmx_core: pinmux@14120 {
+                       compatible = "pinctrl-single";
+                       reg = <0x14120 0x50>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       #pinctrl-cells = <2>;
+                       pinctrl-single,bit-per-mux;
+                       pinctrl-single,register-width = <32>;
+                       pinctrl-single,function-mask = <0xf>;
+                       status = "disabled";
+
+                       serial0_rtscts_pins: pinmux_serial0_rtscts_pins {
+                               pinctrl-single,bits = <
+                                       /* UART0_RTS UART0_CTS */
+                                       0x0c 0x22000000 0xff000000
+                               >;
+                       };
+                       serial0_rxtx_pins: pinmux_serial0_rxtx_pins {
+                               pinctrl-single,bits = <
+                                       /* UART0_TXD UART0_RXD */
+                                       0x0c 0x00220000 0x00ff0000
+                               >;
+                       };
+                       serial1_rtscts_pins: pinmux_serial1_rtscts_pins {
+                               pinctrl-single,bits = <
+                                       /* UART1_CTS UART1_RTS */
+                                       0x00 0x00440000 0x00ff0000
+                               >;
+                       };
+                       serial1_rxtx_pins: pinmux_serial1_rxtx_pins {
+                               pinctrl-single,bits = <
+                                       /* UART1_TXD UART1_RXD */
+                                       0x10 0x22000000 0xff000000
+                               >;
+                       };
+                       serial2_rtscts_pins: pinmux_serial2_rtscts_pins {
+                               pinctrl-single,bits = <
+                                       /* UART2_CTS UART2_RTS */
+                                       0x00 0x44000000 0xff000000
+                               >;
+                       };
+                       serial2_rxtx_pins: pinmux_serial2_rxtx_pins {
+                               pinctrl-single,bits = <
+                                       /* UART2_TXD UART2_RXD */
+                                       0x10 0x00220000 0x00ff0000
+                               >;
+                       };
+                       i2c0_pins: pinmux_i2c0_pins {
+                               pinctrl-single,bits = <
+                                       /* I2C0_SDA,I2C0_SCL */
+                                       0x10 0x00002200 0x0000ff00
+                               >;
+                       };
+                       i2c1_pins: pinmux_i2c1_pins {
+                               pinctrl-single,bits = <
+                                       /* I2C1_SDA, I2C1_SCL */
+                                       0x10 0x00440000 0x00ff0000
+                               >;
+                       };
+                       mmc0_pins: pinmux_mmc_pins {
+                               pinctrl-single,bits = <
+                                       /* MMCSD0_DAT[3] MMCSD0_DAT[2]
+                                        * MMCSD0_DAT[1] MMCSD0_DAT[0]
+                                        * MMCSD0_CMD    MMCSD0_CLK
+                                        */
+                                       0x28 0x00222222  0x00ffffff
+                               >;
+                       };
+                       ehrpwm0a_pins: pinmux_ehrpwm0a_pins {
+                               pinctrl-single,bits = <
+                                       /* EPWM0A */
+                                       0xc 0x00000002 0x0000000f
+                               >;
+                       };
+                       ehrpwm0b_pins: pinmux_ehrpwm0b_pins {
+                               pinctrl-single,bits = <
+                                       /* EPWM0B */
+                                       0xc 0x00000020 0x000000f0
+                               >;
+                       };
+                       ehrpwm1a_pins: pinmux_ehrpwm1a_pins {
+                               pinctrl-single,bits = <
+                                       /* EPWM1A */
+                                       0x14 0x00000002 0x0000000f
+                               >;
+                       };
+                       ehrpwm1b_pins: pinmux_ehrpwm1b_pins {
+                               pinctrl-single,bits = <
+                                       /* EPWM1B */
+                                       0x14 0x00000020 0x000000f0
+                               >;
+                       };
+                       ecap0_pins: pinmux_ecap0_pins {
+                               pinctrl-single,bits = <
+                                       /* ECAP0_APWM0 */
+                                       0x8 0x20000000 0xf0000000
+                               >;
+                       };
+                       ecap1_pins: pinmux_ecap1_pins {
+                               pinctrl-single,bits = <
+                                       /* ECAP1_APWM1 */
+                                       0x4 0x40000000 0xf0000000
+                               >;
+                       };
+                       ecap2_pins: pinmux_ecap2_pins {
+                               pinctrl-single,bits = <
+                                       /* ECAP2_APWM2 */
+                                       0x4 0x00000004 0x0000000f
+                               >;
+                       };
+                       spi0_pins: pinmux_spi0_pins {
+                               pinctrl-single,bits = <
+                                       /* SIMO, SOMI, CLK */
+                                       0xc 0x00001101 0x0000ff0f
+                               >;
+                       };
+                       spi0_cs0_pin: pinmux_spi0_cs0 {
+                               pinctrl-single,bits = <
+                                       /* CS0 */
+                                       0x10 0x00000010 0x000000f0
+                               >;
+                       };
+                       spi0_cs3_pin: pinmux_spi0_cs3_pin {
+                               pinctrl-single,bits = <
+                                       /* CS3 */
+                                       0xc 0x01000000 0x0f000000
+                               >;
+                       };
+                       spi1_pins: pinmux_spi1_pins {
+                               pinctrl-single,bits = <
+                                       /* SIMO, SOMI, CLK */
+                                       0x14 0x00110100 0x00ff0f00
+                               >;
+                       };
+                       spi1_cs0_pin: pinmux_spi1_cs0 {
+                               pinctrl-single,bits = <
+                                       /* CS0 */
+                                       0x14 0x00000010 0x000000f0
+                               >;
+                       };
+                       mdio_pins: pinmux_mdio_pins {
+                               pinctrl-single,bits = <
+                                       /* MDIO_CLK, MDIO_D */
+                                       0x10 0x00000088 0x000000ff
+                               >;
+                       };
+                       mii_pins: pinmux_mii_pins {
+                               pinctrl-single,bits = <
+                                       /*
+                                        * MII_TXEN, MII_TXCLK, MII_COL
+                                        * MII_TXD_3, MII_TXD_2, MII_TXD_1
+                                        * MII_TXD_0
+                                        */
+                                       0x8 0x88888880 0xfffffff0
+                                       /*
+                                        * MII_RXER, MII_CRS, MII_RXCLK
+                                        * MII_RXDV, MII_RXD_3, MII_RXD_2
+                                        * MII_RXD_1, MII_RXD_0
+                                        */
+                                       0xc 0x88888888 0xffffffff
+                               >;
+                       };
+                       lcd_pins: pinmux_lcd_pins {
+                               pinctrl-single,bits = <
+                                       /*
+                                        * LCD_D[2], LCD_D[3], LCD_D[4], LCD_D[5],
+                                        * LCD_D[6], LCD_D[7]
+                                        */
+                                       0x40 0x22222200 0xffffff00
+                                       /*
+                                        * LCD_D[10], LCD_D[11], LCD_D[12], LCD_D[13],
+                                        * LCD_D[14], LCD_D[15], LCD_D[0], LCD_D[1]
+                                        */
+                                       0x44 0x22222222 0xffffffff
+                                       /* LCD_D[8], LCD_D[9] */
+                                       0x48 0x00000022 0x000000ff
+
+                                       /* LCD_PCLK */
+                                       0x48 0x02000000 0x0f000000
+                                       /* LCD_AC_ENB_CS, LCD_VSYNC, LCD_HSYNC */
+                                       0x4c 0x02000022 0x0f0000ff
+                               >;
+                       };
+                       vpif_capture_pins: vpif_capture_pins {
+                               pinctrl-single,bits = <
+                                       /* VP_DIN[2..7], VP_CLKIN1, VP_CLKIN0 */
+                                       0x38 0x11111111 0xffffffff
+                                       /* VP_DIN[10..15,0..1] */
+                                       0x3c 0x11111111 0xffffffff
+                                       /* VP_DIN[8..9] */
+                                       0x40 0x00000011 0x000000ff
+                               >;
+                       };
+                       vpif_display_pins: vpif_display_pins {
+                               pinctrl-single,bits = <
+                                       /* VP_DOUT[2..7] */
+                                       0x40 0x11111100 0xffffff00
+                                       /* VP_DOUT[10..15,0..1] */
+                                       0x44 0x11111111 0xffffffff
+                                       /*  VP_DOUT[8..9] */
+                                       0x48 0x00000011 0x000000ff
+                                       /*
+                                        * VP_CLKOUT3, VP_CLKIN3,
+                                        * VP_CLKOUT2, VP_CLKIN2
+                                        */
+                                       0x4c 0x00111100 0x00ffff00
+                               >;
+                       };
+               };
+               prictrl: priority-controller@14110 {
+                       compatible = "ti,da850-mstpri";
+                       reg = <0x14110 0x0c>;
+                       status = "disabled";
+               };
+               cfgchip: chip-controller@1417c {
+                       compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
+                       reg = <0x1417c 0x14>;
+
+                       usb_phy: usb-phy {
+                               compatible = "ti,da830-usb-phy";
+                               #phy-cells = <1>;
+                               status = "disabled";
+                       };
+               };
+               edma0: edma@0 {
+                       compatible = "ti,edma3-tpcc";
+                       /* eDMA3 CC0: 0x01c0 0000 - 0x01c0 7fff */
+                       reg =   <0x0 0x8000>;
+                       reg-names = "edma3_cc";
+                       interrupts = <11 12>;
+                       interrupt-names = "edma3_ccint", "edma3_ccerrint";
+                       #dma-cells = <2>;
+
+                       ti,tptcs = <&edma0_tptc0 7>, <&edma0_tptc1 0>;
+               };
+               edma0_tptc0: tptc@8000 {
+                       compatible = "ti,edma3-tptc";
+                       reg =   <0x8000 0x400>;
+                       interrupts = <13>;
+                       interrupt-names = "edm3_tcerrint";
+               };
+               edma0_tptc1: tptc@8400 {
+                       compatible = "ti,edma3-tptc";
+                       reg =   <0x8400 0x400>;
+                       interrupts = <32>;
+                       interrupt-names = "edm3_tcerrint";
+               };
+               edma1: edma@230000 {
+                       compatible = "ti,edma3-tpcc";
+                       /* eDMA3 CC1: 0x01e3 0000 - 0x01e3 7fff */
+                       reg =   <0x230000 0x8000>;
+                       reg-names = "edma3_cc";
+                       interrupts = <93 94>;
+                       interrupt-names = "edma3_ccint", "edma3_ccerrint";
+                       #dma-cells = <2>;
+
+                       ti,tptcs = <&edma1_tptc0 7>;
+               };
+               edma1_tptc0: tptc@238000 {
+                       compatible = "ti,edma3-tptc";
+                       reg =   <0x238000 0x400>;
+                       interrupts = <95>;
+                       interrupt-names = "edm3_tcerrint";
+               };
+               serial0: serial@42000 {
+                       compatible = "ti,da830-uart", "ns16550a";
+                       reg = <0x42000 0x100>;
+                       reg-io-width = <4>;
+                       reg-shift = <2>;
+                       interrupts = <25>;
+                       status = "disabled";
+               };
+               serial1: serial@10c000 {
+                       compatible = "ti,da830-uart", "ns16550a";
+                       reg = <0x10c000 0x100>;
+                       reg-io-width = <4>;
+                       reg-shift = <2>;
+                       interrupts = <53>;
+                       status = "disabled";
+               };
+               serial2: serial@10d000 {
+                       compatible = "ti,da830-uart", "ns16550a";
+                       reg = <0x10d000 0x100>;
+                       reg-io-width = <4>;
+                       reg-shift = <2>;
+                       interrupts = <61>;
+                       status = "disabled";
+               };
+               rtc0: rtc@23000 {
+                       compatible = "ti,da830-rtc";
+                       reg = <0x23000 0x1000>;
+                       interrupts = <19
+                                     19>;
+                       status = "disabled";
+               };
+               i2c0: i2c@22000 {
+                       compatible = "ti,davinci-i2c";
+                       reg = <0x22000 0x1000>;
+                       interrupts = <15>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+               i2c1: i2c@228000 {
+                       compatible = "ti,davinci-i2c";
+                       reg = <0x228000 0x1000>;
+                       interrupts = <51>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+               wdt: wdt@21000 {
+                       compatible = "ti,davinci-wdt";
+                       reg = <0x21000 0x1000>;
+                       status = "disabled";
+               };
+               mmc0: mmc@40000 {
+                       compatible = "ti,da830-mmc";
+                       reg = <0x40000 0x1000>;
+                       cap-sd-highspeed;
+                       cap-mmc-highspeed;
+                       interrupts = <16>;
+                       dmas = <&edma0 16 0>, <&edma0 17 0>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+               vpif: video@217000 {
+                       compatible = "ti,da850-vpif";
+                       reg = <0x217000 0x1000>;
+                       interrupts = <92>;
+                       status = "disabled";
+
+                       /* VPIF capture port */
+                       port@0 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       /* VPIF display port */
+                       port@1 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
+               mmc1: mmc@21b000 {
+                       compatible = "ti,da830-mmc";
+                       reg = <0x21b000 0x1000>;
+                       cap-sd-highspeed;
+                       cap-mmc-highspeed;
+                       interrupts = <72>;
+                       dmas = <&edma1 28 0>, <&edma1 29 0>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+               ehrpwm0: pwm@300000 {
+                       compatible = "ti,da850-ehrpwm", "ti,am3352-ehrpwm",
+                                    "ti,am33xx-ehrpwm";
+                       #pwm-cells = <3>;
+                       reg = <0x300000 0x2000>;
+                       status = "disabled";
+               };
+               ehrpwm1: pwm@302000 {
+                       compatible = "ti,da850-ehrpwm", "ti,am3352-ehrpwm",
+                                    "ti,am33xx-ehrpwm";
+                       #pwm-cells = <3>;
+                       reg = <0x302000 0x2000>;
+                       status = "disabled";
+               };
+               ecap0: ecap@306000 {
+                       compatible = "ti,da850-ecap", "ti,am3352-ecap",
+                                    "ti,am33xx-ecap";
+                       #pwm-cells = <3>;
+                       reg = <0x306000 0x80>;
+                       status = "disabled";
+               };
+               ecap1: ecap@307000 {
+                       compatible = "ti,da850-ecap", "ti,am3352-ecap",
+                                    "ti,am33xx-ecap";
+                       #pwm-cells = <3>;
+                       reg = <0x307000 0x80>;
+                       status = "disabled";
+               };
+               ecap2: ecap@308000 {
+                       compatible = "ti,da850-ecap", "ti,am3352-ecap",
+                                    "ti,am33xx-ecap";
+                       #pwm-cells = <3>;
+                       reg = <0x308000 0x80>;
+                       status = "disabled";
+               };
+               spi0: spi@41000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "ti,da830-spi";
+                       reg = <0x41000 0x1000>;
+                       num-cs = <6>;
+                       ti,davinci-spi-intr-line = <1>;
+                       interrupts = <20>;
+                       dmas = <&edma0 14 0>, <&edma0 15 0>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+               spi1: spi@30e000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "ti,da830-spi";
+                       reg = <0x30e000 0x1000>;
+                       num-cs = <4>;
+                       ti,davinci-spi-intr-line = <1>;
+                       interrupts = <56>;
+                       dmas = <&edma0 18 0>, <&edma0 19 0>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+               usb0: usb@200000 {
+                       compatible = "ti,da830-musb";
+                       reg = <0x200000 0x1000>;
+                       ranges;
+                       interrupts = <58>;
+                       interrupt-names = "mc";
+                       dr_mode = "otg";
+                       phys = <&usb_phy 0>;
+                       phy-names = "usb-phy";
+                       status = "disabled";
+
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       dmas = <&cppi41dma 0 0 &cppi41dma 1 0
+                               &cppi41dma 2 0 &cppi41dma 3 0
+                               &cppi41dma 0 1 &cppi41dma 1 1
+                               &cppi41dma 2 1 &cppi41dma 3 1>;
+                       dma-names =
+                               "rx1", "rx2", "rx3", "rx4",
+                               "tx1", "tx2", "tx3", "tx4";
+
+                       cppi41dma: dma-controller@201000 {
+                               compatible = "ti,da830-cppi41";
+                               reg =  <0x201000 0x1000
+                                       0x202000 0x1000
+                                       0x204000 0x4000>;
+                               reg-names = "controller",
+                                           "scheduler", "queuemgr";
+                               interrupts = <58>;
+                               #dma-cells = <2>;
+                               #dma-channels = <4>;
+                               status = "okay";
+                       };
+               };
+               sata: sata@218000 {
+                       compatible = "ti,da850-ahci";
+                       reg = <0x218000 0x2000>, <0x22c018 0x4>;
+                       interrupts = <67>;
+                       status = "disabled";
+               };
+               mdio: mdio@224000 {
+                       compatible = "ti,davinci_mdio";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x224000 0x1000>;
+                       status = "disabled";
+               };
+               eth0: ethernet@220000 {
+                       compatible = "ti,davinci-dm6467-emac";
+                       reg = <0x220000 0x4000>;
+                       ti,davinci-ctrl-reg-offset = <0x3000>;
+                       ti,davinci-ctrl-mod-reg-offset = <0x2000>;
+                       ti,davinci-ctrl-ram-offset = <0>;
+                       ti,davinci-ctrl-ram-size = <0x2000>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <33
+                                       34
+                                       35
+                                       36
+                                       >;
+                       status = "disabled";
+               };
+               usb1: usb@225000 {
+                       compatible = "ti,da830-ohci";
+                       reg = <0x225000 0x1000>;
+                       interrupts = <59>;
+                       phys = <&usb_phy 1>;
+                       phy-names = "usb-phy";
+                       status = "disabled";
+               };
+               gpio: gpio@226000 {
+                       compatible = "ti,dm6441-gpio";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       reg = <0x226000 0x1000>;
+                       interrupts = <42 IRQ_TYPE_EDGE_BOTH
+                               43 IRQ_TYPE_EDGE_BOTH 44 IRQ_TYPE_EDGE_BOTH
+                               45 IRQ_TYPE_EDGE_BOTH 46 IRQ_TYPE_EDGE_BOTH
+                               47 IRQ_TYPE_EDGE_BOTH 48 IRQ_TYPE_EDGE_BOTH
+                               49 IRQ_TYPE_EDGE_BOTH 50 IRQ_TYPE_EDGE_BOTH>;
+                       ti,ngpio = <144>;
+                       ti,davinci-gpio-unbanked = <0>;
+                       status = "disabled";
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+               pinconf: pin-controller@22c00c {
+                       compatible = "ti,da850-pupd";
+                       reg = <0x22c00c 0x8>;
+                       status = "disabled";
+               };
+
+               mcasp0: mcasp@100000 {
+                       compatible = "ti,da830-mcasp-audio";
+                       reg = <0x100000 0x2000>,
+                             <0x102000 0x400000>;
+                       reg-names = "mpu", "dat";
+                       interrupts = <54>;
+                       interrupt-names = "common";
+                       status = "disabled";
+                       dmas = <&edma0 1 1>,
+                               <&edma0 0 1>;
+                       dma-names = "tx", "rx";
+               };
+
+               lcdc: display@213000 {
+                       compatible = "ti,da850-tilcdc";
+                       reg = <0x213000 0x1000>;
+                       interrupts = <52>;
+                       max-pixelclock = <37500>;
+                       status = "disabled";
+               };
+       };
+       aemif: aemif@68000000 {
+               compatible = "ti,da850-aemif";
+               #address-cells = <2>;
+               #size-cells = <1>;
+
+               reg = <0x68000000 0x00008000>;
+               ranges = <0 0 0x60000000 0x08000000
+                         1 0 0x68000000 0x00008000>;
+               status = "disabled";
+       };
+       memctrl: memory-controller@b0000000 {
+               compatible = "ti,da850-ddr-controller";
+               reg = <0xb0000000 0xe8>;
+               status = "disabled";
+       };
+};
index e6f9c9a6ddca7c5dc22422ae97f33d7f7bbd53bd..56c94729bb962f9d7d90e1ed5269a230b7bc81ea 100644 (file)
                        usbhsohci: ohci@48064400 {
                                compatible = "ti,ohci-omap3";
                                reg = <0x48064400 0x400>;
-                               interrupt-parent = <&intc>;
                                interrupts = <76>;
                        };
 
                        usbhsehci: ehci@48064800 {
                                compatible = "ti,ehci-omap";
                                reg = <0x48064800 0x400>;
-                               interrupt-parent = <&intc>;
                                interrupts = <77>;
                        };
                };
                                reg-names = "tx",
                                            "rx";
 
-                               interrupt-parent = <&intc>;
                                interrupts = <67>,
                                             <68>;
                        };
                                reg-names = "tx",
                                            "rx";
 
-                               interrupt-parent = <&intc>;
                                interrupts = <69>,
                                             <70>;
                        };
index 2eeed6f4a0123e1e9e5b5c67a2298dc467d434ca..fdaa69297cc4fba736706b4f20e69e7c880d4029 100644 (file)
        };
 };
 
+&gpio1 {
+       u-boot,dm-spl;
+};
+
 &gpio2 {
        u-boot,dm-spl;
 };
 
+&gpio3 {
+       u-boot,dm-spl;
+};
+
+&gpio4 {
+       u-boot,dm-spl;
+};
+
+&gpio5 {
+       u-boot,dm-spl;
+};
+
+&gpio6 {
+       u-boot,dm-spl;
+};
+
 &gpio7 {
        u-boot,dm-spl;
 };
index 64f1c2d7dac2b854ef870cfbb99676e6a41bea7e..ae0b0a4b8e3fe15ff6b3ac2fbfee5c4e2fc9d0a4 100644 (file)
@@ -40,7 +40,6 @@
 };
 
 &dmc {
-       rockchip,sdram-channel = /bits/ 8 <1 10 3 2 1 0 15 15>;
        rockchip,pctl-timing = <0x96 0xC8 0x1F3 0xF 0x8000004D 0x4 0x4E 0x6 0x3
                0x0 0x6 0x5 0xC 0x10 0x6 0x4 0x4
                0x5 0x4 0x200 0x3 0xA 0x40 0x0 0x1
index dd6ce8b69e634c8fb9709e78d0ee4e5d04e9765d..63785eb55eff07dc0573b5581e9e3fd8d4ae55c8 100644 (file)
        };
 };
 
+&saradc {
+       status = "okay";
+};
+
 &tsadc {
        rockchip,hw-tshut-mode = <0>;
        rockchip,hw-tshut-polarity = <0>;
index 8a14c653e4697d8cd5e28330a1d38bbcf786d02f..3dd9d8196147926290d2e05ac749b12999c26455 100644 (file)
        };
 };
 
+&saradc {
+       status = "okay";
+};
+
 &uart2 {
        status = "okay";
 };
        vbus-supply = <&vcc5v0_host_xhci>;
        status = "okay";
 };
+
+&i2c1 {
+       clock-frequency = <400000>;
+       i2c-scl-rising-time-ns = <168>;
+       i2c-scl-falling-time-ns = <4>;
+       status = "okay";
+
+       rk805: pmic@18 {
+               compatible = "rockchip,rk805";
+               status = "okay";
+               reg = <0x18>;
+               interrupt-parent = <&gpio2>;
+               interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pmic_int_l>;
+               rockchip,system-power-controller;
+               wakeup-source;
+               gpio-controller;
+               #gpio-cells = <2>;
+               #clock-cells = <1>;
+               clock-output-names = "xin32k", "rk805-clkout2";
+
+               regulators {
+                       vdd_logic: DCDC_REG1 {
+                               regulator-name = "vdd_logic";
+                               regulator-min-microvolt = <712500>;
+                               regulator-max-microvolt = <1450000>;
+                               regulator-ramp-delay = <6001>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       vdd_arm: DCDC_REG2 {
+                               regulator-name = "vdd_arm";
+                               regulator-min-microvolt = <712500>;
+                               regulator-max-microvolt = <1450000>;
+                               regulator-ramp-delay = <6001>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       vcc_ddr: DCDC_REG3 {
+                               regulator-name = "vcc_ddr";
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       vcc_io: DCDC_REG4 {
+                               regulator-name = "vcc_io";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3300000>;
+                               };
+                       };
+
+                       vdd_18: LDO_REG1 {
+                               regulator-name = "vdd_18";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcc_18emmc: LDO_REG2 {
+                               regulator-name = "vcc_18emmc";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vdd_10: LDO_REG3 {
+                               regulator-name = "vdd_10";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+               };
+       };
+};
+
+&pinctrl {
+       pmic {
+               pmic_int_l: pmic-int-l {
+               rockchip,pins =
+                       <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;  /* gpio2_a6 */
+               };
+       };
+};
+
index c7478f7ddb71746599809d017fa9e2c831f0dfe4..e9c5ebad4783ef6dfca8f0e0841182eed96041bf 100644 (file)
        };
 };
 
+&saradc {
+       status = "okay";
+};
+
 &tsadc {
        status = "okay";
        rockchip,hw-tshut-mode = <0>; /* CRU */
index 7c190f745660fd1c03f1ad8ff95916019d15efbf..27befadd67ceb152d03a2849bdd470b9ad0efa14 100644 (file)
        };
 };
 
+&saradc {
+       status = "okay";
+};
+
 &tsadc {
        status = "okay";
        rockchip,hw-tshut-mode = <0>; /* CRU */
index be0c6d98bd39945245552873c8cb8030c12771c0..0e5d8d79a19fa53d4c9c3d3d5a086528332d1a4b 100644 (file)
        status = "okay";
 };
 
+&saradc {
+       status = "okay";
+};
+
 &sdmmc {
        bus-width = <4>;
        status = "okay";
index a04878e223c007c1749e659a70f0be79fa6b281b..65ab3801391b50a238e196248db1eecbf0fbbf8b 100644 (file)
@@ -20,7 +20,8 @@
 
        chosen {
                stdout-path = "serial0:115200n8";
-               u-boot,spl-boot-order = &spiflash, &sdhci, &sdmmc;
+               u-boot,spl-boot-order = \
+                       "same-as-spl", &spiflash, &sdhci, &sdmmc;
        };
 
        aliases {
                regulator-max-microvolt = <3300000>;
        };
 
+       /*
+        * The Qseven BIOS_DISABLE signal on the RK3399-Q7 keeps the on-module
+        * eMMC and SPI flash powered-down initially (in fact it keeps the
+        * reset signal asserted).  Even though it is an enable signal, we
+        * model this as a regulator.
+        */
+       bios_enable: bios_enable {
+               compatible = "regulator-fixed";
+               u-boot,dm-pre-reloc;
+               regulator-name = "bios_enable";
+               enable-active-low;
+               gpio = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
+
        vccadc_ref: vccadc-ref {
                compatible = "regulator-fixed";
                regulator-name = "vcc1v8_sys";
 };
 
 &pcie_phy {
-               status = "okay";
+               status = "okay";
 };
 
 &pmu_io_domains {
 };
 
 &sdmmc {
-        u-boot,dm-pre-reloc;
+       u-boot,dm-pre-reloc;
        clock-frequency = <150000000>;
        clock-freq-min-max = <100000 150000000>;
        supports-sd;
        status = "okay";
 };
 
+&gpio3 {
+       u-boot,dm-pre-reloc;
+};
+
 &pinctrl {
        /* Pins that are not explicitely used by any devices */
        pinctrl-names = "default";
        pinctrl-0 = <&puma_pin_hog>;
+
        hog {
                puma_pin_hog: puma_pin_hog {
                        rockchip,pins =
        i2c8 {
                i2c8_xfer_a: i2c8-xfer {
                        rockchip,pins = <1 21 RK_FUNC_1 &pcfg_pull_up>,
-                                       <1 20 RK_FUNC_1 &pcfg_pull_up>;
+                                       <1 20 RK_FUNC_1 &pcfg_pull_up>;
                };
        };
 };
 &spi5 {
        status = "okay";
 };
-
index 2b221b6d61eef5b4d739b3e152f41e624b5b2ba0..8e857b2c8913fee306dd2867377cc435388f8b22 100644 (file)
        snps,reset-gpio = <&gpio1 RK_PC1 GPIO_ACTIVE_LOW>;
 };
 
+&saradc {
+       status = "okay";
+};
+
 &sfc {
        status = "okay";
        flash@0 {
index 3153dfe6584a17bf34f308fea3b2c492f1485d57..31b4d93b0763d49b16a82e235c73c252aa736da6 100644 (file)
                reg = <0x10300000 0x1000>;
        };
 
+       saradc: saradc@1038c000 {
+               compatible = "rockchip,rv1108-saradc", "rockchip,rk3399-saradc";
+               reg = <0x1038c000 0x100>;
+               interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+               #io-channel-cells = <1>;
+               clock-frequency = <1000000>;
+               clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
+               clock-names = "saradc", "apb_pclk";
+               status = "disabled";
+       };
+
        pmugrf: syscon@20060000 {
                compatible = "rockchip,rv1108-pmugrf", "syscon";
                reg = <0x20060000 0x1000>;
diff --git a/arch/arm/dts/tps6507x.dtsi b/arch/arm/dts/tps6507x.dtsi
new file mode 100644 (file)
index 0000000..4c326e5
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Integrated Power Management Chip
+ * http://www.ti.com/lit/ds/symlink/tps65070.pdf
+ */
+
+&tps {
+       compatible = "ti,tps6507x";
+
+       regulators {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               vdcdc1_reg: regulator@0 {
+                       reg = <0>;
+                       regulator-compatible = "VDCDC1";
+               };
+
+               vdcdc2_reg: regulator@1 {
+                       reg = <1>;
+                       regulator-compatible = "VDCDC2";
+               };
+
+               vdcdc3_reg: regulator@2 {
+                       reg = <2>;
+                       regulator-compatible = "VDCDC3";
+               };
+
+               ldo1_reg: regulator@3 {
+                       reg = <3>;
+                       regulator-compatible = "LDO1";
+               };
+
+               ldo2_reg: regulator@4 {
+                       reg = <4>;
+                       regulator-compatible = "LDO2";
+               };
+
+       };
+};
index 92eb8783a3ae3818399b54319911c2b28a0a6b33..169cc5e50b0e982be3132cb523ec8ceb4c62e948 100644 (file)
@@ -24,4 +24,22 @@ void back_to_bootrom(void);
  */
 void _back_to_bootrom_s(void);
 
+/**
+ * Boot-device identifiers as used by the BROM
+ */
+enum {
+       BROM_BOOTSOURCE_NAND = 1,
+       BROM_BOOTSOURCE_EMMC = 2,
+       BROM_BOOTSOURCE_SPINOR = 3,
+       BROM_BOOTSOURCE_SPINAND = 4,
+       BROM_BOOTSOURCE_SD = 5,
+       BROM_BOOTSOURCE_USB = 10,
+       BROM_LAST_BOOTSOURCE = BROM_BOOTSOURCE_USB
+};
+
+/**
+ * Locations of the boot-device identifier in SRAM
+ */
+#define RK3399_BROM_BOOTSOURCE_ID_ADDR   0xff8c0010
+
 #endif
index 2b1197fd4665a5686247f8e1d637ccab740b95a8..5f6a5fbe4cbaeb03c13aff46a88e9b2c0884c960 100644 (file)
@@ -89,6 +89,11 @@ enum {
        MCU_CLK_DIV_SHIFT               = 0,
        MCU_CLK_DIV_MASK                = GENMASK(4, 0),
 
+       /* CLKSEL_CON25 */
+       CLK_SARADC_DIV_CON_SHIFT        = 8,
+       CLK_SARADC_DIV_CON_MASK         = GENMASK(15, 8),
+       CLK_SARADC_DIV_CON_WIDTH        = 8,
+
        /* CLKSEL43_CON */
        GMAC_MUX_SEL_EXTCLK             = BIT(8),
 
index 2a1ae692bef47ac6b8ad2ffc0b80ab87f41788da..ad2dc96467543e183685e5dbc29c7cf69ae4ec27 100644 (file)
@@ -90,6 +90,11 @@ enum {
        CORE_CLK_DIV_SHIFT      = 0,
        CORE_CLK_DIV_MASK       = 0x1f << CORE_CLK_DIV_SHIFT,
 
+       /* CLKSEL_CON22 */
+       CLK_SARADC_DIV_CON_SHIFT= 0,
+       CLK_SARADC_DIV_CON_MASK = GENMASK(9, 0),
+       CLK_SARADC_DIV_CON_WIDTH= 10,
+
        /* CLKSEL24_CON */
        MAC_PLL_SEL_SHIFT       = 12,
        MAC_PLL_SEL_MASK        = 1 << MAC_PLL_SEL_SHIFT,
index 7625f249bd964d92d35b5cae5a4ed964d342712e..d995b7db14cfba72f1b09d091a19bad76442cd6d 100644 (file)
@@ -209,10 +209,10 @@ enum {
        GPIO1A3_I2S_LRCKTX,
 
        GPIO1A2_SHIFT           = 4,
-       GPIO1A2_MASK            = 6 << GPIO1A2_SHIFT,
+       GPIO1A2_MASK            = 3 << GPIO1A2_SHIFT,
        GPIO1A2_GPIO            = 0,
        GPIO1A2_I2S_LRCKRX,
-       GPIO1A2_I2S_PWM1_0,
+       GPIO1A2_PWM1_0,
 
        GPIO1A1_SHIFT           = 2,
        GPIO1A1_MASK            = 1 << GPIO1A1_SHIFT,
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h b/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h
new file mode 100644 (file)
index 0000000..b40da40
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#ifndef _ASM_ARCH_SDRAM_RK322X_H
+#define _ASM_ARCH_SDRAM_RK322X_H
+
+#include <common.h>
+
+enum {
+       DDR3            = 3,
+       LPDDR2          = 5,
+       LPDDR3          = 6,
+       UNUSED          = 0xFF,
+};
+
+struct rk322x_sdram_channel {
+       /*
+        * bit width in address, eg:
+        * 8 banks using 3 bit to address,
+        * 2 cs using 1 bit to address.
+        */
+       u8 rank;
+       u8 col;
+       u8 bk;
+       u8 bw;
+       u8 dbw;
+       u8 row_3_4;
+       u8 cs0_row;
+       u8 cs1_row;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+       /*
+        * For of-platdata, which would otherwise convert this into two
+        * byte-swapped integers. With a size of 9 bytes, this struct will
+        * appear in of-platdata as a byte array.
+        *
+        * If OF_PLATDATA enabled, need to add a dummy byte in dts.(i.e 0xff)
+        */
+       u8 dummy;
+#endif
+};
+
+struct rk322x_ddr_pctl {
+       u32 scfg;
+       u32 sctl;
+       u32 stat;
+       u32 intrstat;
+       u32 reserved0[(0x40 - 0x10) / 4];
+       u32 mcmd;
+       u32 powctl;
+       u32 powstat;
+       u32 cmdtstat;
+       u32 cmdtstaten;
+       u32 reserved1[(0x60 - 0x54) / 4];
+       u32 mrrcfg0;
+       u32 mrrstat0;
+       u32 mrrstat1;
+       u32 reserved2[(0x7c - 0x6c) / 4];
+
+       u32 mcfg1;
+       u32 mcfg;
+       u32 ppcfg;
+       u32 mstat;
+       u32 lpddr2zqcfg;
+       u32 reserved3;
+
+       u32 dtupdes;
+       u32 dtuna;
+       u32 dtune;
+       u32 dtuprd0;
+       u32 dtuprd1;
+       u32 dtuprd2;
+       u32 dtuprd3;
+       u32 dtuawdt;
+       u32 reserved4[(0xc0 - 0xb4) / 4];
+
+       u32 togcnt1u;
+       u32 tinit;
+       u32 trsth;
+       u32 togcnt100n;
+       u32 trefi;
+       u32 tmrd;
+       u32 trfc;
+       u32 trp;
+       u32 trtw;
+       u32 tal;
+       u32 tcl;
+       u32 tcwl;
+       u32 tras;
+       u32 trc;
+       u32 trcd;
+       u32 trrd;
+       u32 trtp;
+       u32 twr;
+       u32 twtr;
+       u32 texsr;
+       u32 txp;
+       u32 txpdll;
+       u32 tzqcs;
+       u32 tzqcsi;
+       u32 tdqs;
+       u32 tcksre;
+       u32 tcksrx;
+       u32 tcke;
+       u32 tmod;
+       u32 trstl;
+       u32 tzqcl;
+       u32 tmrr;
+       u32 tckesr;
+       u32 tdpd;
+       u32 tref_mem_ddr3;
+       u32 reserved5[(0x180 - 0x14c) / 4];
+       u32 ecccfg;
+       u32 ecctst;
+       u32 eccclr;
+       u32 ecclog;
+       u32 reserved6[(0x200 - 0x190) / 4];
+       u32 dtuwactl;
+       u32 dturactl;
+       u32 dtucfg;
+       u32 dtuectl;
+       u32 dtuwd0;
+       u32 dtuwd1;
+       u32 dtuwd2;
+       u32 dtuwd3;
+       u32 dtuwdm;
+       u32 dturd0;
+       u32 dturd1;
+       u32 dturd2;
+       u32 dturd3;
+       u32 dtulfsrwd;
+       u32 dtulfsrrd;
+       u32 dtueaf;
+       /* dfi control registers */
+       u32 dfitctrldelay;
+       u32 dfiodtcfg;
+       u32 dfiodtcfg1;
+       u32 dfiodtrankmap;
+       /* dfi write data registers */
+       u32 dfitphywrdata;
+       u32 dfitphywrlat;
+       u32 reserved7[(0x260 - 0x258) / 4];
+       u32 dfitrddataen;
+       u32 dfitphyrdlat;
+       u32 reserved8[(0x270 - 0x268) / 4];
+       u32 dfitphyupdtype0;
+       u32 dfitphyupdtype1;
+       u32 dfitphyupdtype2;
+       u32 dfitphyupdtype3;
+       u32 dfitctrlupdmin;
+       u32 dfitctrlupdmax;
+       u32 dfitctrlupddly;
+       u32 reserved9;
+       u32 dfiupdcfg;
+       u32 dfitrefmski;
+       u32 dfitctrlupdi;
+       u32 reserved10[(0x2ac - 0x29c) / 4];
+       u32 dfitrcfg0;
+       u32 dfitrstat0;
+       u32 dfitrwrlvlen;
+       u32 dfitrrdlvlen;
+       u32 dfitrrdlvlgateen;
+       u32 dfiststat0;
+       u32 dfistcfg0;
+       u32 dfistcfg1;
+       u32 reserved11;
+       u32 dfitdramclken;
+       u32 dfitdramclkdis;
+       u32 dfistcfg2;
+       u32 dfistparclr;
+       u32 dfistparlog;
+       u32 reserved12[(0x2f0 - 0x2e4) / 4];
+
+       u32 dfilpcfg0;
+       u32 reserved13[(0x300 - 0x2f4) / 4];
+       u32 dfitrwrlvlresp0;
+       u32 dfitrwrlvlresp1;
+       u32 dfitrwrlvlresp2;
+       u32 dfitrrdlvlresp0;
+       u32 dfitrrdlvlresp1;
+       u32 dfitrrdlvlresp2;
+       u32 dfitrwrlvldelay0;
+       u32 dfitrwrlvldelay1;
+       u32 dfitrwrlvldelay2;
+       u32 dfitrrdlvldelay0;
+       u32 dfitrrdlvldelay1;
+       u32 dfitrrdlvldelay2;
+       u32 dfitrrdlvlgatedelay0;
+       u32 dfitrrdlvlgatedelay1;
+       u32 dfitrrdlvlgatedelay2;
+       u32 dfitrcmd;
+       u32 reserved14[(0x3f8 - 0x340) / 4];
+       u32 ipvr;
+       u32 iptr;
+};
+check_member(rk322x_ddr_pctl, iptr, 0x03fc);
+
+struct rk322x_ddr_phy {
+       u32 ddrphy_reg[0x100];
+};
+
+struct rk322x_pctl_timing {
+       u32 togcnt1u;
+       u32 tinit;
+       u32 trsth;
+       u32 togcnt100n;
+       u32 trefi;
+       u32 tmrd;
+       u32 trfc;
+       u32 trp;
+       u32 trtw;
+       u32 tal;
+       u32 tcl;
+       u32 tcwl;
+       u32 tras;
+       u32 trc;
+       u32 trcd;
+       u32 trrd;
+       u32 trtp;
+       u32 twr;
+       u32 twtr;
+       u32 texsr;
+       u32 txp;
+       u32 txpdll;
+       u32 tzqcs;
+       u32 tzqcsi;
+       u32 tdqs;
+       u32 tcksre;
+       u32 tcksrx;
+       u32 tcke;
+       u32 tmod;
+       u32 trstl;
+       u32 tzqcl;
+       u32 tmrr;
+       u32 tckesr;
+       u32 tdpd;
+       u32 trefi_mem_ddr3;
+};
+
+struct rk322x_phy_timing {
+       u32 mr[4];
+       u32 mr11;
+       u32 bl;
+       u32 cl_al;
+};
+
+struct rk322x_msch_timings {
+       u32 ddrtiming;
+       u32 ddrmode;
+       u32 readlatency;
+       u32 activate;
+       u32 devtodev;
+};
+
+struct rk322x_service_sys {
+       u32 id_coreid;
+       u32 id_revisionid;
+       u32 ddrconf;
+       u32 ddrtiming;
+       u32 ddrmode;
+       u32 readlatency;
+       u32 activate;
+       u32 devtodev;
+};
+
+struct rk322x_base_params {
+       struct rk322x_msch_timings noc_timing;
+       u32 ddrconfig;
+       u32 ddr_freq;
+       u32 dramtype;
+       /*
+        * unused for rk322x
+        */
+       u32 stride;
+       u32 odt;
+};
+
+/* PCT_DFISTCFG0 */
+#define DFI_INIT_START                 BIT(0)
+#define DFI_DATA_BYTE_DISABLE_EN       BIT(2)
+
+/* PCT_DFISTCFG1 */
+#define DFI_DRAM_CLK_SR_EN             BIT(0)
+#define DFI_DRAM_CLK_DPD_EN            BIT(1)
+
+/* PCT_DFISTCFG2 */
+#define DFI_PARITY_INTR_EN             BIT(0)
+#define DFI_PARITY_EN                  BIT(1)
+
+/* PCT_DFILPCFG0 */
+#define TLP_RESP_TIME_SHIFT            16
+#define LP_SR_EN                       BIT(8)
+#define LP_PD_EN                       BIT(0)
+
+/* PCT_DFITCTRLDELAY */
+#define TCTRL_DELAY_TIME_SHIFT         0
+
+/* PCT_DFITPHYWRDATA */
+#define TPHY_WRDATA_TIME_SHIFT         0
+
+/* PCT_DFITPHYRDLAT */
+#define TPHY_RDLAT_TIME_SHIFT          0
+
+/* PCT_DFITDRAMCLKDIS */
+#define TDRAM_CLK_DIS_TIME_SHIFT       0
+
+/* PCT_DFITDRAMCLKEN */
+#define TDRAM_CLK_EN_TIME_SHIFT                0
+
+/* PCTL_DFIODTCFG */
+#define RANK0_ODT_WRITE_SEL            BIT(3)
+#define RANK1_ODT_WRITE_SEL            BIT(11)
+
+/* PCTL_DFIODTCFG1 */
+#define ODT_LEN_BL8_W_SHIFT            16
+
+/* PUBL_ACDLLCR */
+#define ACDLLCR_DLLDIS                 BIT(31)
+#define ACDLLCR_DLLSRST                        BIT(30)
+
+/* PUBL_DXDLLCR */
+#define DXDLLCR_DLLDIS                 BIT(31)
+#define DXDLLCR_DLLSRST                        BIT(30)
+
+/* PUBL_DLLGCR */
+#define DLLGCR_SBIAS                   BIT(30)
+
+/* PUBL_DXGCR */
+#define DQSRTT                         BIT(9)
+#define DQRTT                          BIT(10)
+
+/* PIR */
+#define PIR_INIT                       BIT(0)
+#define PIR_DLLSRST                    BIT(1)
+#define PIR_DLLLOCK                    BIT(2)
+#define PIR_ZCAL                       BIT(3)
+#define PIR_ITMSRST                    BIT(4)
+#define PIR_DRAMRST                    BIT(5)
+#define PIR_DRAMINIT                   BIT(6)
+#define PIR_QSTRN                      BIT(7)
+#define PIR_RVTRN                      BIT(8)
+#define PIR_ICPC                       BIT(16)
+#define PIR_DLLBYP                     BIT(17)
+#define PIR_CTLDINIT                   BIT(18)
+#define PIR_CLRSR                      BIT(28)
+#define PIR_LOCKBYP                    BIT(29)
+#define PIR_ZCALBYP                    BIT(30)
+#define PIR_INITBYP                    BIT(31)
+
+/* PGCR */
+#define PGCR_DFTLMT_SHIFT              3
+#define PGCR_DFTCMP_SHIFT              2
+#define PGCR_DQSCFG_SHIFT              1
+#define PGCR_ITMDMD_SHIFT              0
+
+/* PGSR */
+#define PGSR_IDONE                     BIT(0)
+#define PGSR_DLDONE                    BIT(1)
+#define PGSR_ZCDONE                    BIT(2)
+#define PGSR_DIDONE                    BIT(3)
+#define PGSR_DTDONE                    BIT(4)
+#define PGSR_DTERR                     BIT(5)
+#define PGSR_DTIERR                    BIT(6)
+#define PGSR_DFTERR                    BIT(7)
+#define PGSR_RVERR                     BIT(8)
+#define PGSR_RVEIRR                    BIT(9)
+
+/* PTR0 */
+#define PRT_ITMSRST_SHIFT              18
+#define PRT_DLLLOCK_SHIFT              6
+#define PRT_DLLSRST_SHIFT              0
+
+/* PTR1 */
+#define PRT_DINIT0_SHIFT               0
+#define PRT_DINIT1_SHIFT               19
+
+/* PTR2 */
+#define PRT_DINIT2_SHIFT               0
+#define PRT_DINIT3_SHIFT               17
+
+/* DCR */
+#define DDRMD_LPDDR                    0
+#define DDRMD_DDR                      1
+#define DDRMD_DDR2                     2
+#define DDRMD_DDR3                     3
+#define DDRMD_LPDDR2_LPDDR3            4
+#define DDRMD_MASK                     7
+#define DDRMD_SHIFT                    0
+#define PDQ_MASK                       7
+#define PDQ_SHIFT                      4
+
+/* DXCCR */
+#define DQSNRES_MASK                   0xf
+#define DQSNRES_SHIFT                  8
+#define DQSRES_MASK                    0xf
+#define DQSRES_SHIFT                   4
+
+/* DTPR */
+#define TDQSCKMAX_SHIFT                        27
+#define TDQSCKMAX_MASK                 7
+#define TDQSCK_SHIFT                   24
+#define TDQSCK_MASK                    7
+
+/* DSGCR */
+#define DQSGX_SHIFT                    5
+#define DQSGX_MASK                     7
+#define DQSGE_SHIFT                    8
+#define DQSGE_MASK                     7
+
+/* SCTL */
+#define INIT_STATE                     0
+#define CFG_STATE                      1
+#define GO_STATE                       2
+#define SLEEP_STATE                    3
+#define WAKEUP_STATE                   4
+
+/* STAT */
+#define LP_TRIG_SHIFT                  4
+#define LP_TRIG_MASK                   7
+#define PCTL_STAT_MASK                 7
+#define INIT_MEM                       0
+#define CONFIG                         1
+#define CONFIG_REQ                     2
+#define ACCESS                         3
+#define ACCESS_REQ                     4
+#define LOW_POWER                      5
+#define LOW_POWER_ENTRY_REQ            6
+#define LOW_POWER_EXIT_REQ             7
+
+/* ZQCR*/
+#define PD_OUTPUT_SHIFT                        0
+#define PU_OUTPUT_SHIFT                        5
+#define PD_ONDIE_SHIFT                 10
+#define PU_ONDIE_SHIFT                 15
+#define ZDEN_SHIFT                     28
+
+/* DDLGCR */
+#define SBIAS_BYPASS                   BIT(23)
+
+/* MCFG */
+#define MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT        24
+#define PD_IDLE_SHIFT                  8
+#define MDDR_EN                                (2 << 22)
+#define LPDDR2_EN                      (3 << 22)
+#define LPDDR3_EN                      (1 << 22)
+#define DDR2_EN                                (0 << 5)
+#define DDR3_EN                                (1 << 5)
+#define LPDDR2_S2                      (0 << 6)
+#define LPDDR2_S4                      (1 << 6)
+#define MDDR_LPDDR2_BL_2               (0 << 20)
+#define MDDR_LPDDR2_BL_4               (1 << 20)
+#define MDDR_LPDDR2_BL_8               (2 << 20)
+#define MDDR_LPDDR2_BL_16              (3 << 20)
+#define DDR2_DDR3_BL_4                 0
+#define DDR2_DDR3_BL_8                 1
+#define TFAW_SHIFT                     18
+#define PD_EXIT_SLOW                   (0 << 17)
+#define PD_EXIT_FAST                   (1 << 17)
+#define PD_TYPE_SHIFT                  16
+#define BURSTLENGTH_SHIFT              20
+
+/* POWCTL */
+#define POWER_UP_START                 BIT(0)
+
+/* POWSTAT */
+#define POWER_UP_DONE                  BIT(0)
+
+/* MCMD */
+enum {
+       DESELECT_CMD                    = 0,
+       PREA_CMD,
+       REF_CMD,
+       MRS_CMD,
+       ZQCS_CMD,
+       ZQCL_CMD,
+       RSTL_CMD,
+       MRR_CMD                         = 8,
+       DPDE_CMD,
+};
+
+#define BANK_ADDR_MASK                 7
+#define BANK_ADDR_SHIFT                        17
+#define CMD_ADDR_MASK                  0x1fff
+#define CMD_ADDR_SHIFT                 4
+
+#define LPDDR23_MA_SHIFT               4
+#define LPDDR23_MA_MASK                        0xff
+#define LPDDR23_OP_SHIFT               12
+#define LPDDR23_OP_MASK                        0xff
+
+#define START_CMD                      (1u << 31)
+
+/* DDRPHY REG */
+enum {
+       /* DDRPHY_REG0 */
+       SOFT_RESET_MASK                         = 3,
+       SOFT_DERESET_ANALOG                     = 1 << 2,
+       SOFT_DERESET_DIGITAL                    = 1 << 3,
+       SOFT_RESET_SHIFT                        = 2,
+
+       /* DDRPHY REG1 */
+       PHY_DDR3                                = 0,
+       PHY_DDR2                                = 1,
+       PHY_LPDDR3                              = 2,
+       PHY_LPDDR2                              = 3,
+
+       PHT_BL_8                                = 1 << 2,
+       PHY_BL_4                                = 0 << 2,
+
+       /* DDRPHY_REG2 */
+       MEMORY_SELECT_DDR3                      = 0 << 0,
+       MEMORY_SELECT_LPDDR3                    = 2 << 0,
+       MEMORY_SELECT_LPDDR2                    = 3 << 0,
+       DQS_SQU_CAL_SEL_CS0_CS1                 = 0 << 4,
+       DQS_SQU_CAL_SEL_CS1                     = 1 << 4,
+       DQS_SQU_CAL_SEL_CS0                     = 2 << 4,
+       DQS_SQU_CAL_NORMAL_MODE                 = 0 << 1,
+       DQS_SQU_CAL_BYPASS_MODE                 = 1 << 1,
+       DQS_SQU_CAL_START                       = 1 << 0,
+       DQS_SQU_NO_CAL                          = 0 << 0,
+};
+
+/* CK pull up/down driver strength control */
+enum {
+       PHY_RON_RTT_DISABLE = 0,
+       PHY_RON_RTT_451OHM = 1,
+       PHY_RON_RTT_225OHM,
+       PHY_RON_RTT_150OHM,
+       PHY_RON_RTT_112OHM,
+       PHY_RON_RTT_90OHM,
+       PHY_RON_RTT_75OHM,
+       PHY_RON_RTT_64OHM = 7,
+
+       PHY_RON_RTT_56OHM = 16,
+       PHY_RON_RTT_50OHM,
+       PHY_RON_RTT_45OHM,
+       PHY_RON_RTT_41OHM,
+       PHY_RON_RTT_37OHM,
+       PHY_RON_RTT_34OHM,
+       PHY_RON_RTT_33OHM,
+       PHY_RON_RTT_30OHM = 23,
+
+       PHY_RON_RTT_28OHM = 24,
+       PHY_RON_RTT_26OHM,
+       PHY_RON_RTT_25OHM,
+       PHY_RON_RTT_23OHM,
+       PHY_RON_RTT_22OHM,
+       PHY_RON_RTT_21OHM,
+       PHY_RON_RTT_20OHM,
+       PHY_RON_RTT_19OHM = 31,
+};
+
+/* DQS squelch DLL delay */
+enum {
+       DQS_DLL_NO_DELAY        = 0,
+       DQS_DLL_22P5_DELAY,
+       DQS_DLL_45_DELAY,
+       DQS_DLL_67P5_DELAY,
+       DQS_DLL_90_DELAY,
+       DQS_DLL_112P5_DELAY,
+       DQS_DLL_135_DELAY,
+       DQS_DLL_157P5_DELAY,
+};
+
+/* GRF_SOC_CON0 */
+#define GRF_DDR_16BIT_EN               (((0x1 << 0) << 16) | (0x1 << 0))
+#define GRF_DDR_32BIT_EN               (((0x1 << 0) << 16) | (0x0 << 0))
+#define GRF_MSCH_NOC_16BIT_EN          (((0x1 << 7) << 16) | (0x1 << 7))
+#define GRF_MSCH_NOC_32BIT_EN          (((0x1 << 7) << 16) | (0x0 << 7))
+
+#define GRF_DDRPHY_BUFFEREN_CORE_EN    (((0x1 << 8) << 16) | (0x0 << 8))
+#define GRF_DDRPHY_BUFFEREN_CORE_DIS   (((0x1 << 8) << 16) | (0x1 << 8))
+
+#define GRF_DDR3_EN                    (((0x1 << 6) << 16) | (0x1 << 6))
+#define GRF_LPDDR2_3_EN                        (((0x1 << 6) << 16) | (0x0 << 6))
+
+#define PHY_DRV_ODT_SET(n)             (((n) << 4) | (n))
+#define DDR3_DLL_RESET                 (1 << 8)
+
+#endif /* _ASM_ARCH_SDRAM_RK322X_H */
index 35423e1ba07eaee7648016090771a4a054476b3f..e428d59336a87aa9aff0fa41e2b133b79f259ab5 100644 (file)
@@ -7,4 +7,27 @@
 #ifndef _ASM_ARCH_SYS_PROTO_H
 #define _ASM_ARCH_SYS_PROTO_H
 
+#ifdef CONFIG_ROCKCHIP_RK3288
+#include <asm/armv7.h>
+
+static void configure_l2ctlr(void)
+{
+       uint32_t l2ctlr;
+
+       l2ctlr = read_l2ctlr();
+       l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
+
+       /*
+       * Data RAM write latency: 2 cycles
+       * Data RAM read latency: 2 cycles
+       * Data RAM setup latency: 1 cycle
+       * Tag RAM write latency: 1 cycle
+       * Tag RAM read latency: 1 cycle
+       * Tag RAM setup latency: 1 cycle
+       */
+       l2ctlr |= (1 << 3 | 1 << 0);
+       write_l2ctlr(l2ctlr);
+}
+#endif /* CONFIG_ROCKCHIP_RK3288 */
+
 #endif /* _ASM_ARCH_SYS_PROTO_H */
index a20702e612b1b0a9fd31cc5a5eb141e1fa0894b1..efc515eb3348c902844d165f42f12e6c55ce177e 100644 (file)
 #include <asm/io.h>
 #include <asm/barriers.h>
 
+/* read L2 control register (L2CTLR) */
+static inline uint32_t read_l2ctlr(void)
+{
+       uint32_t val = 0;
+
+       asm volatile ("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+
+       return val;
+}
+
+/* write L2 control register (L2CTLR) */
+static inline void write_l2ctlr(uint32_t val)
+{
+       /*
+        * Note: L2CTLR can only be written when the L2 memory system
+        * is idle, ie before the MMU is enabled.
+        */
+       asm volatile("mcr p15, 1, %0, c9, c0, 2" : : "r" (val) : "memory");
+       isb();
+}
+
 /*
  * Workaround for ARM errata # 798870
  * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been
index 11f5f058b9e0c4772da7fd90c06570d16ba070f5..4dbf9a27da8b046a0221dd5d287715e7c305f09d 100644 (file)
@@ -22,6 +22,11 @@ choice
 
 config TARGET_AM3517_EVM
        bool "AM3517 EVM"
+       select DM
+       select DM_SERIAL
+       select DM_GPIO
+       select DM_I2C
+       select DM_MMC
 
 config TARGET_MT_VENTOUX
        bool "TeeJet Mt.Ventoux"
index 52e1785b4aaa73eae184f59c2d6b67f655d61cba..2630e7d316a0d34af2368d928c7ff12e0e6ab282 100644 (file)
@@ -41,6 +41,9 @@
 #define PPA_SERV_HAL_SETUP_EMIF_FW_REGION   (PPA_HAL_SERVICES_START_INDEX + 26)
 #define PPA_SERV_HAL_LOCK_EMIF_FW           (PPA_HAL_SERVICES_START_INDEX + 27)
 
+/* Offset of header size if image is signed as ISW */
+#define HEADER_SIZE_OFFSET     (0x6D)
+
 int tee_loaded = 0;
 
 /* Argument for PPA_SERV_HAL_TEE_LOAD_MASTER */
@@ -125,6 +128,9 @@ int secure_boot_verify_image(void **image, size_t *size)
        }
 
        *size = sig_addr - cert_addr;   /* Subtract out the signature size */
+       /* Subtract header if present */
+       if (strncmp((char *)sig_addr, "CERT_ISW_", 9) == 0)
+               *size = ((u32 *)*image)[HEADER_SIZE_OFFSET];
        cert_size = *size;
 
        /* Check if image load address is 32-bit aligned */
index 79e9704a2c5fa58a7ec2d849ce564cf639bb9cd3..daafc8de6a8a059298bc942d34e102d144ca4ec8 100644 (file)
@@ -12,6 +12,7 @@ obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
 obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
 
 obj-tpl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
+obj-tpl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-tpl.o
 obj-tpl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-tpl.o
 
 obj-spl-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
index 2dc9511de7f197445b6ff3074fcfd675a388272c..7fa010405b1c96d66a556c3302511c039df3e5f6 100644 (file)
@@ -6,6 +6,5 @@
 
 ifndef CONFIG_TPL_BUILD
 obj-y += clk_rk3188.o
-obj-y += sdram_rk3188.o
 obj-y += syscon_rk3188.o
 endif
index dcd8cf805fe51aa2a1d2fa25aefdb6a3e37a758b..d44311457a4194dc0f99c635cac730ae19ac0e33 100644 (file)
@@ -21,12 +21,12 @@ DECLARE_GLOBAL_DATA_PTR;
 static void setup_boot_mode(void)
 {
        struct rk322x_grf *const grf = (void *)GRF_BASE;
-       int boot_mode = readl(&grf->os_reg[4]);
+       int boot_mode = readl(&grf->os_reg[0]);
 
        debug("boot mode %x.\n", boot_mode);
 
        /* Clear boot mode */
-       writel(BOOT_NORMAL, &grf->os_reg[4]);
+       writel(BOOT_NORMAL, &grf->os_reg[0]);
 
        switch (boot_mode) {
        case BOOT_FASTBOOT:
index 6b7bf85d8d3347aaa3f2363935f971978f1830c0..7b7fd5a6f1a03692f19dc9f21c191a1aa637b013 100644 (file)
 #include <asm/arch/clock.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/periph.h>
+#include <asm/arch/pmu_rk3288.h>
 #include <asm/arch/sdram.h>
+#include <asm/arch/sdram_common.h>
+#include <asm/arch/sys_proto.h>
 #include <asm/arch/timer.h>
 #include <dm/pinctrl.h>
 #include <dm/root.h>
@@ -80,46 +83,6 @@ u32 spl_boot_mode(const u32 boot_device)
        return MMCSD_MODE_RAW;
 }
 
-/* read L2 control register (L2CTLR) */
-static inline uint32_t read_l2ctlr(void)
-{
-       uint32_t val = 0;
-
-       asm volatile ("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
-
-       return val;
-}
-
-/* write L2 control register (L2CTLR) */
-static inline void write_l2ctlr(uint32_t val)
-{
-       /*
-        * Note: L2CTLR can only be written when the L2 memory system
-        * is idle, ie before the MMU is enabled.
-        */
-       asm volatile("mcr p15, 1, %0, c9, c0, 2" : : "r" (val) : "memory");
-       isb();
-}
-
-static void configure_l2ctlr(void)
-{
-       uint32_t l2ctlr;
-
-       l2ctlr = read_l2ctlr();
-       l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
-
-       /*
-       * Data RAM write latency: 2 cycles
-       * Data RAM read latency: 2 cycles
-       * Data RAM setup latency: 1 cycle
-       * Tag RAM write latency: 1 cycle
-       * Tag RAM read latency: 1 cycle
-       * Tag RAM setup latency: 1 cycle
-       */
-       l2ctlr |= (1 << 3 | 1 << 0);
-       write_l2ctlr(l2ctlr);
-}
-
 #ifdef CONFIG_SPL_MMC_SUPPORT
 static int configure_emmc(struct udevice *pinctrl)
 {
@@ -243,12 +206,15 @@ void board_init_f(ulong dummy)
        }
 #endif
 
+#if !defined(CONFIG_SUPPORT_TPL)
        debug("\nspl:init dram\n");
        ret = uclass_get_device(UCLASS_RAM, 0, &dev);
        if (ret) {
                debug("DRAM init failed: %d\n", ret);
                return;
        }
+#endif
+
 #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
        back_to_bootrom();
 #endif
@@ -326,3 +292,18 @@ err:
        /* No way to report error here */
        hang();
 }
+
+#ifdef CONFIG_SPL_OS_BOOT
+
+#define PMU_BASE               0xff730000
+int dram_init_banksize(void)
+{
+       struct rk3288_pmu *const pmu = (void *)PMU_BASE;
+       size_t size = rockchip_sdram_size((phys_addr_t)&pmu->sys_reg[2]);
+
+       gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+       gd->bd->bi_dram[0].size = size;
+
+       return 0;
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rk3288-board-tpl.c b/arch/arm/mach-rockchip/rk3288-board-tpl.c
new file mode 100644 (file)
index 0000000..3d08b5b
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 Amarula Solutions
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <ram.h>
+#include <spl.h>
+#include <version.h>
+#include <asm/io.h>
+#include <asm/arch/bootrom.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/grf_rk3288.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/pmu_rk3288.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define GRF_BASE               0xff770000
+void board_init_f(ulong dummy)
+{
+       struct udevice *dev;
+       int ret;
+
+       /* Example code showing how to enable the debug UART on RK3288 */
+       /* Enable early UART on the RK3288 */
+       struct rk3288_grf * const grf = (void *)GRF_BASE;
+
+       rk_clrsetreg(&grf->gpio7ch_iomux, GPIO7C7_MASK << GPIO7C7_SHIFT |
+                    GPIO7C6_MASK << GPIO7C6_SHIFT,
+                    GPIO7C7_UART2DBG_SOUT << GPIO7C7_SHIFT |
+                    GPIO7C6_UART2DBG_SIN << GPIO7C6_SHIFT);
+       /*
+        * Debug UART can be used from here if required:
+        *
+        * debug_uart_init();
+        * printch('a');
+        * printhex8(0x1234);
+        * printascii("string");
+        */
+       debug_uart_init();
+
+       ret = spl_early_init();
+       if (ret) {
+               debug("spl_early_init() failed: %d\n", ret);
+               hang();
+       }
+
+       rockchip_timer_init();
+       configure_l2ctlr();
+
+       ret = rockchip_get_clk(&dev);
+       if (ret) {
+               debug("CLK init failed: %d\n", ret);
+               return;
+       }
+
+       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+       if (ret) {
+               debug("DRAM init failed: %d\n", ret);
+               return;
+       }
+}
+
+void board_return_to_bootrom(void)
+{
+       back_to_bootrom();
+}
+
+u32 spl_boot_device(void)
+{
+       return BOOT_DEVICE_BOOTROM;
+}
+
+void spl_board_init(void)
+{
+       puts("\nU-Boot TPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
+                               U_BOOT_TIME ")\n");
+}
index 4ad294006949672243638dca6227d43f8b524b3b..6beb26fd7a68a4a09616e2e332132ac25db492fd 100644 (file)
@@ -87,6 +87,22 @@ config TARGET_POPMETAL_RK3288
 config TARGET_VYASA_RK3288
        bool "Vyasa-RK3288"
        select BOARD_LATE_INIT
+       select TPL
+       select SUPPORT_TPL
+       select TPL_DM
+       select TPL_REGMAP
+       select TPL_SYSCON
+       select TPL_CLK
+       select TPL_RAM
+       select TPL_OF_PLATDATA
+       select TPL_OF_CONTROL
+       select TPL_BOOTROM_SUPPORT
+       select TPL_NEEDS_SEPARATE_TEXT_BASE if SPL
+       select ROCKCHIP_BROM_HELPER
+       select TPL_DRIVERS_MISC_SUPPORT
+       select TPL_LIBCOMMON_SUPPORT
+       select TPL_LIBGENERIC_SUPPORT
+       select TPL_SERIAL_SUPPORT
        help
          Vyasa is a RK3288-based development board with 2 USB ports,
          HDMI, VGA, micro-SD card, audio, WiFi  and Gigabit Ethernet, It
index b5b28efbe8163ee2f561ba486940e7e09b2aed6e..a0033a0d845cd5abb16bce30c7049b6c890d6c49 100644 (file)
@@ -6,5 +6,4 @@
 
 obj-y += clk_rk3288.o
 obj-y += rk3288.o
-obj-y += sdram_rk3288.o
 obj-y += syscon_rk3288.o
index 72873e29e6aac1cabf860565cf73f268acb958a4..bbab036a12a5a992dcb160e3f654d7e5ac9aef21 100644 (file)
@@ -6,5 +6,4 @@
 
 obj-y += clk_rk3328.o
 obj-y += rk3328.o
-obj-y += sdram_rk3328.o
 obj-y += syscon_rk3328.o
index 34061564478d165742f3f1abc719f017e77e7014..9c20f56dc949c468bab0589f06f480988d59ecef 100644 (file)
@@ -1,10 +1,12 @@
 /*
  * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #include <common.h>
+#include <asm/arch/bootrom.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/grf_rk3399.h>
 #include <asm/arch/hardware.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+void board_return_to_bootrom(void)
+{
+       back_to_bootrom();
+}
+
+static const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
+       [BROM_BOOTSOURCE_EMMC] = "/sdhci@fe330000",
+       [BROM_BOOTSOURCE_SPINOR] = "/spi@ff1d0000",
+       [BROM_BOOTSOURCE_SD] = "/dwmmc@fe320000",
+};
+
+const char *board_spl_was_booted_from(void)
+{
+       u32  bootdevice_brom_id = readl(RK3399_BROM_BOOTSOURCE_ID_ADDR);
+       const char *bootdevice_ofpath = NULL;
+
+       if (bootdevice_brom_id < ARRAY_SIZE(boot_devices))
+               bootdevice_ofpath = boot_devices[bootdevice_brom_id];
+
+       if (bootdevice_ofpath)
+               debug("%s: brom_bootdevice_id %x maps to '%s'\n",
+                     __func__, bootdevice_brom_id, bootdevice_ofpath);
+       else
+               debug("%s: failed to resolve brom_bootdevice_id %x\n",
+                     __func__, bootdevice_brom_id);
+
+       return bootdevice_ofpath;
+}
+
 u32 spl_boot_device(void)
 {
-       return BOOT_DEVICE_MMC1;
+       u32 boot_device = BOOT_DEVICE_MMC1;
+
+       if (CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM))
+               return BOOT_DEVICE_BOOTROM;
+
+       return boot_device;
 }
 
 u32 spl_boot_mode(const u32 boot_device)
@@ -137,37 +173,6 @@ void board_init_f(ulong dummy)
        }
 }
 
-void spl_board_init(void)
-{
-       struct udevice *pinctrl;
-       int ret;
-
-       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
-       if (ret) {
-               debug("%s: Cannot find pinctrl device\n", __func__);
-               goto err;
-       }
-
-       /* Enable debug UART */
-       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG);
-       if (ret) {
-               debug("%s: Failed to set up console UART\n", __func__);
-               goto err;
-       }
-
-       preloader_console_init();
-#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
-       back_to_bootrom();
-#endif
-
-       return;
-err:
-       printf("spl_board_init: Error %d\n", ret);
-
-       /* No way to report error here */
-       hang();
-}
-
 #ifdef CONFIG_SPL_LOAD_FIT
 int board_fit_config_name_match(const char *name)
 {
index 793ce31c12c553f6568cfee65dbaa773e063cec9..98ebeac340d8ccdebaafa003b3a8127ad21b3ce1 100644 (file)
@@ -6,5 +6,4 @@
 
 obj-y += clk_rk3399.o
 obj-y += rk3399.o
-obj-y += sdram_rk3399.o
 obj-y += syscon_rk3399.o
index 4f78c72720948e9adc77ae1c3437d096d5c5dca9..843998dfdcb8d256bbb5966761273e40805646c6 100644 (file)
 #include <spl.h>
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
+/**
+ * spl_node_to_boot_device() - maps from a DT-node to a SPL boot device
+ * @node:      of_offset of the node
+ *
+ * The SPL framework uses BOOT_DEVICE_... constants to identify its boot
+ * sources.  These may take on a device-specific meaning, depending on
+ * what nodes are enabled in a DTS (e.g. BOOT_DEVICE_MMC1 may refer to
+ * different controllers/block-devices, depending on which SD/MMC controllers
+ * are enabled in any given DTS).  This function maps from a DT-node back
+ * onto a BOOT_DEVICE_... constant, considering the currently active devices.
+ *
+ * Returns
+ *   -ENOENT, if no device matching the node could be found
+ *   -ENOSYS, if the device matching the node can not be mapped onto a
+ *            SPL boot device (e.g. the third MMC device)
+ *   -1, for unspecified failures
+ *   a positive integer (from the BOOT_DEVICE_... family) on succes.
+ */
+
 static int spl_node_to_boot_device(int node)
 {
        struct udevice *parent;
@@ -57,6 +76,24 @@ static int spl_node_to_boot_device(int node)
        return -1;
 }
 
+/**
+ * board_spl_was_booted_from() - retrieves the of-path the SPL was loaded from
+ *
+ * To support a 'same-as-spl' specification in the search-order for the next
+ * stage, we need a SoC- or board-specific way to handshake with what 'came
+ * before us' (either a BROM or TPL stage) and map the info retrieved onto
+ * a OF path.
+ *
+ * Returns
+ *   NULL, on failure or if the device could not be identified
+ *   a of_path (a string), on success
+ */
+__weak const char *board_spl_was_booted_from(void)
+{
+       debug("%s: no support for 'same-as-spl' for this board\n", __func__);
+       return NULL;
+}
+
 void board_boot_order(u32 *spl_boot_list)
 {
        const void *blob = gd->fdt_blob;
@@ -78,8 +115,17 @@ void board_boot_order(u32 *spl_boot_list)
             (conf = fdt_stringlist_get(blob, chosen_node,
                                        "u-boot,spl-boot-order", elem, NULL));
             elem++) {
+               const char *alias;
+
+               /* Handle the case of 'same device the SPL was loaded from' */
+               if (strncmp(conf, "same-as-spl", 11) == 0) {
+                       conf = board_spl_was_booted_from();
+                       if (!conf)
+                               continue;
+               }
+
                /* First check if the list element is an alias */
-               const char *alias = fdt_get_alias(blob, conf);
+               alias = fdt_get_alias(blob, conf);
                if (alias)
                        conf = alias;
 
index e8ee9615264cf89c00e5e2f24680706d2c217495..25ef9a46c6d4622ba2de1276f3701680d23617af 100644 (file)
@@ -125,26 +125,26 @@ extern void __raw_readsl(unsigned int addr, void *data, int longlen);
 #define __iormb()      dmb()
 #define __iowmb()      dmb()
 
-static inline void writeb(unsigned char val, unsigned char *addr)
+static inline void writeb(u8 val, volatile void __iomem *addr)
 {
        __iowmb();
        __arch_putb(val, addr);
 }
 
-static inline void writew(unsigned short val, unsigned short *addr)
+static inline void writew(u16 val, volatile void __iomem *addr)
 {
        __iowmb();
        __arch_putw(val, addr);
 
 }
 
-static inline void writel(unsigned int val, unsigned int *addr)
+static inline void writel(u32 val, volatile void __iomem *addr)
 {
        __iowmb();
        __arch_putl(val, addr);
 }
 
-static inline unsigned char readb(unsigned char *addr)
+static inline u8 readb(const volatile void __iomem *addr)
 {
        u8      val;
 
@@ -153,7 +153,7 @@ static inline unsigned char readb(unsigned char *addr)
        return val;
 }
 
-static inline unsigned short readw(unsigned short *addr)
+static inline u16 readw(const volatile void __iomem *addr)
 {
        u16     val;
 
@@ -162,7 +162,7 @@ static inline unsigned short readw(unsigned short *addr)
        return val;
 }
 
-static inline unsigned int readl(unsigned int *addr)
+static inline u32 readl(const volatile void __iomem *addr)
 {
        u32     val;
 
index ceee42c16e24591a57ebba90fb42e8b1cc036dfe..7985671fbd708a12bc0ea01d42729d77a6aeff1d 100644 (file)
@@ -5,3 +5,16 @@
  */
 
 #include <common.h>
+
+#ifndef CONFIG_TPL_BUILD
+#include <spl.h>
+
+int spl_start_uboot(void)
+{
+        /* break into full u-boot on 'c' */
+        if (serial_tstc() && serial_getc() == 'c')
+                return 1;
+
+        return 0;
+}
+#endif
index bb1188b4ea2d27ed3efd8225301755b0adc1548c..e0df97ca0ea4558244fb7e9716aabf5df70f4514 100644 (file)
@@ -33,6 +33,8 @@ config MAC_ADDR_IN_EEPROM
 
 endif
 
+source "board/ti/common/Kconfig"
+
 endif
 
 if TARGET_OMAPL138_LCDK
index 516d86df5097208c7b0d93595934f44c17adf8f4..83c9f2940fe87791908d6c7a739ad14bd98ad4ee 100644 (file)
@@ -60,7 +60,7 @@ static int get_mac_addr(u8 *addr)
                return -1;
        }
 
-       ret = spi_flash_read(flash, CFG_MAC_ADDR_OFFSET, 6, addr);
+       ret = spi_flash_read(flash, (CFG_MAC_ADDR_OFFSET) + 1, 7, addr);
        if (ret) {
                printf("Error - unable to read MAC address from SPI flash.\n");
                return -1;
@@ -140,6 +140,7 @@ int misc_init_r(void)
        uchar buff[6];
 
        spi_mac_read = get_mac_addr(buff);
+       buff[0] = 0;
 
        /*
         * MAC address not present in the environment
index c18a5a3140b9323ce01535deabc0899d4e95d5d8..29f136a530686c95c553a0d0e05c4f5a436b2f75 100644 (file)
@@ -12,6 +12,8 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <ns16550.h>
 #include <asm/io.h>
 #include <asm/omap_musb.h>
 #include <asm/arch/am35x_def.h>
@@ -34,6 +36,22 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define AM3517_IP_SW_RESET     0x48002598
 #define CPGMACSS_SW_RST                (1 << 1)
+#define PHY_GPIO               30
+
+/* This is only needed until SPL gets OF support */
+#ifdef CONFIG_SPL_BUILD
+static const struct ns16550_platdata am3517_serial = {
+       .base = OMAP34XX_UART3,
+       .reg_shift = 2,
+       .clock = V_NS16550_CLK,
+       .fcr = UART_FCR_DEFVAL,
+};
+
+U_BOOT_DEVICE(am3517_uart) = {
+       "ns16550_serial",
+       &am3517_serial
+};
+#endif
 
 /*
  * Routine: board_init
@@ -113,30 +131,35 @@ int misc_init_r(void)
 
        am3517_evm_musb_init();
 
-       /* activate PHY reset */
-       gpio_direction_output(30, 0);
-       gpio_set_value(30, 0);
-
-       ctr  = 0;
-       do {
-               udelay(1000);
-               ctr++;
-       } while (ctr < 300);
-
-       /* deactivate PHY reset */
-       gpio_set_value(30, 1);
-
-       /* allow the PHY to stabilize and settle down */
-       ctr = 0;
-       do {
-               udelay(1000);
-               ctr++;
-       } while (ctr < 300);
-
-       /* ensure that the module is out of reset */
-       reset = readl(AM3517_IP_SW_RESET);
-       reset &= (~CPGMACSS_SW_RST);
-       writel(reset,AM3517_IP_SW_RESET);
+       if (gpio_request(PHY_GPIO, "gpio_30") == 0) {
+               /* activate PHY reset */
+               gpio_direction_output(PHY_GPIO, 0);
+               gpio_set_value(PHY_GPIO, 0);
+
+               ctr  = 0;
+               do {
+                       udelay(1000);
+                       ctr++;
+               } while (ctr < 300);
+
+               /* deactivate PHY reset */
+               gpio_set_value(PHY_GPIO, 1);
+
+               /* allow the PHY to stabilize and settle down */
+               ctr = 0;
+               do {
+                       udelay(1000);
+                       ctr++;
+               } while (ctr < 300);
+
+               /* ensure that the module is out of reset */
+               reset = readl(AM3517_IP_SW_RESET);
+               reset &= (~CPGMACSS_SW_RST);
+               writel(reset, AM3517_IP_SW_RESET);
+
+               /* Free requested GPIO */
+               gpio_free(PHY_GPIO);
+       }
 
        return 0;
 }
index d50c59db8dde5df228324c5f99b7550657f26e3b..502dec325fc12d66a7e040e8cfd61b5e5b7c4e2d 100644 (file)
@@ -3,13 +3,14 @@
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
+
 #include <common.h>
 #include <dm.h>
-#include <ram.h>
 #include <dm/pinctrl.h>
 #include <dm/uclass-internal.h>
 #include <asm/arch/periph.h>
 #include <power/regulator.h>
+#include <spl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -67,3 +68,30 @@ int board_init(void)
 out:
        return 0;
 }
+
+void spl_board_init(void)
+{
+       struct udevice *pinctrl;
+       int ret;
+
+       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+       if (ret) {
+               debug("%s: Cannot find pinctrl device\n", __func__);
+               goto err;
+       }
+
+       /* Enable debug UART */
+       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG);
+       if (ret) {
+               debug("%s: Failed to set up console UART\n", __func__);
+               goto err;
+       }
+
+       preloader_console_init();
+       return;
+err:
+       printf("%s: Error %d\n", __func__, ret);
+
+       /* No way to report error here */
+       hang();
+}
index 405750f3517b5588428626a9b136044b736d3868..60daddcc44143fb90d2ae75a3430ce7cf95c12b9 100644 (file)
@@ -27,8 +27,8 @@
                        type = "firmware";
                        arch = "arm64";
                        compression = "none";
-                       load = <0x00010000>;
-                       entry = <0x00010000>;
+                       load = <0x00100000>;
+                       entry = <0x00100000>;
                };
 
                fdt {
index 45d56cd99eb26adb15edfff8572e9ee9998972ce..2b4988e2d2255a306f4aa213c5cf450a65fca0f7 100644 (file)
@@ -3,60 +3,48 @@
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
+
 #include <common.h>
 #include <dm.h>
 #include <misc.h>
-#include <ram.h>
 #include <dm/pinctrl.h>
 #include <dm/uclass-internal.h>
 #include <asm/setup.h>
 #include <asm/arch/periph.h>
 #include <power/regulator.h>
+#include <spl.h>
 #include <u-boot/sha256.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
 int board_init(void)
 {
-       struct udevice *pinctrl, *regulator;
        int ret;
 
        /*
-        * The PWM does not have decicated interrupt number in dts and can
-        * not get periph_id by pinctrl framework, so let's init them here.
-        * The PWM2 and PWM3 are for pwm regulators.
+        * We need to call into regulators_enable_boot_on() again, as the call
+        * during SPL may have not included all regulators.
         */
-       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
-       if (ret) {
-               debug("%s: Cannot find pinctrl device\n", __func__);
-               goto out;
-       }
-
-       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_PWM2);
-       if (ret) {
-               debug("%s PWM2 pinctrl init fail!\n", __func__);
-               goto out;
-       }
-
-       /* rk3399 need to init vdd_center to get the correct output voltage */
-       ret = regulator_get_by_platname("vdd_center", &regulator);
+       ret = regulators_enable_boot_on(false);
        if (ret)
-               debug("%s: Cannot get vdd_center regulator\n", __func__);
+               debug("%s: Cannot enable boot on regulator\n", __func__);
 
-       ret = regulator_get_by_platname("vcc5v0_host", &regulator);
-       if (ret) {
-               debug("%s vcc5v0_host init fail! ret %d\n", __func__, ret);
-               goto out;
-       }
+       return 0;
+}
 
-       ret = regulator_set_enable(regulator, true);
-       if (ret) {
-               debug("%s vcc5v0-host-en set fail!\n", __func__);
-               goto out;
-       }
+void spl_board_init(void)
+{
+       int  ret;
 
-out:
-       return 0;
+       /*
+        * Turning the eMMC and SPI back on (if disabled via the Qseven
+        * BIOS_ENABLE) signal is done through a always-on regulator).
+        */
+       ret = regulators_enable_boot_on(false);
+       if (ret)
+               debug("%s: Cannot enable boot on regulator\n", __func__);
+
+       preloader_console_init();
 }
 
 static void setup_macaddr(void)
@@ -91,8 +79,6 @@ static void setup_macaddr(void)
        mac_addr[0] |= 0x02;  /* set local assignment bit (IEEE802) */
        eth_env_set_enetaddr("ethaddr", mac_addr);
 #endif
-
-       return;
 }
 
 static void setup_serial(void)
@@ -147,8 +133,6 @@ static void setup_serial(void)
        env_set("cpuid#", cpuid_str);
        env_set("serial#", serialno_str);
 #endif
-
-       return;
 }
 
 int misc_init_r(void)
index d6d130edfa917c7f6af938be710e0f4e581d8276..3ef9b16b082169189facfadd3ffbeba27d4b21ae 100644 (file)
@@ -222,6 +222,8 @@ config CMD_BOOTEFI_HELLO
          for testing that EFI is working at a basic level, and for bringing
          up EFI support on a new architecture.
 
+source lib/efi_selftest/Kconfig
+
 config CMD_BOOTMENU
        bool "bootmenu"
        select MENU
index 3196d86040729487186c241e9b7c36d597bbb6f2..b7087e3da874e7f14745dc63dfbf62458bf80795 100644 (file)
@@ -22,97 +22,14 @@ DECLARE_GLOBAL_DATA_PTR;
 
 static uint8_t efi_obj_list_initalized;
 
-/*
- * When booting using the "bootefi" command, we don't know which
- * physical device the file came from. So we create a pseudo-device
- * called "bootefi" with the device path /bootefi.
- *
- * In addition to the originating device we also declare the file path
- * of "bootefi" based loads to be /bootefi.
- */
-static struct efi_device_path_file_path bootefi_image_path[] = {
-       {
-               .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
-               .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
-               .dp.length = sizeof(bootefi_image_path[0]),
-               .str = { 'b','o','o','t','e','f','i' },
-       }, {
-               .dp.type = DEVICE_PATH_TYPE_END,
-               .dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
-               .dp.length = sizeof(bootefi_image_path[0]),
-       }
-};
-
-static struct efi_device_path_file_path bootefi_device_path[] = {
-       {
-               .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
-               .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
-               .dp.length = sizeof(bootefi_image_path[0]),
-               .str = { 'b','o','o','t','e','f','i' },
-       }, {
-               .dp.type = DEVICE_PATH_TYPE_END,
-               .dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
-               .dp.length = sizeof(bootefi_image_path[0]),
-       }
-};
-
-/* The EFI loaded_image interface for the image executed via "bootefi" */
-static struct efi_loaded_image loaded_image_info = {
-       .device_handle = bootefi_device_path,
-       .file_path = bootefi_image_path,
-};
-
-/* The EFI object struct for the image executed via "bootefi" */
-static struct efi_object loaded_image_info_obj = {
-       .handle = &loaded_image_info,
-       .protocols = {
-               {
-                       /*
-                        * When asking for the loaded_image interface, just
-                        * return handle which points to loaded_image_info
-                        */
-                       .guid = &efi_guid_loaded_image,
-                       .protocol_interface = &loaded_image_info,
-               },
-               {
-                       /*
-                        * When asking for the device path interface, return
-                        * bootefi_device_path
-                        */
-                       .guid = &efi_guid_device_path,
-                       .protocol_interface = bootefi_device_path,
-               },
-               {
-                       .guid = &efi_guid_console_control,
-                       .protocol_interface = (void *) &efi_console_control
-               },
-               {
-                       .guid = &efi_guid_device_path_to_text_protocol,
-                       .protocol_interface = (void *) &efi_device_path_to_text
-               },
-       },
-};
-
-/* The EFI object struct for the device the "bootefi" image was loaded from */
-static struct efi_object bootefi_device_obj = {
-       .handle = bootefi_device_path,
-       .protocols = {
-               {
-                       /* When asking for the device path interface, return
-                        * bootefi_device_path */
-                       .guid = &efi_guid_device_path,
-                       .protocol_interface = bootefi_device_path
-               }
-       },
-};
+static struct efi_device_path *bootefi_image_path;
+static struct efi_device_path *bootefi_device_path;
 
 /* Initialize and populate EFI object list */
 static void efi_init_obj_list(void)
 {
        efi_obj_list_initalized = 1;
 
-       list_add_tail(&loaded_image_info_obj.link, &efi_obj_list);
-       list_add_tail(&bootefi_device_obj.link, &efi_obj_list);
        efi_console_register();
 #ifdef CONFIG_PARTITIONS
        efi_disk_register();
@@ -121,13 +38,7 @@ static void efi_init_obj_list(void)
        efi_gop_register();
 #endif
 #ifdef CONFIG_NET
-       void *nethandle = loaded_image_info.device_handle;
-       efi_net_register(&nethandle);
-
-       if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6))
-               loaded_image_info.device_handle = nethandle;
-       else
-               loaded_image_info.device_handle = bootefi_device_path;
+       efi_net_register();
 #endif
 #ifdef CONFIG_GENERATE_SMBIOS_TABLE
        efi_smbios_register();
@@ -210,14 +121,27 @@ static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)(
  * Load an EFI payload into a newly allocated piece of memory, register all
  * EFI objects it would want to access and jump to it.
  */
-static unsigned long do_bootefi_exec(void *efi, void *fdt)
+static unsigned long do_bootefi_exec(void *efi, void *fdt,
+                                    struct efi_device_path *device_path,
+                                    struct efi_device_path *image_path)
 {
+       struct efi_loaded_image loaded_image_info = {};
+       struct efi_object loaded_image_info_obj = {};
+       ulong ret;
+
        ulong (*entry)(void *image_handle, struct efi_system_table *st)
                asmlinkage;
        ulong fdt_pages, fdt_size, fdt_start, fdt_end;
        const efi_guid_t fdt_guid = EFI_FDT_GUID;
        bootm_headers_t img = { 0 };
 
+       /* Initialize and populate EFI object list */
+       if (!efi_obj_list_initalized)
+               efi_init_obj_list();
+
+       efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj,
+                              device_path, image_path);
+
        /*
         * gd lives in a fixed register which may get clobbered while we execute
         * the payload. So save it here and restore it on every callback entry
@@ -252,18 +176,21 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt)
 
        /* Load the EFI payload */
        entry = efi_load_pe(efi, &loaded_image_info);
-       if (!entry)
-               return -ENOENT;
+       if (!entry) {
+               ret = -ENOENT;
+               goto exit;
+       }
 
-       /* Initialize and populate EFI object list */
-       if (!efi_obj_list_initalized)
-               efi_init_obj_list();
+       /* we don't support much: */
+       env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported",
+               "{ro,boot}(blob)0000000000000000");
 
        /* Call our payload! */
        debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
 
        if (setjmp(&loaded_image_info.exit_jmp)) {
-               return loaded_image_info.exit_status;
+               ret = loaded_image_info.exit_status;
+               goto exit;
        }
 
 #ifdef CONFIG_ARM64
@@ -282,9 +209,45 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt)
        }
 #endif
 
-       return efi_do_enter(&loaded_image_info, &systab, entry);
+       ret = efi_do_enter(&loaded_image_info, &systab, entry);
+
+exit:
+       /* image has returned, loaded-image obj goes *poof*: */
+       list_del(&loaded_image_info_obj.link);
+
+       return ret;
 }
 
+static int do_bootefi_bootmgr_exec(unsigned long fdt_addr)
+{
+       struct efi_device_path *device_path, *file_path;
+       void *addr;
+       efi_status_t r;
+
+       /* Initialize and populate EFI object list */
+       if (!efi_obj_list_initalized)
+               efi_init_obj_list();
+
+       /*
+        * gd lives in a fixed register which may get clobbered while we execute
+        * the payload. So save it here and restore it on every callback entry
+        */
+       efi_save_gd();
+
+       addr = efi_bootmgr_load(&device_path, &file_path);
+       if (!addr)
+               return 1;
+
+       printf("## Starting EFI application at %p ...\n", addr);
+       r = do_bootefi_exec(addr, (void *)fdt_addr, device_path, file_path);
+       printf("## Application terminated, r = %lu\n",
+              r & ~EFI_ERROR_MASK);
+
+       if (r != EFI_SUCCESS)
+               return 1;
+
+       return 0;
+}
 
 /* Interpreter command to boot an arbitrary EFI image from memory */
 static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -297,13 +260,44 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                return CMD_RET_USAGE;
 #ifdef CONFIG_CMD_BOOTEFI_HELLO
        if (!strcmp(argv[1], "hello")) {
-               ulong size = __efi_hello_world_end - __efi_hello_world_begin;
-
-               addr = CONFIG_SYS_LOAD_ADDR;
-               memcpy((char *)addr, __efi_hello_world_begin, size);
+               ulong size = __efi_helloworld_end - __efi_helloworld_begin;
+
+               saddr = env_get("loadaddr");
+               if (saddr)
+                       addr = simple_strtoul(saddr, NULL, 16);
+               else
+                       addr = CONFIG_SYS_LOAD_ADDR;
+               memcpy((char *)addr, __efi_helloworld_begin, size);
        } else
 #endif
-       {
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
+       if (!strcmp(argv[1], "selftest")) {
+               struct efi_loaded_image loaded_image_info = {};
+               struct efi_object loaded_image_info_obj = {};
+
+               efi_setup_loaded_image(&loaded_image_info,
+                                      &loaded_image_info_obj,
+                                      bootefi_device_path, bootefi_image_path);
+               /*
+                * gd lives in a fixed register which may get clobbered while we
+                * execute the payload. So save it here and restore it on every
+                * callback entry
+                */
+               efi_save_gd();
+               /* Initialize and populate EFI object list */
+               if (!efi_obj_list_initalized)
+                       efi_init_obj_list();
+               return efi_selftest(&loaded_image_info, &systab);
+       } else
+#endif
+       if (!strcmp(argv[1], "bootmgr")) {
+               unsigned long fdt_addr = 0;
+
+               if (argc > 2)
+                       fdt_addr = simple_strtoul(argv[2], NULL, 16);
+
+               return do_bootefi_bootmgr_exec(fdt_addr);
+       } else {
                saddr = argv[1];
 
                addr = simple_strtoul(saddr, NULL, 16);
@@ -315,7 +309,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        }
 
        printf("## Starting EFI application at %08lx ...\n", addr);
-       r = do_bootefi_exec((void *)addr, (void*)fdt_addr);
+       r = do_bootefi_exec((void *)addr, (void *)fdt_addr,
+                           bootefi_device_path, bootefi_image_path);
        printf("## Application terminated, r = %lu\n",
               r & ~EFI_ERROR_MASK);
 
@@ -332,10 +327,18 @@ static char bootefi_help_text[] =
        "    If specified, the device tree located at <fdt address> gets\n"
        "    exposed as EFI configuration table.\n"
 #ifdef CONFIG_CMD_BOOTEFI_HELLO
-       "hello\n"
-       "  - boot a sample Hello World application stored within U-Boot"
+       "bootefi hello\n"
+       "  - boot a sample Hello World application stored within U-Boot\n"
+#endif
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
+       "bootefi selftest\n"
+       "  - boot an EFI selftest application stored within U-Boot\n"
 #endif
-       ;
+       "bootmgr [fdt addr]\n"
+       "  - load and boot EFI payload based on BootOrder/BootXXXX variables.\n"
+       "\n"
+       "    If specified, the device tree located at <fdt address> gets\n"
+       "    exposed as EFI configuration table.\n";
 #endif
 
 U_BOOT_CMD(
@@ -344,58 +347,47 @@ U_BOOT_CMD(
        bootefi_help_text
 );
 
-void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
+static int parse_partnum(const char *devnr)
 {
-       __maybe_unused struct blk_desc *desc;
-       char devname[32] = { 0 }; /* dp->str is u16[32] long */
-       char *colon, *s;
-
-#if defined(CONFIG_BLK) || CONFIG_IS_ENABLED(ISO_PARTITION)
-       desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
-#endif
-
-#ifdef CONFIG_BLK
-       if (desc) {
-               snprintf(devname, sizeof(devname), "%s", desc->bdev->name);
-       } else
-#endif
-
-       {
-               /* Assemble the condensed device name we use in efi_disk.c */
-               snprintf(devname, sizeof(devname), "%s%s", dev, devnr);
+       const char *str = strchr(devnr, ':');
+       if (str) {
+               str++;
+               return simple_strtoul(str, NULL, 16);
        }
+       return 0;
+}
+
+void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
+{
+       char filename[32] = { 0 }; /* dp->str is u16[32] long */
+       char *s;
 
-       colon = strchr(devname, ':');
+       if (strcmp(dev, "Net")) {
+               struct blk_desc *desc;
+               int part;
 
-#if CONFIG_IS_ENABLED(ISO_PARTITION)
-       /* For ISOs we create partition block devices */
-       if (desc && (desc->type != DEV_TYPE_UNKNOWN) &&
-           (desc->part_type == PART_TYPE_ISO)) {
-               if (!colon)
-                       snprintf(devname, sizeof(devname), "%s:1", devname);
+               desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
+               part = parse_partnum(devnr);
 
-               colon = NULL;
-       }
+               bootefi_device_path = efi_dp_from_part(desc, part);
+       } else {
+#ifdef CONFIG_NET
+               bootefi_device_path = efi_dp_from_eth();
 #endif
+       }
 
-       if (colon)
-               *colon = '\0';
-
-       /* Patch bootefi_device_path to the target device */
-       memset(bootefi_device_path[0].str, 0, sizeof(bootefi_device_path[0].str));
-       ascii2unicode(bootefi_device_path[0].str, devname);
+       if (!path)
+               return;
 
-       /* Patch bootefi_image_path to the target file path */
-       memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str));
        if (strcmp(dev, "Net")) {
                /* Add leading / to fs paths, because they're absolute */
-               snprintf(devname, sizeof(devname), "/%s", path);
+               snprintf(filename, sizeof(filename), "/%s", path);
        } else {
-               snprintf(devname, sizeof(devname), "%s", path);
+               snprintf(filename, sizeof(filename), "%s", path);
        }
        /* DOS style file path: */
-       s = devname;
+       s = filename;
        while ((s = strchr(s, '/')))
                *s++ = '\\';
-       ascii2unicode(bootefi_image_path[0].str, devname);
+       bootefi_image_path = efi_dp_from_file(NULL, 0, filename);
 }
index b05ec21ed62e6a8157a498513880aea749f0b7c0..0bd8370337bcc5bd5d7d551abee2c49880535a76 100644 (file)
@@ -94,6 +94,7 @@ config SPL_STACK_R
 config SPL_STACK_R_ADDR
        depends on SPL_STACK_R
        hex "SDRAM location for SPL stack"
+       default 0x82000000 if ARCH_OMAP2PLUS
        help
          Specify the address in SDRAM for the SPL stack. This will be set up
          before board_init_r() is called.
index b2cccc6c6e41ca450e49cd68fc28516187d8372e..b57e0b04e46a3174a5ccead5c2489eb9c2ade1f0 100644 (file)
@@ -52,8 +52,9 @@ static ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
        return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf);
 }
 
-static int mmc_load_image_raw_sector(struct spl_image_info *spl_image,
-                                    struct mmc *mmc, unsigned long sector)
+static __maybe_unused
+int mmc_load_image_raw_sector(struct spl_image_info *spl_image,
+                             struct mmc *mmc, unsigned long sector)
 {
        unsigned long count;
        struct image_header *header;
index eb8338f0f10d40d2a317fadb29fd7caa9eeedac6..2842694dbc80702e2e089167f679b8c532d3d70d 100644 (file)
@@ -10,7 +10,6 @@ CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
@@ -18,7 +17,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_MTD_SUPPORT=y
index b8526fc15ed3fe4567474bf799daa3ade48af3e4..2fc25fbaaba111b635643c4fd5bd5f554dcd7907 100644 (file)
@@ -3,14 +3,12 @@ CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
 # CONFIG_SPL_NAND_SUPPORT is not set
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_AUTOBOOT_KEYED=y
index 0a239bb73399175569143388ef5487aaa168c6a7..e8bcb6d0c8b5a9903224a8d27c9c810e7fc1e6eb 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
 # CONFIG_SPL_NAND_SUPPORT is not set
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am335x-boneblack"
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_FIT_SIGNATURE=y
@@ -13,7 +12,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_AUTOBOOT_KEYED=y
index 00c1af43449d74442feed23241b860375118035a..b6a7cf0e5c5f62bfbfc0b10fe36ef84d996b7b0a 100644 (file)
@@ -2,7 +2,6 @@ CONFIG_ARM=y
 CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am335x-evm"
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SPL_LOAD_FIT=y
@@ -10,7 +9,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
index 9f08edff4ca50da7f852e0d11f9e6bbfdb7fcd9c..e2fc822c2f4089a19480d246e23418de19d2785b 100644 (file)
@@ -3,13 +3,11 @@ CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
 CONFIG_NOR=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
index 501fb2b90f4d619515451c9cd154db915723b267..a53e5aee836393e09878f4175d760eb5487daa9a 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_AM33XX=y
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_EXTRA_OPTIONS="SPI_BOOT"
 CONFIG_SPI_BOOT=y
@@ -13,7 +12,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_FASTBOOT=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
index 7c351382d96c1b5bff93b5eef34feaf75a92d20b..7b003ee7773d6c6af9841bdd259751a7ebcb62e3 100644 (file)
@@ -3,14 +3,12 @@ CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
 # CONFIG_SPL_NAND_SUPPORT is not set
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DISTRO_DEFAULTS=y
 # CONFIG_ANDROID_BOOT_IMAGE is not set
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_NET_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
index acdd56b43558c04e7a90348d90e32567dd7b1726..af5233c5fc4986d1c48cb4f9444ee2c349d81ee1 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_AM33XX=y
 CONFIG_TI_SECURE_DEVICE=y
 CONFIG_ISW_ENTRY_ADDR=0x40300350
 # CONFIG_SPL_NAND_SUPPORT is not set
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am335x-evm"
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_ANDROID_BOOT_IMAGE=y
@@ -16,7 +15,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 # CONFIG_SPL_ENV_SUPPORT is not set
 # CONFIG_SPL_EXT_SUPPORT is not set
 CONFIG_SPL_MTD_SUPPORT=y
diff --git a/configs/am335x_hs_evm_uart_defconfig b/configs/am335x_hs_evm_uart_defconfig
new file mode 100644 (file)
index 0000000..1c453fb
--- /dev/null
@@ -0,0 +1,67 @@
+CONFIG_ARM=y
+CONFIG_ARCH_OMAP2PLUS=y
+CONFIG_TI_COMMON_CMD_OPTIONS=y
+CONFIG_AM33XX=y
+# CONFIG_SPL_FAT_SUPPORT is not set
+# CONFIG_SPL_LIBDISK_SUPPORT is not set
+# CONFIG_SPL_MMC_SUPPORT is not set
+# CONFIG_SPL_NAND_SUPPORT is not set
+CONFIG_TI_SECURE_DEVICE=y
+CONFIG_ISW_ENTRY_ADDR=0x40301950
+CONFIG_SPL_STACK_R_ADDR=0x82000000
+CONFIG_DEFAULT_DEVICE_TREE="am335x-evm"
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT_IMAGE_POST_PROCESS=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_VERSION_VARIABLE=y
+CONFIG_ARCH_MISC_INIT=y
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_STACK_R=y
+# CONFIG_SPL_ENV_SUPPORT is not set
+# CONFIG_SPL_EXT_SUPPORT is not set
+CONFIG_SPL_MTD_SUPPORT=y
+# CONFIG_SPL_YMODEM_SUPPORT is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_NAND=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_MTDPARTS=y
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIST="am335x-evm am335x-bone am335x-boneblack am335x-evmsk am335x-bonegreen am335x-icev2"
+# CONFIG_BLK is not set
+CONFIG_DFU_MMC=y
+CONFIG_DFU_NAND=y
+CONFIG_DFU_RAM=y
+CONFIG_DM_I2C=y
+CONFIG_MISC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_NAND=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_PHYLIB=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
+CONFIG_TIMER=y
+CONFIG_OMAP_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_TI=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
+CONFIG_G_DNL_VENDOR_NUM=0x0451
+CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_RSA=y
+CONFIG_LZO=y
+CONFIG_OF_LIBFDT_OVERLAY=y
index 1b03c334b4a49a81ca3993aa317b0500032a4103..f344a7367d683477462cde72565857dbf190278d 100644 (file)
@@ -11,14 +11,12 @@ CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_SYS_EXTRA_OPTIONS="MACH_TYPE=MACH_TYPE_IGEP0033"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_MTD_SUPPORT=y
index c63e388ff51cd552b670242a14b4dfa23214630e..0b29290cf52e30c0ffbb0c987a86a8da5be013ab 100644 (file)
@@ -9,13 +9,11 @@ CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
index 1bcf683e35e65633de7302015a30c3a6a4363e68..73e0d2857f1877188b78275f3aac3ac0bdb1d9ae 100644 (file)
@@ -9,14 +9,12 @@ CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SHC_ICT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
index 9528a8cd5cc46acfcadee4d3df8c19996014b532..c4f2f55d05a998515d680fc2612bc71bae3ce513 100644 (file)
@@ -9,14 +9,12 @@ CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SHC_NETBOOT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
index 8519282ecf80841af36a3f2296925dc8a45b82d6..4eac21b4eb273359448b7006f11e2272a3ba838c 100644 (file)
@@ -9,13 +9,11 @@ CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
index b00d6f6b226b171c681315ff2ea0a5cb46879eb1..e3a37db04a3f8eef63316c8d3248ae1fdfffe44d 100644 (file)
@@ -9,14 +9,12 @@ CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SHC_SDBOOT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
index b00d6f6b226b171c681315ff2ea0a5cb46879eb1..e3a37db04a3f8eef63316c8d3248ae1fdfffe44d 100644 (file)
@@ -9,14 +9,12 @@ CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SHC_SDBOOT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
index 3fa5d5e5cc113a8cb890502cfa5a74d2e89ca3f0..e9ca0d640fadf9b64092ff777b6d1ea3779aefde 100644 (file)
@@ -9,14 +9,12 @@ CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
index 920c61c39174185812b121b38cbf9ac40d3b24fd..8ab018656d2ae588a16204495420aadb66d10e9e 100644 (file)
@@ -4,11 +4,14 @@ CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_SYS_TEXT_BASE=0x80100000
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 # CONFIG_SPL_GPIO_SUPPORT is not set
+CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_AM3517_EVM=y
 CONFIG_EMIF4=y
+CONFIG_DEFAULT_DEVICE_TREE="am3517-evm"
 CONFIG_BOOTDELAY=10
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 # CONFIG_SPL_EXT_SUPPORT is not set
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_HUSH_PARSER=y
@@ -27,13 +30,12 @@ CONFIG_CMD_CACHE=y
 # CONFIG_CMD_TIME is not set
 CONFIG_CMD_UBI=y
 CONFIG_SPL_PARTITION_UUIDS=y
+CONFIG_OF_CONTROL=y
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
-CONFIG_USB_STORAGE=y
 # CONFIG_FAT_WRITE is not set
 CONFIG_BCH=y
-CONFIG_OF_LIBFDT=y
index 15c25d39f1aef07df6718e393191f3e6c0d7f065..352ae16a9e4ccba9d0b7f44b82c9d73bf2607284 100644 (file)
@@ -3,14 +3,12 @@ CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_AM43XX=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm"
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=1"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_HUSH_PARSER=y
index 0bed3357229703d1d9b86b4a7cc61afffaf9c47a..1a4856ca9e6fad8924700276311a3f152c6ac5a2 100644 (file)
@@ -3,14 +3,12 @@ CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_AM43XX=y
 CONFIG_ISW_ENTRY_ADDR=0x40300350
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm"
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="SERIAL1,CONS_INDEX=1"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_USB_HOST_SUPPORT=y
index a4d23e10b60ecbe7d30d8debcfaced54971fce20..9b2b1d7196e615c6223ed8a293ec1c9942a13642 100644 (file)
@@ -8,7 +8,6 @@ CONFIG_TI_SECURE_EMIF_REGION_START=0xbdb00000
 CONFIG_TI_SECURE_EMIF_TOTAL_REGION_SIZE=0x02000000
 CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE=0x01c00000
 CONFIG_ISW_ENTRY_ADDR=0x403018e0
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm"
 CONFIG_FIT_IMAGE_POST_PROCESS=y
 CONFIG_SPL_LOAD_FIT=y
@@ -18,7 +17,6 @@ CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=1"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_ETH_SUPPORT=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_NET_SUPPORT=y
index 0e4679abedf22788473a04a8bd0f1b80060b77d8..0c9daed5f55edf9daaed08d1ea7f445cb986ebca 100644 (file)
@@ -7,7 +7,6 @@ CONFIG_TARGET_AM57XX_EVM=y
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_ARMV7_LPAE=y
 CONFIG_DEFAULT_DEVICE_TREE="am572x-idk"
 CONFIG_SPL_LOAD_FIT=y
@@ -19,7 +18,6 @@ CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
index e7638b88c25dabd74e57184838793a363644b2e9..b527e184634940a1d63ca4d2ec367ba2f4de0d73 100644 (file)
@@ -11,7 +11,6 @@ CONFIG_TARGET_AM57XX_EVM=y
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_ARMV7_LPAE=y
 CONFIG_DEFAULT_DEVICE_TREE="am57xx-beagle-x15"
 CONFIG_FIT_IMAGE_POST_PROCESS=y
@@ -25,7 +24,6 @@ CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_HUSH_PARSER=y
index ea729b015524b4ba0a3b7bdfb23477797a79e96d..d0f6f5fa11234bfe6844589304f9f6636b6d815b 100644 (file)
@@ -9,12 +9,10 @@ CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_BOOTDELAY=1
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_POWER_SUPPORT=y
 CONFIG_HUSH_PARSER=y
index 27370e7c0c32623c8d820630fbff85edc87dc860..0c60fef098d979e5d4bc54ba9468bb99ad78d018 100644 (file)
@@ -1,17 +1,16 @@
 CONFIG_ARM=y
 CONFIG_ARCH_DAVINCI=y
 CONFIG_TARGET_DA850EVM=y
-CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_MAC_ADDR_IN_EEPROM=y
+CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="da850-evm"
 CONFIG_SYS_EXTRA_OPTIONS="DA850_AM18X_EVM,SYS_I2C_EEPROM_ADDR_LEN=2,SYS_I2C_EEPROM_ADDR=0x50"
 CONFIG_BOOTDELAY=3
-CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="mem=32M console=ttyS2,115200n8 root=/dev/mtdblock2 rw noinitrd ip=dhcp"
 CONFIG_VERSION_VARIABLE=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
@@ -19,24 +18,29 @@ CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_BOARD_INIT=y
 CONFIG_HUSH_PARSER=y
-# CONFIG_CMD_BOOTZ is not set
+CONFIG_SYS_PROMPT="U-Boot > "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CRC32_VERIFY=y
 # CONFIG_CMD_EEPROM is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_GPIO is not set
 # CONFIG_CMD_GPT is not set
-# CONFIG_CMD_I2C is not set
 # CONFIG_CMD_PART is not set
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_TIME is not set
 # CONFIG_CMD_EXT4 is not set
 # CONFIG_CMD_FS_GENERIC is not set
 CONFIG_CMD_DIAG=y
+CONFIG_OF_CONTROL=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_DM=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
+CONFIG_DM_SPI=y
 # CONFIG_FAT_WRITE is not set
-CONFIG_OF_LIBFDT=y
index bfa5ea1c4bc6f8b089b6421599ea10c1735388ef..d6eb4a5ba2fda29a091e2e4ff61e7e6093288ff2 100644 (file)
@@ -7,9 +7,9 @@ CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="da850-evm"
+CONFIG_SYS_EXTRA_OPTIONS="MAC_ADDR_IN_SPIFLASH"
 CONFIG_BOOTDELAY=3
-CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="mem=32M console=ttyS2,115200n8 root=/dev/mtdblock2 rw noinitrd ip=dhcp"
 CONFIG_VERSION_VARIABLE=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
@@ -24,17 +24,24 @@ CONFIG_CRC32_VERIFY=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_GPIO is not set
 # CONFIG_CMD_GPT is not set
-# CONFIG_CMD_I2C is not set
 # CONFIG_CMD_PART is not set
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_TIME is not set
 # CONFIG_CMD_EXT4 is not set
 # CONFIG_CMD_FS_GENERIC is not set
+CONFIG_CMD_MTDPARTS=y
 CONFIG_CMD_DIAG=y
+CONFIG_OF_CONTROL=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_DM=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
+CONFIG_DM_SPI=y
 # CONFIG_FAT_WRITE is not set
-CONFIG_OF_LIBFDT=y
index 24ab89224df17824ad0ac732b78af4179c4a8cfa..3c8e7ad15a0575742018f913ff25d8367c69621c 100644 (file)
@@ -2,6 +2,8 @@ CONFIG_ARM=y
 CONFIG_ARCH_DAVINCI=y
 CONFIG_TARGET_DA850EVM=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
+CONFIG_DEFAULT_DEVICE_TREE="da850-evm"
+# CONFIG_SYS_MALLOC_F is not set
 CONFIG_SYS_EXTRA_OPTIONS="USE_NOR,DIRECT_NOR_BOOT"
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
@@ -17,7 +19,6 @@ CONFIG_CRC32_VERIFY=y
 # CONFIG_CMD_EEPROM is not set
 # CONFIG_CMD_GPIO is not set
 # CONFIG_CMD_GPT is not set
-# CONFIG_CMD_I2C is not set
 # CONFIG_CMD_MMC is not set
 # CONFIG_CMD_PART is not set
 # CONFIG_CMD_SPI is not set
@@ -28,11 +29,16 @@ CONFIG_CRC32_VERIFY=y
 # CONFIG_CMD_FAT is not set
 # CONFIG_CMD_FS_GENERIC is not set
 CONFIG_CMD_DIAG=y
+CONFIG_OF_CONTROL=y
 CONFIG_ENV_IS_IN_FLASH=y
+CONFIG_DM=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
 # CONFIG_MMC is not set
 CONFIG_MTD_NOR_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
-CONFIG_OF_LIBFDT=y
+CONFIG_DM_SPI=y
index 53903bf7308498fe9129d585632193d0895fc8c1..215fc61dc661d4dfd7766b611a02cf28cfdeec7d 100644 (file)
@@ -7,7 +7,6 @@ CONFIG_TARGET_DRA7XX_EVM=y
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_ARMV7_LPAE=y
 CONFIG_DEFAULT_DEVICE_TREE="dra7-evm"
 CONFIG_SPL_LOAD_FIT=y
@@ -19,7 +18,6 @@ CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
index 06d883411906c16a599acaf2efc46f514f8113c4..c88229cead12149ecab04735d44ecbfadf195d2e 100644 (file)
@@ -11,7 +11,6 @@ CONFIG_TARGET_DRA7XX_EVM=y
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_ARMV7_LPAE=y
 CONFIG_DEFAULT_DEVICE_TREE="dra7-evm"
 CONFIG_FIT_IMAGE_POST_PROCESS=y
@@ -25,7 +24,6 @@ CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_HUSH_PARSER=y
index 7bec00178692129301b82cbd7b47c8cd06582bf3..6d0f3af7a3d89fc94f23667f22a9b5e1886bb673 100644 (file)
@@ -22,12 +22,18 @@ CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_CLK=y
 CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_ROCKCHIP_RK3328=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_DM_REGULATOR=y
 CONFIG_REGULATOR_PWM=y
 CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_BAUDRATE=1500000
 CONFIG_DEBUG_UART_BASE=0xFF130000
index c7ee7b3f97f4fe4c7dceeab2b63a846d642962f3..985fb1ce9858cc1af61fb2db9b5c2ebfbb77952e 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_BOOTSTAGE=y
 CONFIG_SPL_BOOTSTAGE=y
 CONFIG_BOOTSTAGE_REPORT=y
 CONFIG_BOOTSTAGE_FDT=y
-CONFIG_ENV_IS_IN_MMC=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_ARCH_EARLY_INIT_R=y
 CONFIG_SPL=y
index 962ffa072996f5299f4f720fe2b20eca0fb39cde..bae67de718d11d9b0df72dfbd1a9b9593d2d9366 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_SYS_TEXT_BASE=0x80100000
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_SYS_MPUCLK=720
 CONFIG_TARGET_OMAP3_EVM=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTDELAY=3
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
@@ -13,7 +12,6 @@ CONFIG_DEFAULT_FDT_FILE="omap3-evm.dtb"
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 # CONFIG_SPL_EXT_SUPPORT is not set
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SYS_PROMPT="OMAP3_EVM # "
index b8f25883d8de14b26d6f1eb072b64c8d6bf5080f..adffcd981ce4ba5787da3af36774de8deeada53a 100644 (file)
@@ -3,13 +3,11 @@ CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_OMAP3_LOGIC=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="logicpd-torpedo-37xx-devkit"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_HUSH_PARSER=y
index 5d1cbe993aaa81442b1edfda9251f1359d6a7ebe..4043c42e4bc3be64692f229c0f9be3958ddeb823 100644 (file)
@@ -2,12 +2,10 @@ CONFIG_ARM=y
 CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_OMAP3_OVERO=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_HUSH_PARSER=y
index 2ab2516c018426f60d567076624f35dc0aa0ecbb..62a8d7c859f8ca675bd2734b5a5a2a8f150e3340 100644 (file)
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SYS_MALLOC_F_LEN=0x4000
@@ -20,6 +21,8 @@ CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
+CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_POWER_SUPPORT=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_GPT=y
@@ -63,8 +66,10 @@ CONFIG_SPL_PINCTRL=y
 CONFIG_PINCTRL_ROCKCHIP_RK3399=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_RK8XX=y
-CONFIG_REGULATOR_PWM=y
+CONFIG_SPL_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_SPL_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
 CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
index 4341d8d01f8d6810d72b615c5e938c26c66b7f8e..d269e3641a97e9fba12e37cb5a1e9b4fecef3df0 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="dm8168-evm"
 CONFIG_DISTRO_DEFAULTS=y
@@ -20,7 +19,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x300
 # CONFIG_CMD_IMLS is not set
index 7db7b0b6f9f92af7cb2f382d472b1937c3724922..7bd6068e0ca3421a881ed4a1e31407a7cd29d624 100644 (file)
@@ -1,8 +1,11 @@
 CONFIG_ARM=y
+# CONFIG_SPL_USE_ARCH_MEMCPY is not set
+# CONFIG_SPL_USE_ARCH_MEMSET is not set
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 CONFIG_TARGET_VYASA_RK3288=y
+CONFIG_TPL_TEXT_BASE=0xff704004
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-vyasa"
 CONFIG_DEBUG_UART=y
index 7ede15ec261315e6922fdfd6298bf0f17f5220a4..1a36be0446ac06d30ce23aa4dfedfd3fa16a6827 100644 (file)
@@ -44,7 +44,7 @@ static inline int is_extended(int part_type)
 
 static inline int is_bootable(dos_partition_t *p)
 {
-       return p->boot_ind == 0x80;
+       return (p->sys_ind == 0xef) || (p->boot_ind == 0x80);
 }
 
 static void print_one_part(dos_partition_t *p, lbaint_t ext_part_sector,
@@ -89,14 +89,20 @@ static int test_block_type(unsigned char *buffer)
 
 static int part_test_dos(struct blk_desc *dev_desc)
 {
-       ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
+       ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, mbr, dev_desc->blksz);
 
-       if (blk_dread(dev_desc, 0, 1, (ulong *)buffer) != 1)
+       if (blk_dread(dev_desc, 0, 1, (ulong *)mbr) != 1)
                return -1;
 
-       if (test_block_type(buffer) != DOS_MBR)
+       if (test_block_type((unsigned char *)mbr) != DOS_MBR)
                return -1;
 
+       if (dev_desc->sig_type == SIG_TYPE_NONE &&
+           mbr->unique_mbr_signature != 0) {
+               dev_desc->sig_type = SIG_TYPE_MBR;
+               dev_desc->mbr_sig = mbr->unique_mbr_signature;
+       }
+
        return 0;
 }
 
index 2973d52f6abb278756a814057e3b77d7c08945ca..208bb14ee88e2e5115134070b41feac72dce1b02 100644 (file)
@@ -923,11 +923,19 @@ static int is_pmbr_valid(legacy_mbr * mbr)
 static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba,
                        gpt_header *pgpt_head, gpt_entry **pgpt_pte)
 {
+       ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, mbr, dev_desc->blksz);
+
        if (!dev_desc || !pgpt_head) {
                printf("%s: Invalid Argument(s)\n", __func__);
                return 0;
        }
 
+       /* Read MBR Header from device */
+       if (blk_dread(dev_desc, 0, 1, (ulong *)mbr) != 1) {
+               printf("*** ERROR: Can't read MBR header ***\n");
+               return 0;
+       }
+
        /* Read GPT Header from device */
        if (blk_dread(dev_desc, (lbaint_t)lba, 1, pgpt_head) != 1) {
                printf("*** ERROR: Can't read GPT header ***\n");
@@ -937,6 +945,18 @@ static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba,
        if (validate_gpt_header(pgpt_head, (lbaint_t)lba, dev_desc->lba))
                return 0;
 
+       if (dev_desc->sig_type == SIG_TYPE_NONE) {
+               efi_guid_t empty = {};
+               if (memcmp(&pgpt_head->disk_guid, &empty, sizeof(empty))) {
+                       dev_desc->sig_type = SIG_TYPE_GUID;
+                       memcpy(&dev_desc->guid_sig, &pgpt_head->disk_guid,
+                             sizeof(empty));
+               } else if (mbr->unique_mbr_signature != 0) {
+                       dev_desc->sig_type = SIG_TYPE_MBR;
+                       dev_desc->mbr_sig = mbr->unique_mbr_signature;
+               }
+       }
+
        /* Read and allocate Partition Table Entries */
        *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
        if (*pgpt_pte == NULL) {
index 12fec38139c827a2d4511b97a1694984d473ce15..4b7be0b715212bb122b929d4be8ddd9d34db7d89 100644 (file)
@@ -150,6 +150,24 @@ Note: rk3036 SDMMC and debug uart use the same iomux, so if you boot from SD, th
       debug uart must be disabled
 
 
+Booting from an SD card on RK3288 with TPL
+==========================================
+
+Since the size of SPL can't be exceeded 0x8000 bytes in RK3288, it is not possible add
+new SPL features like Falcon mode or etc.
+
+So introduce TPL so-that adding new features to SPL is possible because now TPL should
+run minimal with code like DDR, clock etc and rest of new features in SPL.
+
+As of now TPL is added on Vyasa-RK3288 board.
+
+To write an image that boots from an SD card (assumed to be /dev/mmcblk0):
+
+   ./tools/mkimage -n rk3288 -T rksd -d ./tpl/u-boot-tpl.bin out &&
+    cat ./spl/u-boot-spl-dtb.bin >> out &&
+    sudo dd if=out of=/dev/mmcblk0 seek=64 &&
+    sudo dd if=u-boot-dtb.img of=/dev/mmcblk0 seek=256
+
 Booting from an SD card on RK3188
 =================================
 
index 5625d210e8ce3844d545b7ca200408698b37b8ee..c96b8f7109053e21edca880f580c21bbdd325946 100644 (file)
@@ -56,10 +56,20 @@ Each list element of the property should specify a device to be probed
 in the order they are listed: references (i.e. implicit paths), a full
 path or an alias is expected for each entry.
 
+A special specifier "same-as-spl" can be used at any position in the
+boot-order to direct U-Boot to insert the device the SPL was booted
+from there.  Whether this is indeed inserted or silently ignored (if
+it is not supported on any given SoC/board or if the boot-device is
+not available to continue booting from) is implementation-defined.
+Note that if "same-as-spl" expands to an actual node for a given
+board, the corresponding node may appear multiple times in the
+boot-order (as there currently exists no mechanism to suppress
+duplicates from the list).
+
 Example
 -------
 / {
        chosen {
-               u-boot,spl-boot-order = &sdmmc, "/sdhci@fe330000";
+               u-boot,spl-boot-order = "same-as-spl", &sdmmc, "/sdhci@fe330000";
        };
 };
index e5335f7234b779769f40d7a652c4dcd2fbea3157..80944205481eda28702f3b586b19c42f7f9e7eab 100644 (file)
@@ -28,3 +28,12 @@ config ADC_SANDBOX
          - 4 analog input channels
          - 16-bit resolution
          - single and multi-channel conversion mode
+
+config SARADC_ROCKCHIP
+       bool "Enable Rockchip SARADC driver"
+       help
+         This enables driver for Rockchip SARADC.
+         It provides:
+         - 2~6 analog input channels
+         - 1O or 12 bits resolution
+         - Up to 1MSPS of sample rate
index cebf26de078044dbcbecc1aea7c92172352d8037..4b5aa693ec1d12618339fc75432cf8f79d1d465d 100644 (file)
@@ -8,3 +8,4 @@
 obj-$(CONFIG_ADC) += adc-uclass.o
 obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o
 obj-$(CONFIG_ADC_SANDBOX) += sandbox.o
+obj-$(CONFIG_SARADC_ROCKCHIP) += rockchip-saradc.o
diff --git a/drivers/adc/rockchip-saradc.c b/drivers/adc/rockchip-saradc.c
new file mode 100644 (file)
index 0000000..0e6271d
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * (C) Copyright 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Rockchip SARADC driver for U-Boot
+ */
+
+#include <common.h>
+#include <adc.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+
+#define SARADC_CTRL_CHN_MASK           GENMASK(2, 0)
+#define SARADC_CTRL_POWER_CTRL         BIT(3)
+#define SARADC_CTRL_IRQ_ENABLE         BIT(5)
+#define SARADC_CTRL_IRQ_STATUS         BIT(6)
+
+#define SARADC_TIMEOUT                 (100 * 1000)
+
+struct rockchip_saradc_regs {
+       unsigned int data;
+       unsigned int stas;
+       unsigned int ctrl;
+       unsigned int dly_pu_soc;
+};
+
+struct rockchip_saradc_data {
+       int                             num_bits;
+       int                             num_channels;
+       unsigned long                   clk_rate;
+};
+
+struct rockchip_saradc_priv {
+       struct rockchip_saradc_regs             *regs;
+       int                                     active_channel;
+       const struct rockchip_saradc_data       *data;
+};
+
+int rockchip_saradc_channel_data(struct udevice *dev, int channel,
+                                unsigned int *data)
+{
+       struct rockchip_saradc_priv *priv = dev_get_priv(dev);
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+
+       if (channel != priv->active_channel) {
+               error("Requested channel is not active!");
+               return -EINVAL;
+       }
+
+       if ((readl(&priv->regs->ctrl) & SARADC_CTRL_IRQ_STATUS) !=
+           SARADC_CTRL_IRQ_STATUS)
+               return -EBUSY;
+
+       /* Read value */
+       *data = readl(&priv->regs->data);
+       *data &= uc_pdata->data_mask;
+
+       /* Power down adc */
+       writel(0, &priv->regs->ctrl);
+
+       return 0;
+}
+
+int rockchip_saradc_start_channel(struct udevice *dev, int channel)
+{
+       struct rockchip_saradc_priv *priv = dev_get_priv(dev);
+
+       if (channel < 0 || channel >= priv->data->num_channels) {
+               error("Requested channel is invalid!");
+               return -EINVAL;
+       }
+
+       /* 8 clock periods as delay between power up and start cmd */
+       writel(8, &priv->regs->dly_pu_soc);
+
+       /* Select the channel to be used and trigger conversion */
+       writel(SARADC_CTRL_POWER_CTRL | (channel & SARADC_CTRL_CHN_MASK) |
+              SARADC_CTRL_IRQ_ENABLE, &priv->regs->ctrl);
+
+       priv->active_channel = channel;
+
+       return 0;
+}
+
+int rockchip_saradc_stop(struct udevice *dev)
+{
+       struct rockchip_saradc_priv *priv = dev_get_priv(dev);
+
+       /* Power down adc */
+       writel(0, &priv->regs->ctrl);
+
+       priv->active_channel = -1;
+
+       return 0;
+}
+
+int rockchip_saradc_probe(struct udevice *dev)
+{
+       struct rockchip_saradc_priv *priv = dev_get_priv(dev);
+       struct clk clk;
+       int ret;
+
+       ret = clk_get_by_index(dev, 0, &clk);
+       if (ret)
+               return ret;
+
+       ret = clk_set_rate(&clk, priv->data->clk_rate);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+
+       priv->active_channel = -1;
+
+       return 0;
+}
+
+int rockchip_saradc_ofdata_to_platdata(struct udevice *dev)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       struct rockchip_saradc_priv *priv = dev_get_priv(dev);
+       struct rockchip_saradc_data *data;
+
+       data = (struct rockchip_saradc_data *)dev_get_driver_data(dev);
+       priv->regs = (struct rockchip_saradc_regs *)dev_read_addr(dev);
+       if (priv->regs == (struct rockchip_saradc_regs *)FDT_ADDR_T_NONE) {
+               error("Dev: %s - can't get address!", dev->name);
+               return -ENODATA;
+       }
+
+       priv->data = data;
+       uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;;
+       uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
+       uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5;
+       uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
+
+       return 0;
+}
+
+static const struct adc_ops rockchip_saradc_ops = {
+       .start_channel = rockchip_saradc_start_channel,
+       .channel_data = rockchip_saradc_channel_data,
+       .stop = rockchip_saradc_stop,
+};
+
+static const struct rockchip_saradc_data saradc_data = {
+       .num_bits = 10,
+       .num_channels = 3,
+       .clk_rate = 1000000,
+};
+
+static const struct rockchip_saradc_data rk3066_tsadc_data = {
+       .num_bits = 12,
+       .num_channels = 2,
+       .clk_rate = 50000,
+};
+
+static const struct rockchip_saradc_data rk3399_saradc_data = {
+       .num_bits = 10,
+       .num_channels = 6,
+       .clk_rate = 1000000,
+};
+
+static const struct udevice_id rockchip_saradc_ids[] = {
+       { .compatible = "rockchip,saradc",
+         .data = (ulong)&saradc_data },
+       { .compatible = "rockchip,rk3066-tsadc",
+         .data = (ulong)&rk3066_tsadc_data },
+       { .compatible = "rockchip,rk3399-saradc",
+         .data = (ulong)&rk3399_saradc_data },
+       { }
+};
+
+U_BOOT_DRIVER(rockchip_saradc) = {
+       .name           = "rockchip_saradc",
+       .id             = UCLASS_ADC,
+       .of_match       = rockchip_saradc_ids,
+       .ops            = &rockchip_saradc_ops,
+       .probe          = rockchip_saradc_probe,
+       .ofdata_to_platdata = rockchip_saradc_ofdata_to_platdata,
+       .priv_auto_alloc_size = sizeof(struct rockchip_saradc_priv),
+};
index 255a583c954586805a961e69caf16f6648124299..68d6ba0461d7bfbd8d06c88e95112e05ad4f2246 100644 (file)
@@ -310,10 +310,11 @@ static const struct udevice_id stm32_clk_ids[] = {
 };
 
 U_BOOT_DRIVER(stm32f7_clk) = {
-       .name           = "stm32f7_clk",
-       .id             = UCLASS_CLK,
-       .of_match       = stm32_clk_ids,
-       .ops            = &stm32_clk_ops,
-       .probe          = stm32_clk_probe,
-       .flags          = DM_FLAG_PRE_RELOC,
+       .name                   = "stm32f7_clk",
+       .id                     = UCLASS_CLK,
+       .of_match               = stm32_clk_ids,
+       .ops                    = &stm32_clk_ops,
+       .probe                  = stm32_clk_probe,
+       .priv_auto_alloc_size   = sizeof(struct stm32_clk),
+       .flags                  = DM_FLAG_PRE_RELOC,
 };
index d7f6a3c313e6c86143dc3931fc00196981d8b534..e87267d239fe4433e3a43f88415ddecb8beb024a 100644 (file)
@@ -117,16 +117,16 @@ static void rkclk_init(struct rk322x_cru *cru)
                     pclk_div << CORE_PERI_DIV_SHIFT);
 
        /*
-        * select apll as pd_bus bus clock source and
+        * select gpll as pd_bus bus clock source and
         * set up dependent divisors for PCLK/HCLK and ACLK clocks.
         */
        aclk_div = GPLL_HZ / BUS_ACLK_HZ - 1;
        assert((aclk_div + 1) * BUS_ACLK_HZ == GPLL_HZ && aclk_div <= 0x1f);
 
-       pclk_div = GPLL_HZ / BUS_PCLK_HZ - 1;
+       pclk_div = BUS_ACLK_HZ / BUS_PCLK_HZ - 1;
        assert((pclk_div + 1) * BUS_PCLK_HZ == GPLL_HZ && pclk_div <= 0x7);
 
-       hclk_div = GPLL_HZ / BUS_HCLK_HZ - 1;
+       hclk_div = BUS_ACLK_HZ / BUS_HCLK_HZ - 1;
        assert((hclk_div + 1) * BUS_HCLK_HZ == GPLL_HZ && hclk_div <= 0x3);
 
        rk_clrsetreg(&cru->cru_clksel_con[0],
@@ -389,7 +389,7 @@ static int rk322x_clk_bind(struct udevice *dev)
        /* The reset driver does not have a device node, so bind it here */
        ret = device_bind_driver(gd->dm_root, "rk322x_sysreset", "reset", &dev);
        if (ret)
-               debug("Warning: No RK3036 reset driver: ret=%d\n", ret);
+               debug("Warning: No RK322x reset driver: ret=%d\n", ret);
 
        return 0;
 }
index 478195b10b0eb6175b86a8a0b599c1011af3671e..a133810bf6074416aae264302bab2bb16895c44f 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <bitfield.h>
 #include <clk-uclass.h>
 #include <dm.h>
 #include <dt-structs.h>
@@ -111,6 +112,15 @@ enum {
        PERI_ACLK_DIV_SHIFT     = 0,
        PERI_ACLK_DIV_MASK      = 0x1f << PERI_ACLK_DIV_SHIFT,
 
+       /*
+        * CLKSEL24
+        * saradc_div_con:
+        * clk_saradc=24MHz/(saradc_div_con+1)
+        */
+       CLK_SARADC_DIV_CON_SHIFT        = 8,
+       CLK_SARADC_DIV_CON_MASK         = GENMASK(15, 8),
+       CLK_SARADC_DIV_CON_WIDTH        = 8,
+
        SOCSTS_DPLL_LOCK        = 1 << 5,
        SOCSTS_APLL_LOCK        = 1 << 6,
        SOCSTS_CPLL_LOCK        = 1 << 7,
@@ -634,6 +644,31 @@ static ulong rockchip_spi_set_clk(struct rk3288_cru *cru, uint gclk_rate,
        return rockchip_spi_get_clk(cru, gclk_rate, periph);
 }
 
+static ulong rockchip_saradc_get_clk(struct rk3288_cru *cru)
+{
+       u32 div, val;
+
+       val = readl(&cru->cru_clksel_con[24]);
+       div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
+                              CLK_SARADC_DIV_CON_WIDTH);
+
+       return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rockchip_saradc_set_clk(struct rk3288_cru *cru, uint hz)
+{
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
+       assert(src_clk_div < 128);
+
+       rk_clrsetreg(&cru->cru_clksel_con[24],
+                    CLK_SARADC_DIV_CON_MASK,
+                    src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
+
+       return rockchip_saradc_get_clk(cru);
+}
+
 static ulong rk3288_clk_get_rate(struct clk *clk)
 {
        struct rk3288_clk_priv *priv = dev_get_priv(clk->dev);
@@ -666,6 +701,9 @@ static ulong rk3288_clk_get_rate(struct clk *clk)
                return gclk_rate;
        case PCLK_PWM:
                return PD_BUS_PCLK_HZ;
+       case SCLK_SARADC:
+               new_rate = rockchip_saradc_get_clk(priv->cru);
+               break;
        default:
                return -ENOENT;
        }
@@ -756,6 +794,9 @@ static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate)
                new_rate = rate;
                break;
 #endif
+       case SCLK_SARADC:
+               new_rate = rockchip_saradc_set_clk(priv->cru, rate);
+               break;
        default:
                return -ENOENT;
        }
index c3a6650de0328d563bf869582b596c043d75d862..540d9104c3ccba4208b717fe3af4a3344ad67d25 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <bitfield.h>
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
@@ -114,7 +115,8 @@ enum {
 
        /* CLKSEL_CON23 */
        CLK_SARADC_DIV_CON_SHIFT        = 0,
-       CLK_SARADC_DIV_CON_MASK         = 0x3ff << CLK_SARADC_DIV_CON_SHIFT,
+       CLK_SARADC_DIV_CON_MASK         = GENMASK(9, 0),
+       CLK_SARADC_DIV_CON_WIDTH        = 10,
 
        /* CLKSEL_CON24 */
        CLK_PWM_PLL_SEL_CPLL            = 0,
@@ -478,6 +480,31 @@ static ulong rk3328_pwm_set_clk(struct rk3328_cru *cru, uint hz)
        return DIV_TO_RATE(GPLL_HZ, div);
 }
 
+static ulong rk3328_saradc_get_clk(struct rk3328_cru *cru)
+{
+       u32 div, val;
+
+       val = readl(&cru->clksel_con[23]);
+       div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
+                              CLK_SARADC_DIV_CON_WIDTH);
+
+       return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3328_saradc_set_clk(struct rk3328_cru *cru, uint hz)
+{
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
+       assert(src_clk_div < 128);
+
+       rk_clrsetreg(&cru->clksel_con[23],
+                    CLK_SARADC_DIV_CON_MASK,
+                    src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
+
+       return rk3328_saradc_get_clk(cru);
+}
+
 static ulong rk3328_clk_get_rate(struct clk *clk)
 {
        struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
@@ -501,6 +528,9 @@ static ulong rk3328_clk_get_rate(struct clk *clk)
        case SCLK_PWM:
                rate = rk3328_pwm_get_clk(priv->cru);
                break;
+       case SCLK_SARADC:
+               rate = rk3328_saradc_get_clk(priv->cru);
+               break;
        default:
                return -ENOENT;
        }
@@ -531,6 +561,9 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
        case SCLK_PWM:
                ret = rk3328_pwm_set_clk(priv->cru, rate);
                break;
+       case SCLK_SARADC:
+               ret = rk3328_saradc_set_clk(priv->cru, rate);
+               break;
        default:
                return -ENOENT;
        }
index e2747816b9c7752f5f96eef4c518d4df6f878b54..3a12be77282b18910368f2849c94a8b28f486735 100644 (file)
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <mapmem.h>
 #include <syscon.h>
+#include <bitfield.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/cru_rk3368.h>
 #include <asm/arch/hardware.h>
@@ -397,6 +398,31 @@ static ulong rk3368_spi_set_clk(struct rk3368_cru *cru, ulong clk_id, uint hz)
        return rk3368_spi_get_clk(cru, clk_id);
 }
 
+static ulong rk3368_saradc_get_clk(struct rk3368_cru *cru)
+{
+       u32 div, val;
+
+       val = readl(&cru->clksel_con[25]);
+       div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
+                              CLK_SARADC_DIV_CON_WIDTH);
+
+       return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3368_saradc_set_clk(struct rk3368_cru *cru, uint hz)
+{
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
+       assert(src_clk_div < 128);
+
+       rk_clrsetreg(&cru->clksel_con[25],
+                    CLK_SARADC_DIV_CON_MASK,
+                    src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
+
+       return rk3368_saradc_get_clk(cru);
+}
+
 static ulong rk3368_clk_get_rate(struct clk *clk)
 {
        struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
@@ -419,6 +445,9 @@ static ulong rk3368_clk_get_rate(struct clk *clk)
                rate = rk3368_mmc_get_clk(priv->cru, clk->id);
                break;
 #endif
+       case SCLK_SARADC:
+               rate = rk3368_saradc_get_clk(priv->cru);
+               break;
        default:
                return -ENOENT;
        }
@@ -453,6 +482,9 @@ static ulong rk3368_clk_set_rate(struct clk *clk, ulong rate)
                ret = rk3368_gmac_set_clk(priv->cru, clk->id, rate);
                break;
 #endif
+       case SCLK_SARADC:
+               ret =  rk3368_saradc_set_clk(priv->cru, rate);
+               break;
        default:
                return -ENOENT;
        }
index 9d963be5529a74a85767519b82e39a0a8c931dc5..50faf5d193563a05a693cd866e80e6f50f75dc91 100644 (file)
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <mapmem.h>
 #include <syscon.h>
+#include <bitfield.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/cru_rk3399.h>
@@ -181,7 +182,8 @@ enum {
 
        /* CLKSEL_CON26 */
        CLK_SARADC_DIV_CON_SHIFT        = 8,
-       CLK_SARADC_DIV_CON_MASK         = 0xff << CLK_SARADC_DIV_CON_SHIFT,
+       CLK_SARADC_DIV_CON_MASK         = GENMASK(15, 8),
+       CLK_SARADC_DIV_CON_WIDTH        = 8,
 
        /* CLKSEL_CON27 */
        CLK_TSADC_SEL_X24M              = 0x0,
@@ -860,6 +862,32 @@ static ulong rk3399_ddr_set_clk(struct rk3399_cru *cru,
 
        return set_rate;
 }
+
+static ulong rk3399_saradc_get_clk(struct rk3399_cru *cru)
+{
+       u32 div, val;
+
+       val = readl(&cru->clksel_con[26]);
+       div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
+                              CLK_SARADC_DIV_CON_WIDTH);
+
+       return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3399_saradc_set_clk(struct rk3399_cru *cru, uint hz)
+{
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
+       assert(src_clk_div < 128);
+
+       rk_clrsetreg(&cru->clksel_con[26],
+                    CLK_SARADC_DIV_CON_MASK,
+                    src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
+
+       return rk3399_saradc_get_clk(cru);
+}
+
 static ulong rk3399_clk_get_rate(struct clk *clk)
 {
        struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
@@ -895,6 +923,9 @@ static ulong rk3399_clk_get_rate(struct clk *clk)
                break;
        case PCLK_EFUSE1024NS:
                break;
+       case SCLK_SARADC:
+               rate = rk3399_saradc_get_clk(priv->cru);
+               break;
        default:
                return -ENOENT;
        }
@@ -943,6 +974,9 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
                break;
        case PCLK_EFUSE1024NS:
                break;
+       case SCLK_SARADC:
+               ret = rk3399_saradc_set_clk(priv->cru, rate);
+               break;
        default:
                return -ENOENT;
        }
index cf966bbdc339924eba4ac8e73b630f41da53d5e2..86e73e414cf971bfe138b58919665ae2d28c5d48 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <bitfield.h>
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
@@ -36,7 +37,7 @@ enum {
                         #hz "Hz cannot be hit with PLL "\
                         "divisors on line " __stringify(__LINE__));
 
-/* use interge mode*/
+/* use integer mode */
 static inline int rv1108_pll_id(enum rk_clk_id clk_id)
 {
        int id = 0;
@@ -130,6 +131,31 @@ static int rv1108_sfc_set_clk(struct rv1108_cru *cru, uint rate)
        return DIV_TO_RATE(pll_rate, div);
 }
 
+static ulong rv1108_saradc_get_clk(struct rv1108_cru *cru)
+{
+       u32 div, val;
+
+       val = readl(&cru->clksel_con[22]);
+       div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
+                              CLK_SARADC_DIV_CON_WIDTH);
+
+       return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rv1108_saradc_set_clk(struct rv1108_cru *cru, uint hz)
+{
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
+       assert(src_clk_div < 128);
+
+       rk_clrsetreg(&cru->clksel_con[22],
+                    CLK_SARADC_DIV_CON_MASK,
+                    src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
+
+       return rv1108_saradc_get_clk(cru);
+}
+
 static ulong rv1108_clk_get_rate(struct clk *clk)
 {
        struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
@@ -137,6 +163,8 @@ static ulong rv1108_clk_get_rate(struct clk *clk)
        switch (clk->id) {
        case 0 ... 63:
                return rkclk_pll_get_rate(priv->cru, clk->id);
+       case SCLK_SARADC:
+               return rv1108_saradc_get_clk(priv->cru);
        default:
                return -ENOENT;
        }
@@ -154,6 +182,9 @@ static ulong rv1108_clk_set_rate(struct clk *clk, ulong rate)
        case SCLK_SFC:
                new_rate = rv1108_sfc_set_clk(priv->cru, rate);
                break;
+       case SCLK_SARADC:
+               new_rate = rv1108_saradc_set_clk(priv->cru, rate);
+               break;
        default:
                return -ENOENT;
        }
index 840b3f6046bfe2005e4aafd3f73769680510c8ea..332280c220e7dc90af7d27b5aa2c983a3521460b 100644 (file)
@@ -396,6 +396,7 @@ static const struct udevice_id rockchip_i2c_ids[] = {
        { .compatible = "rockchip,rk3066-i2c" },
        { .compatible = "rockchip,rk3188-i2c" },
        { .compatible = "rockchip,rk3288-i2c" },
+       { .compatible = "rockchip,rk3328-i2c" },
        { .compatible = "rockchip,rk3399-i2c" },
        { }
 };
index fa24c52351160688002125196301977f405a381d..24b4eadd2abe1f3f7489b95591d2bd4531cec42b 100644 (file)
@@ -384,6 +384,14 @@ config GENERIC_ATMEL_MCI
          the SD Memory Card Specification V2.0, the SDIO V2.0 specification
          and CE-ATA V1.1.
 
+config STM32_SDMMC2
+       bool "STMicroelectronics STM32H7 SD/MMC Host Controller support"
+       depends on DM_MMC && BLK && OF_CONTROL && DM_MMC_OPS
+       help
+         This selects support for the SD/MMC controller on STM32H7 SoCs.
+         If you have a board based on such a SoC and with a SD/MMC slot,
+         say Y or M here.
+
 endif
 
 config TEGRA124_MMC_DISABLE_EXT_LOOPBACK
index a6becb230908844dac8c75607726af679dbed7c2..d505f37f0194ff152747fe8775c3c0cd5192f28f 100644 (file)
@@ -43,6 +43,7 @@ obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
 obj-$(CONFIG_MMC_SANDBOX)              += sandbox_mmc.o
 obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
 obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
+obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
 
 # SDHCI
 obj-$(CONFIG_MMC_SDHCI)                        += sdhci.o
index f83c1d7241082c9351d2dba5d5a523c65b337476..72d1c646a2b64a132839d5df40486496face7802 100644 (file)
 #define   SDHCI_CDNS_HRS04_WDATA_SHIFT         8
 #define   SDHCI_CDNS_HRS04_ADDR_SHIFT          0
 
+#define SDHCI_CDNS_HRS06               0x18            /* eMMC control */
+#define   SDHCI_CDNS_HRS06_TUNE_UP             BIT(15)
+#define   SDHCI_CDNS_HRS06_TUNE_SHIFT          8
+#define   SDHCI_CDNS_HRS06_TUNE_MASK           0x3f
+#define   SDHCI_CDNS_HRS06_MODE_MASK           0x7
+#define   SDHCI_CDNS_HRS06_MODE_SD             0x0
+#define   SDHCI_CDNS_HRS06_MODE_MMC_SDR                0x2
+#define   SDHCI_CDNS_HRS06_MODE_MMC_DDR                0x3
+#define   SDHCI_CDNS_HRS06_MODE_MMC_HS200      0x4
+#define   SDHCI_CDNS_HRS06_MODE_MMC_HS400      0x5
+#define   SDHCI_CDNS_HRS06_MODE_MMC_HS400ES    0x6
+
 /* SRS - Slot Register Set (SDHCI-compatible) */
 #define SDHCI_CDNS_SRS_BASE            0x200
 
@@ -111,6 +123,44 @@ static int sdhci_cdns_phy_init(struct sdhci_cdns_plat *plat,
        return 0;
 }
 
+static void sdhci_cdns_set_control_reg(struct sdhci_host *host)
+{
+       struct mmc *mmc = host->mmc;
+       struct sdhci_cdns_plat *plat = dev_get_platdata(mmc->dev);
+       unsigned int clock = mmc->clock;
+       u32 mode, tmp;
+
+       /*
+        * REVISIT:
+        * The mode should be decided by MMC_TIMING_* like Linux, but
+        * U-Boot does not support timing.  Use the clock frequency instead.
+        */
+       if (clock <= 26000000)
+               mode = SDHCI_CDNS_HRS06_MODE_SD; /* use this for Legacy */
+       else if (clock <= 52000000) {
+               if (mmc->ddr_mode)
+                       mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
+               else
+                       mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
+       } else {
+               /*
+                * REVISIT:
+                * The IP supports HS200/HS400, revisit once U-Boot support it
+                */
+               printf("unsupported frequency %d\n", clock);
+               return;
+       }
+
+       tmp = readl(plat->hrs_addr + SDHCI_CDNS_HRS06);
+       tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
+       tmp |= mode;
+       writel(tmp, plat->hrs_addr + SDHCI_CDNS_HRS06);
+}
+
+static const struct sdhci_ops sdhci_cdns_ops = {
+       .set_control_reg = sdhci_cdns_set_control_reg,
+};
+
 static int sdhci_cdns_bind(struct udevice *dev)
 {
        struct sdhci_cdns_plat *plat = dev_get_platdata(dev);
@@ -137,6 +187,7 @@ static int sdhci_cdns_probe(struct udevice *dev)
 
        host->name = dev->name;
        host->ioaddr = plat->hrs_addr + SDHCI_CDNS_SRS_BASE;
+       host->ops = &sdhci_cdns_ops;
        host->quirks |= SDHCI_QUIRK_WAIT_SEND_CMD;
 
        ret = sdhci_cdns_phy_init(plat, gd->fdt_blob, dev_of_offset(dev));
diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c
new file mode 100644 (file)
index 0000000..0e1f40b
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2017
+ * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <mmc.h>
+#include <reset.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <linux/iopoll.h>
+
+struct stm32_sdmmc2_plat {
+       struct mmc_config cfg;
+       struct mmc mmc;
+};
+
+struct stm32_sdmmc2_priv {
+       fdt_addr_t base;
+       struct clk clk;
+       struct reset_ctl reset_ctl;
+       struct gpio_desc cd_gpio;
+       u32 clk_reg_msk;
+       u32 pwr_reg_msk;
+};
+
+struct stm32_sdmmc2_ctx {
+       u32 cache_start;
+       u32 cache_end;
+       u32 data_length;
+       bool dpsm_abort;
+};
+
+/* SDMMC REGISTERS OFFSET */
+#define SDMMC_POWER            0x00    /* SDMMC power control             */
+#define SDMMC_CLKCR            0x04    /* SDMMC clock control             */
+#define SDMMC_ARG              0x08    /* SDMMC argument                  */
+#define SDMMC_CMD              0x0C    /* SDMMC command                   */
+#define SDMMC_RESP1            0x14    /* SDMMC response 1                */
+#define SDMMC_RESP2            0x18    /* SDMMC response 2                */
+#define SDMMC_RESP3            0x1C    /* SDMMC response 3                */
+#define SDMMC_RESP4            0x20    /* SDMMC response 4                */
+#define SDMMC_DTIMER           0x24    /* SDMMC data timer                */
+#define SDMMC_DLEN             0x28    /* SDMMC data length               */
+#define SDMMC_DCTRL            0x2C    /* SDMMC data control              */
+#define SDMMC_DCOUNT           0x30    /* SDMMC data counter              */
+#define SDMMC_STA              0x34    /* SDMMC status                    */
+#define SDMMC_ICR              0x38    /* SDMMC interrupt clear           */
+#define SDMMC_MASK             0x3C    /* SDMMC mask                      */
+#define SDMMC_IDMACTRL         0x50    /* SDMMC DMA control               */
+#define SDMMC_IDMABASE0                0x58    /* SDMMC DMA buffer 0 base address */
+
+/* SDMMC_POWER register */
+#define SDMMC_POWER_PWRCTRL            GENMASK(1, 0)
+#define SDMMC_POWER_VSWITCH            BIT(2)
+#define SDMMC_POWER_VSWITCHEN          BIT(3)
+#define SDMMC_POWER_DIRPOL             BIT(4)
+
+/* SDMMC_CLKCR register */
+#define SDMMC_CLKCR_CLKDIV             GENMASK(9, 0)
+#define SDMMC_CLKCR_CLKDIV_MAX         SDMMC_CLKCR_CLKDIV
+#define SDMMC_CLKCR_PWRSAV             BIT(12)
+#define SDMMC_CLKCR_WIDBUS_4           BIT(14)
+#define SDMMC_CLKCR_WIDBUS_8           BIT(15)
+#define SDMMC_CLKCR_NEGEDGE            BIT(16)
+#define SDMMC_CLKCR_HWFC_EN            BIT(17)
+#define SDMMC_CLKCR_DDR                        BIT(18)
+#define SDMMC_CLKCR_BUSSPEED           BIT(19)
+#define SDMMC_CLKCR_SELCLKRX           GENMASK(21, 20)
+
+/* SDMMC_CMD register */
+#define SDMMC_CMD_CMDINDEX             GENMASK(5, 0)
+#define SDMMC_CMD_CMDTRANS             BIT(6)
+#define SDMMC_CMD_CMDSTOP              BIT(7)
+#define SDMMC_CMD_WAITRESP             GENMASK(9, 8)
+#define SDMMC_CMD_WAITRESP_0           BIT(8)
+#define SDMMC_CMD_WAITRESP_1           BIT(9)
+#define SDMMC_CMD_WAITINT              BIT(10)
+#define SDMMC_CMD_WAITPEND             BIT(11)
+#define SDMMC_CMD_CPSMEN               BIT(12)
+#define SDMMC_CMD_DTHOLD               BIT(13)
+#define SDMMC_CMD_BOOTMODE             BIT(14)
+#define SDMMC_CMD_BOOTEN               BIT(15)
+#define SDMMC_CMD_CMDSUSPEND           BIT(16)
+
+/* SDMMC_DCTRL register */
+#define SDMMC_DCTRL_DTEN               BIT(0)
+#define SDMMC_DCTRL_DTDIR              BIT(1)
+#define SDMMC_DCTRL_DTMODE             GENMASK(3, 2)
+#define SDMMC_DCTRL_DBLOCKSIZE         GENMASK(7, 4)
+#define SDMMC_DCTRL_DBLOCKSIZE_SHIFT   4
+#define SDMMC_DCTRL_RWSTART            BIT(8)
+#define SDMMC_DCTRL_RWSTOP             BIT(9)
+#define SDMMC_DCTRL_RWMOD              BIT(10)
+#define SDMMC_DCTRL_SDMMCEN            BIT(11)
+#define SDMMC_DCTRL_BOOTACKEN          BIT(12)
+#define SDMMC_DCTRL_FIFORST            BIT(13)
+
+/* SDMMC_STA register */
+#define SDMMC_STA_CCRCFAIL             BIT(0)
+#define SDMMC_STA_DCRCFAIL             BIT(1)
+#define SDMMC_STA_CTIMEOUT             BIT(2)
+#define SDMMC_STA_DTIMEOUT             BIT(3)
+#define SDMMC_STA_TXUNDERR             BIT(4)
+#define SDMMC_STA_RXOVERR              BIT(5)
+#define SDMMC_STA_CMDREND              BIT(6)
+#define SDMMC_STA_CMDSENT              BIT(7)
+#define SDMMC_STA_DATAEND              BIT(8)
+#define SDMMC_STA_DHOLD                        BIT(9)
+#define SDMMC_STA_DBCKEND              BIT(10)
+#define SDMMC_STA_DABORT               BIT(11)
+#define SDMMC_STA_DPSMACT              BIT(12)
+#define SDMMC_STA_CPSMACT              BIT(13)
+#define SDMMC_STA_TXFIFOHE             BIT(14)
+#define SDMMC_STA_RXFIFOHF             BIT(15)
+#define SDMMC_STA_TXFIFOF              BIT(16)
+#define SDMMC_STA_RXFIFOF              BIT(17)
+#define SDMMC_STA_TXFIFOE              BIT(18)
+#define SDMMC_STA_RXFIFOE              BIT(19)
+#define SDMMC_STA_BUSYD0               BIT(20)
+#define SDMMC_STA_BUSYD0END            BIT(21)
+#define SDMMC_STA_SDMMCIT              BIT(22)
+#define SDMMC_STA_ACKFAIL              BIT(23)
+#define SDMMC_STA_ACKTIMEOUT           BIT(24)
+#define SDMMC_STA_VSWEND               BIT(25)
+#define SDMMC_STA_CKSTOP               BIT(26)
+#define SDMMC_STA_IDMATE               BIT(27)
+#define SDMMC_STA_IDMABTC              BIT(28)
+
+/* SDMMC_ICR register */
+#define SDMMC_ICR_CCRCFAILC            BIT(0)
+#define SDMMC_ICR_DCRCFAILC            BIT(1)
+#define SDMMC_ICR_CTIMEOUTC            BIT(2)
+#define SDMMC_ICR_DTIMEOUTC            BIT(3)
+#define SDMMC_ICR_TXUNDERRC            BIT(4)
+#define SDMMC_ICR_RXOVERRC             BIT(5)
+#define SDMMC_ICR_CMDRENDC             BIT(6)
+#define SDMMC_ICR_CMDSENTC             BIT(7)
+#define SDMMC_ICR_DATAENDC             BIT(8)
+#define SDMMC_ICR_DHOLDC               BIT(9)
+#define SDMMC_ICR_DBCKENDC             BIT(10)
+#define SDMMC_ICR_DABORTC              BIT(11)
+#define SDMMC_ICR_BUSYD0ENDC           BIT(21)
+#define SDMMC_ICR_SDMMCITC             BIT(22)
+#define SDMMC_ICR_ACKFAILC             BIT(23)
+#define SDMMC_ICR_ACKTIMEOUTC          BIT(24)
+#define SDMMC_ICR_VSWENDC              BIT(25)
+#define SDMMC_ICR_CKSTOPC              BIT(26)
+#define SDMMC_ICR_IDMATEC              BIT(27)
+#define SDMMC_ICR_IDMABTCC             BIT(28)
+#define SDMMC_ICR_STATIC_FLAGS         ((GENMASK(28, 21)) | (GENMASK(11, 0)))
+
+/* SDMMC_MASK register */
+#define SDMMC_MASK_CCRCFAILIE          BIT(0)
+#define SDMMC_MASK_DCRCFAILIE          BIT(1)
+#define SDMMC_MASK_CTIMEOUTIE          BIT(2)
+#define SDMMC_MASK_DTIMEOUTIE          BIT(3)
+#define SDMMC_MASK_TXUNDERRIE          BIT(4)
+#define SDMMC_MASK_RXOVERRIE           BIT(5)
+#define SDMMC_MASK_CMDRENDIE           BIT(6)
+#define SDMMC_MASK_CMDSENTIE           BIT(7)
+#define SDMMC_MASK_DATAENDIE           BIT(8)
+#define SDMMC_MASK_DHOLDIE             BIT(9)
+#define SDMMC_MASK_DBCKENDIE           BIT(10)
+#define SDMMC_MASK_DABORTIE            BIT(11)
+#define SDMMC_MASK_TXFIFOHEIE          BIT(14)
+#define SDMMC_MASK_RXFIFOHFIE          BIT(15)
+#define SDMMC_MASK_RXFIFOFIE           BIT(17)
+#define SDMMC_MASK_TXFIFOEIE           BIT(18)
+#define SDMMC_MASK_BUSYD0ENDIE         BIT(21)
+#define SDMMC_MASK_SDMMCITIE           BIT(22)
+#define SDMMC_MASK_ACKFAILIE           BIT(23)
+#define SDMMC_MASK_ACKTIMEOUTIE                BIT(24)
+#define SDMMC_MASK_VSWENDIE            BIT(25)
+#define SDMMC_MASK_CKSTOPIE            BIT(26)
+#define SDMMC_MASK_IDMABTCIE           BIT(28)
+
+/* SDMMC_IDMACTRL register */
+#define SDMMC_IDMACTRL_IDMAEN          BIT(0)
+
+#define SDMMC_CMD_TIMEOUT              0xFFFFFFFF
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void stm32_sdmmc2_start_data(struct stm32_sdmmc2_priv *priv,
+                                   struct mmc_data *data,
+                                   struct stm32_sdmmc2_ctx *ctx)
+{
+       u32 data_ctrl, idmabase0;
+
+       /* Configure the SDMMC DPSM (Data Path State Machine) */
+       data_ctrl = (__ilog2(data->blocksize) <<
+                    SDMMC_DCTRL_DBLOCKSIZE_SHIFT) &
+                   SDMMC_DCTRL_DBLOCKSIZE;
+
+       if (data->flags & MMC_DATA_READ) {
+               data_ctrl |= SDMMC_DCTRL_DTDIR;
+               idmabase0 = (u32)data->dest;
+       } else {
+               idmabase0 = (u32)data->src;
+       }
+
+       /* Set the SDMMC Data TimeOut value */
+       writel(SDMMC_CMD_TIMEOUT, priv->base + SDMMC_DTIMER);
+
+       /* Set the SDMMC DataLength value */
+       writel(ctx->data_length, priv->base + SDMMC_DLEN);
+
+       /* Write to SDMMC DCTRL */
+       writel(data_ctrl, priv->base + SDMMC_DCTRL);
+
+       /* Cache align */
+       ctx->cache_start = rounddown(idmabase0, ARCH_DMA_MINALIGN);
+       ctx->cache_end = roundup(idmabase0 + ctx->data_length,
+                                ARCH_DMA_MINALIGN);
+
+       /*
+        * Flush data cache before DMA start (clean and invalidate)
+        * Clean also needed for read
+        * Avoid issue on buffer not cached-aligned
+        */
+       flush_dcache_range(ctx->cache_start, ctx->cache_end);
+
+       /* Enable internal DMA */
+       writel(idmabase0, priv->base + SDMMC_IDMABASE0);
+       writel(SDMMC_IDMACTRL_IDMAEN, priv->base + SDMMC_IDMACTRL);
+}
+
+static void stm32_sdmmc2_start_cmd(struct stm32_sdmmc2_priv *priv,
+                                  struct mmc_cmd *cmd, u32 cmd_param)
+{
+       if (readl(priv->base + SDMMC_ARG) & SDMMC_CMD_CPSMEN)
+               writel(0, priv->base + SDMMC_ARG);
+
+       cmd_param |= cmd->cmdidx | SDMMC_CMD_CPSMEN;
+       if (cmd->resp_type & MMC_RSP_PRESENT) {
+               if (cmd->resp_type & MMC_RSP_136)
+                       cmd_param |= SDMMC_CMD_WAITRESP;
+               else if (cmd->resp_type & MMC_RSP_CRC)
+                       cmd_param |= SDMMC_CMD_WAITRESP_0;
+               else
+                       cmd_param |= SDMMC_CMD_WAITRESP_1;
+       }
+
+       /* Clear flags */
+       writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR);
+
+       /* Set SDMMC argument value */
+       writel(cmd->cmdarg, priv->base + SDMMC_ARG);
+
+       /* Set SDMMC command parameters */
+       writel(cmd_param, priv->base + SDMMC_CMD);
+}
+
+static int stm32_sdmmc2_end_cmd(struct stm32_sdmmc2_priv *priv,
+                               struct mmc_cmd *cmd,
+                               struct stm32_sdmmc2_ctx *ctx)
+{
+       u32 mask = SDMMC_STA_CTIMEOUT;
+       u32 status;
+       int ret;
+
+       if (cmd->resp_type & MMC_RSP_PRESENT) {
+               mask |= SDMMC_STA_CMDREND;
+               if (cmd->resp_type & MMC_RSP_CRC)
+                       mask |= SDMMC_STA_CCRCFAIL;
+       } else {
+               mask |= SDMMC_STA_CMDSENT;
+       }
+
+       /* Polling status register */
+       ret = readl_poll_timeout(priv->base + SDMMC_STA, status, status & mask,
+                                300);
+
+       if (ret < 0) {
+               debug("%s: timeout reading SDMMC_STA register\n", __func__);
+               ctx->dpsm_abort = true;
+               return ret;
+       }
+
+       /* Check status */
+       if (status & SDMMC_STA_CTIMEOUT) {
+               debug("%s: error SDMMC_STA_CTIMEOUT (0x%x) for cmd %d\n",
+                     __func__, status, cmd->cmdidx);
+               ctx->dpsm_abort = true;
+               return -ETIMEDOUT;
+       }
+
+       if (status & SDMMC_STA_CCRCFAIL && cmd->resp_type & MMC_RSP_CRC) {
+               debug("%s: error SDMMC_STA_CCRCFAIL (0x%x) for cmd %d\n",
+                     __func__, status, cmd->cmdidx);
+               ctx->dpsm_abort = true;
+               return -EILSEQ;
+       }
+
+       if (status & SDMMC_STA_CMDREND && cmd->resp_type & MMC_RSP_PRESENT) {
+               cmd->response[0] = readl(priv->base + SDMMC_RESP1);
+               if (cmd->resp_type & MMC_RSP_136) {
+                       cmd->response[1] = readl(priv->base + SDMMC_RESP2);
+                       cmd->response[2] = readl(priv->base + SDMMC_RESP3);
+                       cmd->response[3] = readl(priv->base + SDMMC_RESP4);
+               }
+       }
+
+       return 0;
+}
+
+static int stm32_sdmmc2_end_data(struct stm32_sdmmc2_priv *priv,
+                                struct mmc_cmd *cmd,
+                                struct mmc_data *data,
+                                struct stm32_sdmmc2_ctx *ctx)
+{
+       u32 mask = SDMMC_STA_DCRCFAIL | SDMMC_STA_DTIMEOUT |
+                  SDMMC_STA_IDMATE | SDMMC_STA_DATAEND;
+       u32 status;
+
+       if (data->flags & MMC_DATA_READ)
+               mask |= SDMMC_STA_RXOVERR;
+       else
+               mask |= SDMMC_STA_TXUNDERR;
+
+       status = readl(priv->base + SDMMC_STA);
+       while (!(status & mask))
+               status = readl(priv->base + SDMMC_STA);
+
+       /*
+        * Need invalidate the dcache again to avoid any
+        * cache-refill during the DMA operations (pre-fetching)
+        */
+       if (data->flags & MMC_DATA_READ)
+               invalidate_dcache_range(ctx->cache_start, ctx->cache_end);
+
+       if (status & SDMMC_STA_DCRCFAIL) {
+               debug("%s: error SDMMC_STA_DCRCFAIL (0x%x) for cmd %d\n",
+                     __func__, status, cmd->cmdidx);
+               if (readl(priv->base + SDMMC_DCOUNT))
+                       ctx->dpsm_abort = true;
+               return -EILSEQ;
+       }
+
+       if (status & SDMMC_STA_DTIMEOUT) {
+               debug("%s: error SDMMC_STA_DTIMEOUT (0x%x) for cmd %d\n",
+                     __func__, status, cmd->cmdidx);
+               ctx->dpsm_abort = true;
+               return -ETIMEDOUT;
+       }
+
+       if (status & SDMMC_STA_TXUNDERR) {
+               debug("%s: error SDMMC_STA_TXUNDERR (0x%x) for cmd %d\n",
+                     __func__, status, cmd->cmdidx);
+               ctx->dpsm_abort = true;
+               return -EIO;
+       }
+
+       if (status & SDMMC_STA_RXOVERR) {
+               debug("%s: error SDMMC_STA_RXOVERR (0x%x) for cmd %d\n",
+                     __func__, status, cmd->cmdidx);
+               ctx->dpsm_abort = true;
+               return -EIO;
+       }
+
+       if (status & SDMMC_STA_IDMATE) {
+               debug("%s: error SDMMC_STA_IDMATE (0x%x) for cmd %d\n",
+                     __func__, status, cmd->cmdidx);
+               ctx->dpsm_abort = true;
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int stm32_sdmmc2_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+                                struct mmc_data *data)
+{
+       struct stm32_sdmmc2_priv *priv = dev_get_priv(dev);
+       struct stm32_sdmmc2_ctx ctx;
+       u32 cmdat = data ? SDMMC_CMD_CMDTRANS : 0;
+       int ret, retry = 3;
+
+retry_cmd:
+       ctx.data_length = 0;
+       ctx.dpsm_abort = false;
+
+       if (data) {
+               ctx.data_length = data->blocks * data->blocksize;
+               stm32_sdmmc2_start_data(priv, data, &ctx);
+       }
+
+       stm32_sdmmc2_start_cmd(priv, cmd, cmdat);
+
+       debug("%s: send cmd %d data: 0x%x @ 0x%x\n",
+             __func__, cmd->cmdidx,
+             data ? ctx.data_length : 0, (unsigned int)data);
+
+       ret = stm32_sdmmc2_end_cmd(priv, cmd, &ctx);
+
+       if (data && !ret)
+               ret = stm32_sdmmc2_end_data(priv, cmd, data, &ctx);
+
+       /* Clear flags */
+       writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR);
+       if (data)
+               writel(0x0, priv->base + SDMMC_IDMACTRL);
+
+       /*
+        * To stop Data Path State Machine, a stop_transmission command
+        * shall be send on cmd or data errors.
+        */
+       if (ctx.dpsm_abort && (cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION)) {
+               struct mmc_cmd stop_cmd;
+
+               stop_cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
+               stop_cmd.cmdarg = 0;
+               stop_cmd.resp_type = MMC_RSP_R1b;
+
+               debug("%s: send STOP command to abort dpsm treatments\n",
+                     __func__);
+
+               stm32_sdmmc2_start_cmd(priv, &stop_cmd, SDMMC_CMD_CMDSTOP);
+               stm32_sdmmc2_end_cmd(priv, &stop_cmd, &ctx);
+
+               writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR);
+       }
+
+       if ((ret != -ETIMEDOUT) && (ret != 0) && retry) {
+               printf("%s: cmd %d failed, retrying ...\n",
+                      __func__, cmd->cmdidx);
+               retry--;
+               goto retry_cmd;
+       }
+
+       debug("%s: end for CMD %d, ret = %d\n", __func__, cmd->cmdidx, ret);
+
+       return ret;
+}
+
+static void stm32_sdmmc2_pwron(struct stm32_sdmmc2_priv *priv)
+{
+       /* Reset */
+       reset_assert(&priv->reset_ctl);
+       udelay(2);
+       reset_deassert(&priv->reset_ctl);
+
+       udelay(1000);
+
+       /* Set Power State to ON */
+       writel(SDMMC_POWER_PWRCTRL | priv->pwr_reg_msk, priv->base + SDMMC_POWER);
+
+       /*
+        * 1ms: required power up waiting time before starting the
+        * SD initialization sequence
+        */
+       udelay(1000);
+}
+
+#define IS_RISING_EDGE(reg) (reg & SDMMC_CLKCR_NEGEDGE ? 0 : 1)
+static int stm32_sdmmc2_set_ios(struct udevice *dev)
+{
+       struct mmc *mmc = mmc_get_mmc_dev(dev);
+       struct stm32_sdmmc2_priv *priv = dev_get_priv(dev);
+       struct stm32_sdmmc2_plat *plat = dev_get_platdata(dev);
+       struct mmc_config *cfg = &plat->cfg;
+       u32 desired = mmc->clock;
+       u32 sys_clock = clk_get_rate(&priv->clk);
+       u32 clk = 0;
+
+       debug("%s: bus_with = %d, clock = %d\n", __func__,
+             mmc->bus_width, mmc->clock);
+
+       if ((mmc->bus_width == 1) && (desired == cfg->f_min))
+               stm32_sdmmc2_pwron(priv);
+
+       /*
+        * clk_div = 0 => command and data generated on SDMMCCLK falling edge
+        * clk_div > 0 and NEGEDGE = 0 => command and data generated on
+        * SDMMCCLK rising edge
+        * clk_div > 0 and NEGEDGE = 1 => command and data generated on
+        * SDMMCCLK falling edge
+        */
+       if (desired && ((sys_clock > desired) ||
+                       IS_RISING_EDGE(priv->clk_reg_msk))) {
+               clk = DIV_ROUND_UP(sys_clock, 2 * desired);
+               if (clk > SDMMC_CLKCR_CLKDIV_MAX)
+                       clk = SDMMC_CLKCR_CLKDIV_MAX;
+       }
+
+       if (mmc->bus_width == 4)
+               clk |= SDMMC_CLKCR_WIDBUS_4;
+       if (mmc->bus_width == 8)
+               clk |= SDMMC_CLKCR_WIDBUS_8;
+
+       writel(clk | priv->clk_reg_msk, priv->base + SDMMC_CLKCR);
+
+       return 0;
+}
+
+static int stm32_sdmmc2_getcd(struct udevice *dev)
+{
+       struct stm32_sdmmc2_priv *priv = dev_get_priv(dev);
+
+       debug("stm32_sdmmc2_getcd called\n");
+
+       if (dm_gpio_is_valid(&priv->cd_gpio))
+               return dm_gpio_get_value(&priv->cd_gpio);
+
+       return 1;
+}
+
+static const struct dm_mmc_ops stm32_sdmmc2_ops = {
+       .send_cmd = stm32_sdmmc2_send_cmd,
+       .set_ios = stm32_sdmmc2_set_ios,
+       .get_cd = stm32_sdmmc2_getcd,
+};
+
+static int stm32_sdmmc2_probe(struct udevice *dev)
+{
+       struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+       struct stm32_sdmmc2_plat *plat = dev_get_platdata(dev);
+       struct stm32_sdmmc2_priv *priv = dev_get_priv(dev);
+       struct mmc_config *cfg = &plat->cfg;
+       int ret;
+
+       priv->base = dev_read_addr(dev);
+       if (priv->base == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       if (dev_read_bool(dev, "st,negedge"))
+               priv->clk_reg_msk |= SDMMC_CLKCR_NEGEDGE;
+       if (dev_read_bool(dev, "st,dirpol"))
+               priv->pwr_reg_msk |= SDMMC_POWER_DIRPOL;
+
+       ret = clk_get_by_index(dev, 0, &priv->clk);
+       if (ret)
+               return ret;
+
+       ret = clk_enable(&priv->clk);
+       if (ret)
+               goto clk_free;
+
+       ret = reset_get_by_index(dev, 0, &priv->reset_ctl);
+       if (ret)
+               goto clk_disable;
+
+       gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
+                            GPIOD_IS_IN);
+
+       cfg->f_min = 400000;
+       cfg->f_max = dev_read_u32_default(dev, "max-frequency", 52000000);
+       cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+       cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+       cfg->name = "STM32 SDMMC2";
+
+       cfg->host_caps = 0;
+       if (cfg->f_max > 25000000)
+               cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+       switch (dev_read_u32_default(dev, "bus-width", 1)) {
+       case 8:
+               cfg->host_caps |= MMC_MODE_8BIT;
+       case 4:
+               cfg->host_caps |= MMC_MODE_4BIT;
+               break;
+       case 1:
+               break;
+       default:
+               error("invalid \"bus-width\" property, force to 1\n");
+       }
+
+       upriv->mmc = &plat->mmc;
+
+       return 0;
+
+clk_disable:
+       clk_disable(&priv->clk);
+clk_free:
+       clk_free(&priv->clk);
+
+       return ret;
+}
+
+int stm32_sdmmc_bind(struct udevice *dev)
+{
+       struct stm32_sdmmc2_plat *plat = dev_get_platdata(dev);
+
+       return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static const struct udevice_id stm32_sdmmc2_ids[] = {
+       { .compatible = "st,stm32-sdmmc2" },
+       { }
+};
+
+U_BOOT_DRIVER(stm32_sdmmc2) = {
+       .name = "stm32_sdmmc2",
+       .id = UCLASS_MMC,
+       .of_match = stm32_sdmmc2_ids,
+       .ops = &stm32_sdmmc2_ops,
+       .probe = stm32_sdmmc2_probe,
+       .bind = stm32_sdmmc_bind,
+       .priv_auto_alloc_size = sizeof(struct stm32_sdmmc2_priv),
+       .platdata_auto_alloc_size = sizeof(struct stm32_sdmmc2_plat),
+};
index 0786ad0d5f8cdcc733d6b0042592e41a7418fa55..0d1203cb766ff0c045fc8e4857afe3e4ba60daf7 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/dma-direction.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
+#include <power/regulator.h>
 #include <asm/unaligned.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -135,7 +136,7 @@ struct uniphier_sd_priv {
 #define UNIPHIER_SD_CAP_64BIT          BIT(3)  /* Controller is 64bit */
 };
 
-static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, const u32 reg)
+static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, unsigned int reg)
 {
        if (priv->caps & UNIPHIER_SD_CAP_64BIT)
                return readq(priv->regbase + (reg << 1));
@@ -144,7 +145,7 @@ static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, const u32 reg)
 }
 
 static void uniphier_sd_writeq(struct uniphier_sd_priv *priv,
-                              const u64 val, const u32 reg)
+                              u64 val, unsigned int reg)
 {
        if (priv->caps & UNIPHIER_SD_CAP_64BIT)
                writeq(val, priv->regbase + (reg << 1));
@@ -152,7 +153,7 @@ static void uniphier_sd_writeq(struct uniphier_sd_priv *priv,
                writeq(val, priv->regbase + reg);
 }
 
-static u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, const u32 reg)
+static u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, unsigned int reg)
 {
        if (priv->caps & UNIPHIER_SD_CAP_64BIT)
                return readl(priv->regbase + (reg << 1));
@@ -161,7 +162,7 @@ static u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, const u32 reg)
 }
 
 static void uniphier_sd_writel(struct uniphier_sd_priv *priv,
-                              const u32 val, const u32 reg)
+                              u32 val, unsigned int reg)
 {
        if (priv->caps & UNIPHIER_SD_CAP_64BIT)
                writel(val, priv->regbase + (reg << 1));
@@ -246,7 +247,7 @@ static int uniphier_sd_wait_for_irq(struct udevice *dev, unsigned int reg,
        return 0;
 }
 
-static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf,
+static int uniphier_sd_pio_read_one_block(struct udevice *dev, char *pbuf,
                                          uint blocksize)
 {
        struct uniphier_sd_priv *priv = dev_get_priv(dev);
@@ -264,36 +265,33 @@ static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf,
         */
        uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2);
 
-       if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) {
-               if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
+       if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
+               u64 *buf = (u64 *)pbuf;
+               if (likely(IS_ALIGNED((uintptr_t)buf, 8))) {
                        for (i = 0; i < blocksize / 8; i++) {
-                               u64 data;
-                               data = uniphier_sd_readq(priv,
-                                                        UNIPHIER_SD_BUF);
-                               *(*pbuf)++ = data;
-                               *(*pbuf)++ = data >> 32;
+                               *buf++ = uniphier_sd_readq(priv,
+                                                          UNIPHIER_SD_BUF);
                        }
                } else {
-                       for (i = 0; i < blocksize / 4; i++) {
-                               u32 data;
-                               data = uniphier_sd_readl(priv, UNIPHIER_SD_BUF);
-                               *(*pbuf)++ = data;
-                       }
-               }
-       } else {
-               if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
                        for (i = 0; i < blocksize / 8; i++) {
                                u64 data;
                                data = uniphier_sd_readq(priv,
                                                         UNIPHIER_SD_BUF);
-                               put_unaligned(data, (*pbuf)++);
-                               put_unaligned(data >> 32, (*pbuf)++);
+                               put_unaligned(data, buf++);
+                       }
+               }
+       } else {
+               u32 *buf = (u32 *)pbuf;
+               if (likely(IS_ALIGNED((uintptr_t)buf, 4))) {
+                       for (i = 0; i < blocksize / 4; i++) {
+                               *buf++ = uniphier_sd_readl(priv,
+                                                          UNIPHIER_SD_BUF);
                        }
                } else {
                        for (i = 0; i < blocksize / 4; i++) {
                                u32 data;
                                data = uniphier_sd_readl(priv, UNIPHIER_SD_BUF);
-                               put_unaligned(data, (*pbuf)++);
+                               put_unaligned(data, buf++);
                        }
                }
        }
@@ -302,7 +300,7 @@ static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf,
 }
 
 static int uniphier_sd_pio_write_one_block(struct udevice *dev,
-                                          const u32 **pbuf, uint blocksize)
+                                          const char *pbuf, uint blocksize)
 {
        struct uniphier_sd_priv *priv = dev_get_priv(dev);
        int i, ret;
@@ -315,31 +313,30 @@ static int uniphier_sd_pio_write_one_block(struct udevice *dev,
 
        uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2);
 
-       if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) {
-               if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
+       if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
+               const u64 *buf = (const u64 *)pbuf;
+               if (likely(IS_ALIGNED((uintptr_t)buf, 8))) {
                        for (i = 0; i < blocksize / 8; i++) {
-                               u64 data = *(*pbuf)++;
-                               data |= (u64)*(*pbuf)++ << 32;
-                               uniphier_sd_writeq(priv, data,
+                               uniphier_sd_writeq(priv, *buf++,
                                                   UNIPHIER_SD_BUF);
                        }
                } else {
-                       for (i = 0; i < blocksize / 4; i++) {
-                               uniphier_sd_writel(priv, *(*pbuf)++,
+                       for (i = 0; i < blocksize / 8; i++) {
+                               u64 data = get_unaligned(buf++);
+                               uniphier_sd_writeq(priv, data,
                                                   UNIPHIER_SD_BUF);
                        }
                }
        } else {
-               if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
-                       for (i = 0; i < blocksize / 8; i++) {
-                               u64 data = get_unaligned((*pbuf)++);
-                               data |= (u64)get_unaligned((*pbuf)++) << 32;
-                               uniphier_sd_writeq(priv, data,
+               const u32 *buf = (const u32 *)pbuf;
+               if (likely(IS_ALIGNED((uintptr_t)buf, 4))) {
+                       for (i = 0; i < blocksize / 4; i++) {
+                               uniphier_sd_writel(priv, *buf++,
                                                   UNIPHIER_SD_BUF);
                        }
                } else {
                        for (i = 0; i < blocksize / 4; i++) {
-                               u32 data = get_unaligned((*pbuf)++);
+                               u32 data = get_unaligned(buf++);
                                uniphier_sd_writel(priv, data,
                                                   UNIPHIER_SD_BUF);
                        }
@@ -351,19 +348,24 @@ static int uniphier_sd_pio_write_one_block(struct udevice *dev,
 
 static int uniphier_sd_pio_xfer(struct udevice *dev, struct mmc_data *data)
 {
-       u32 *dest = (u32 *)data->dest;
-       const u32 *src = (const u32 *)data->src;
+       const char *src = data->src;
+       char *dest = data->dest;
        int i, ret;
 
        for (i = 0; i < data->blocks; i++) {
                if (data->flags & MMC_DATA_READ)
-                       ret = uniphier_sd_pio_read_one_block(dev, &dest,
+                       ret = uniphier_sd_pio_read_one_block(dev, dest,
                                                             data->blocksize);
                else
-                       ret = uniphier_sd_pio_write_one_block(dev, &src,
+                       ret = uniphier_sd_pio_write_one_block(dev, src,
                                                              data->blocksize);
                if (ret)
                        return ret;
+
+               if (data->flags & MMC_DATA_READ)
+                       dest += data->blocksize;
+               else
+                       src += data->blocksize;
        }
 
        return 0;
@@ -755,6 +757,9 @@ static int uniphier_sd_probe(struct udevice *dev)
        fdt_addr_t base;
        struct clk clk;
        int ret;
+#ifdef CONFIG_DM_REGULATOR
+       struct udevice *vqmmc_dev;
+#endif
 
        base = devfdt_get_addr(dev);
        if (base == FDT_ADDR_T_NONE)
@@ -764,6 +769,15 @@ static int uniphier_sd_probe(struct udevice *dev)
        if (!priv->regbase)
                return -ENOMEM;
 
+#ifdef CONFIG_DM_REGULATOR
+       ret = device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_dev);
+       if (!ret) {
+               /* Set the regulator to 3.3V until we support 1.8V modes */
+               regulator_set_value(vqmmc_dev, 3300000);
+               regulator_set_enable(vqmmc_dev, true);
+       }
+#endif
+
        ret = clk_get_by_index(dev, 0, &clk);
        if (ret < 0) {
                dev_err(dev, "failed to get host clock\n");
index b1f570416425390a2570534de06cdb803962a30b..25249e377a6459ac58e4ebe7a582621322863e37 100644 (file)
@@ -208,6 +208,29 @@ enum {
        GPIO2A0_FLASH_CSN0      = (1 << GPIO2A0_SHIFT),
 };
 
+/*GRF_GPIO2B_IOMUX*/
+enum {
+       GPIO2B3_SHIFT           = 6,
+       GPIO2B3_MASK            = GENMASK(GPIO2B3_SHIFT + 1, GPIO2B3_SHIFT),
+       GPIO2B3_GPIO            = 0,
+       GPIO2B3_SDMMC0_DTECTN   = (1 << GPIO2B3_SHIFT),
+
+       GPIO2B2_SHIFT           = 4,
+       GPIO2B2_MASK            = GENMASK(GPIO2B2_SHIFT + 1, GPIO2B2_SHIFT),
+       GPIO2B2_GPIO            = 0,
+       GPIO2B2_SDMMC0_CMD      = (1 << GPIO2B2_SHIFT),
+
+       GPIO2B1_SHIFT           = 2,
+       GPIO2B1_MASK            = GENMASK(GPIO2B1_SHIFT + 1, GPIO2B1_SHIFT),
+       GPIO2B1_GPIO            = 0,
+       GPIO2B1_SDMMC0_CLKOUT   = (1 << GPIO2B1_SHIFT),
+
+       GPIO2B0_SHIFT           = 0,
+       GPIO2B0_MASK            = GENMASK(GPIO2B0_SHIFT + 1, GPIO2B0_SHIFT),
+       GPIO2B0_GPIO            = 0,
+       GPIO2B0_SDMMC0_D3       = (1 << GPIO2B0_SHIFT),
+};
+
 /*GRF_GPIO2D_IOMUX*/
 enum {
        GPIO2D7_SHIFT           = 14,
@@ -580,11 +603,17 @@ static void pinctrl_rk3368_sdmmc_config(struct rk3368_grf *grf, int mmc_id)
                             GPIO2A4_EMMC_CLKOUT);
                break;
        case PERIPH_ID_SDCARD:
-               /*
-                * We assume that the BROM has already set this up
-                * correctly for us and that there's nothing to do
-                * here.
-                */
+               debug("mmc id = %d setting registers!\n", mmc_id);
+               rk_clrsetreg(&grf->gpio2a_iomux,
+                            GPIO2A5_MASK | GPIO2A7_MASK |
+                            GPIO2A7_MASK,
+                            GPIO2A5_SDMMC0_D0 | GPIO2A6_SDMMC0_D1 |
+                            GPIO2A7_SDMMC0_D2);
+               rk_clrsetreg(&grf->gpio2b_iomux,
+                            GPIO2B0_MASK | GPIO2B1_MASK |
+                            GPIO2B2_MASK | GPIO2B3_MASK,
+                            GPIO2B0_SDMMC0_D3 | GPIO2B1_SDMMC0_CLKOUT |
+                            GPIO2B2_SDMMC0_CMD | GPIO2B3_SDMMC0_DTECTN);
                break;
        default:
                debug("mmc id = %d iomux error!\n", mmc_id);
index 2cfade1cb2d59e8a7ee11a24b1579f58e0549628..8892fa14e0226868d1b1b88aec92d1258fbce76f 100644 (file)
@@ -77,6 +77,13 @@ config DM_REGULATOR_FIXED
        features for fixed value regulators. The driver implements get/set api
        for enable and get only for voltage value.
 
+config SPL_DM_REGULATOR_FIXED
+       bool "Enable Driver Model for REGULATOR Fixed value in SPL"
+       depends on DM_REGULATOR_FIXED
+       ---help---
+       This config enables implementation of driver-model regulator uclass
+       features for fixed value regulators in SPL.
+
 config DM_REGULATOR_GPIO
        bool "Enable Driver Model for GPIO REGULATOR"
        depends on DM_REGULATOR
index b09d03c2c9d09bfbdf44d0f7afdebfd5c9139333..45b5fe724719ce74346b4dc7d15530add992f637 100644 (file)
@@ -5,3 +5,8 @@
 #
 
 obj-$(CONFIG_ROCKCHIP_RK3368) = dmc-rk3368.o
+obj-$(CONFIG_ROCKCHIP_RK3188) = sdram_rk3188.o
+obj-$(CONFIG_ROCKCHIP_RK322X) = sdram_rk322x.o
+obj-$(CONFIG_ROCKCHIP_RK3288) = sdram_rk3288.o
+obj-$(CONFIG_ROCKCHIP_RK3328) = sdram_rk3328.o
+obj-$(CONFIG_ROCKCHIP_RK3399) = sdram_rk3399.o
similarity index 99%
rename from arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
rename to drivers/ram/rockchip/sdram_rk3188.c
index 9d8b225dfac0b3b4d507f58fbbdc0dce99eb12d4..365d00ef542440796f65b38bde0ab7360d37170e 100644 (file)
@@ -682,11 +682,18 @@ out:
 
 static int sdram_get_niu_config(struct rk3188_sdram_params *sdram_params)
 {
-       int i, tmp, size, ret = 0;
+       int i, tmp, size, row, ret = 0;
 
+       row = sdram_params->ch[0].cs0_row;
+       /*
+        * RK3188 share the rank and row bit15, we use same ddr config for 15bit
+        * and 16bit row
+        */
+       if (row == 16)
+               row = 15;
        tmp = sdram_params->ch[0].col - 9;
        tmp -= (sdram_params->ch[0].bw == 2) ? 0 : 1;
-       tmp |= ((sdram_params->ch[0].cs0_row - 13) << 4);
+       tmp |= ((row - 13) << 4);
        size = sizeof(ddrconf_table)/sizeof(ddrconf_table[0]);
        for (i = 0; i < size; i++)
                if (tmp == ddrconf_table[i])
diff --git a/drivers/ram/rockchip/sdram_rk322x.c b/drivers/ram/rockchip/sdram_rk322x.c
new file mode 100644 (file)
index 0000000..cc3138b
--- /dev/null
@@ -0,0 +1,855 @@
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <errno.h>
+#include <ram.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk322x.h>
+#include <asm/arch/grf_rk322x.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sdram_rk322x.h>
+#include <asm/arch/timer.h>
+#include <asm/arch/uart.h>
+#include <asm/arch/sdram_common.h>
+#include <asm/types.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+struct chan_info {
+       struct rk322x_ddr_pctl *pctl;
+       struct rk322x_ddr_phy *phy;
+       struct rk322x_service_sys *msch;
+};
+
+struct dram_info {
+       struct chan_info chan[1];
+       struct ram_info info;
+       struct clk ddr_clk;
+       struct rk322x_cru *cru;
+       struct rk322x_grf *grf;
+};
+
+struct rk322x_sdram_params {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+               struct dtd_rockchip_rk3228_dmc of_plat;
+#endif
+               struct rk322x_sdram_channel ch[1];
+               struct rk322x_pctl_timing pctl_timing;
+               struct rk322x_phy_timing phy_timing;
+               struct rk322x_base_params base;
+               int num_channels;
+               struct regmap *map;
+};
+
+#ifdef CONFIG_TPL_BUILD
+/*
+ * [7:6]  bank(n:n bit bank)
+ * [5:4]  row(13+n)
+ * [3]    cs(0:1 cs, 1:2 cs)
+ * [2:1]  bank(n:n bit bank)
+ * [0]    col(10+n)
+ */
+const char ddr_cfg_2_rbc[] = {
+       ((0 << 6) | (0 << 4) | (0 << 3) | (1 << 2) | 1),
+       ((0 << 6) | (1 << 4) | (0 << 3) | (1 << 2) | 1),
+       ((0 << 6) | (2 << 4) | (0 << 3) | (1 << 2) | 1),
+       ((0 << 6) | (3 << 4) | (0 << 3) | (1 << 2) | 1),
+       ((0 << 6) | (1 << 4) | (0 << 3) | (1 << 2) | 2),
+       ((0 << 6) | (2 << 4) | (0 << 3) | (1 << 2) | 2),
+       ((0 << 6) | (3 << 4) | (0 << 3) | (1 << 2) | 2),
+       ((0 << 6) | (0 << 4) | (0 << 3) | (1 << 2) | 0),
+       ((0 << 6) | (1 << 4) | (0 << 3) | (1 << 2) | 0),
+       ((0 << 6) | (2 << 4) | (0 << 3) | (1 << 2) | 0),
+       ((0 << 6) | (3 << 4) | (0 << 3) | (1 << 2) | 0),
+       ((0 << 6) | (2 << 4) | (0 << 3) | (0 << 2) | 1),
+       ((1 << 6) | (1 << 4) | (0 << 3) | (0 << 2) | 2),
+       ((1 << 6) | (1 << 4) | (0 << 3) | (0 << 2) | 1),
+       ((0 << 6) | (3 << 4) | (1 << 3) | (1 << 2) | 1),
+       ((0 << 6) | (3 << 4) | (1 << 3) | (1 << 2) | 0),
+};
+
+static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
+{
+       int i;
+
+       for (i = 0; i < n / sizeof(u32); i++) {
+               writel(*src, dest);
+               src++;
+               dest++;
+       }
+}
+
+void phy_pctrl_reset(struct rk322x_cru *cru,
+                    struct rk322x_ddr_phy *ddr_phy)
+{
+       rk_clrsetreg(&cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT |
+                       1 << DDRCTRL_SRST_SHIFT | 1 << DDRPHY_PSRST_SHIFT |
+                       1 << DDRPHY_SRST_SHIFT,
+                       1 << DDRCTRL_PSRST_SHIFT | 1 << DDRCTRL_SRST_SHIFT |
+                       1 << DDRPHY_PSRST_SHIFT | 1 << DDRPHY_SRST_SHIFT);
+
+       rockchip_udelay(10);
+
+       rk_clrreg(&cru->cru_softrst_con[5], 1 << DDRPHY_PSRST_SHIFT |
+                                                 1 << DDRPHY_SRST_SHIFT);
+       rockchip_udelay(10);
+
+       rk_clrreg(&cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT |
+                                                 1 << DDRCTRL_SRST_SHIFT);
+       rockchip_udelay(10);
+
+       clrbits_le32(&ddr_phy->ddrphy_reg[0],
+                    SOFT_RESET_MASK << SOFT_RESET_SHIFT);
+       rockchip_udelay(10);
+       setbits_le32(&ddr_phy->ddrphy_reg[0],
+                    SOFT_DERESET_ANALOG);
+       rockchip_udelay(5);
+       setbits_le32(&ddr_phy->ddrphy_reg[0],
+                    SOFT_DERESET_DIGITAL);
+
+       rockchip_udelay(1);
+}
+
+void phy_dll_bypass_set(struct rk322x_ddr_phy *ddr_phy, u32 freq)
+{
+       u32 tmp;
+
+       setbits_le32(&ddr_phy->ddrphy_reg[0x13], 0x10);
+       setbits_le32(&ddr_phy->ddrphy_reg[0x26], 0x10);
+       setbits_le32(&ddr_phy->ddrphy_reg[0x36], 0x10);
+       setbits_le32(&ddr_phy->ddrphy_reg[0x46], 0x10);
+       setbits_le32(&ddr_phy->ddrphy_reg[0x56], 0x10);
+
+       clrbits_le32(&ddr_phy->ddrphy_reg[0x14], 0x8);
+       clrbits_le32(&ddr_phy->ddrphy_reg[0x27], 0x8);
+       clrbits_le32(&ddr_phy->ddrphy_reg[0x37], 0x8);
+       clrbits_le32(&ddr_phy->ddrphy_reg[0x47], 0x8);
+       clrbits_le32(&ddr_phy->ddrphy_reg[0x57], 0x8);
+
+       if (freq <= 400)
+               setbits_le32(&ddr_phy->ddrphy_reg[0xa4], 0x1f);
+       else
+               clrbits_le32(&ddr_phy->ddrphy_reg[0xa4], 0x1f);
+
+       if (freq <= 680)
+               tmp = 3;
+       else
+               tmp = 2;
+
+       writel(tmp, &ddr_phy->ddrphy_reg[0x28]);
+       writel(tmp, &ddr_phy->ddrphy_reg[0x38]);
+       writel(tmp, &ddr_phy->ddrphy_reg[0x48]);
+       writel(tmp, &ddr_phy->ddrphy_reg[0x58]);
+}
+
+static void send_command(struct rk322x_ddr_pctl *pctl,
+                        u32 rank, u32 cmd, u32 arg)
+{
+       writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd);
+       rockchip_udelay(1);
+       while (readl(&pctl->mcmd) & START_CMD)
+               ;
+}
+
+static void memory_init(struct chan_info *chan,
+                       struct rk322x_sdram_params *sdram_params)
+{
+       struct rk322x_ddr_pctl *pctl = chan->pctl;
+       u32 dramtype = sdram_params->base.dramtype;
+
+       if (dramtype == DDR3) {
+               send_command(pctl, 3, DESELECT_CMD, 0);
+               rockchip_udelay(1);
+               send_command(pctl, 3, PREA_CMD, 0);
+               send_command(pctl, 3, MRS_CMD,
+                            (0x02 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
+                            (sdram_params->phy_timing.mr[2] & CMD_ADDR_MASK) <<
+                            CMD_ADDR_SHIFT);
+
+               send_command(pctl, 3, MRS_CMD,
+                            (0x03 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
+                            (sdram_params->phy_timing.mr[3] & CMD_ADDR_MASK) <<
+                            CMD_ADDR_SHIFT);
+
+               send_command(pctl, 3, MRS_CMD,
+                            (0x01 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
+                            (sdram_params->phy_timing.mr[1] & CMD_ADDR_MASK) <<
+                            CMD_ADDR_SHIFT);
+
+               send_command(pctl, 3, MRS_CMD,
+                            (0x00 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
+                            ((sdram_params->phy_timing.mr[0] |
+                              DDR3_DLL_RESET) &
+                            CMD_ADDR_MASK) << CMD_ADDR_SHIFT);
+
+               send_command(pctl, 3, ZQCL_CMD, 0);
+       } else {
+               send_command(pctl, 3, MRS_CMD,
+                            (0x63 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+                            (0 & LPDDR23_OP_MASK) <<
+                            LPDDR23_OP_SHIFT);
+               rockchip_udelay(10);
+               send_command(pctl, 3, MRS_CMD,
+                            (0x10 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+                            (0xff & LPDDR23_OP_MASK) <<
+                            LPDDR23_OP_SHIFT);
+               rockchip_udelay(1);
+               send_command(pctl, 3, MRS_CMD,
+                            (0x10 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+                            (0xff & LPDDR23_OP_MASK) <<
+                            LPDDR23_OP_SHIFT);
+               rockchip_udelay(1);
+               send_command(pctl, 3, MRS_CMD,
+                            (1 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+                            (sdram_params->phy_timing.mr[1] &
+                             LPDDR23_OP_MASK) << LPDDR23_OP_SHIFT);
+               send_command(pctl, 3, MRS_CMD,
+                            (2 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+                            (sdram_params->phy_timing.mr[2] &
+                             LPDDR23_OP_MASK) << LPDDR23_OP_SHIFT);
+               send_command(pctl, 3, MRS_CMD,
+                            (3 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+                            (sdram_params->phy_timing.mr[3] &
+                             LPDDR23_OP_MASK) << LPDDR23_OP_SHIFT);
+               if (dramtype == LPDDR3)
+                       send_command(pctl, 3, MRS_CMD, (11 & LPDDR23_MA_MASK) <<
+                                    LPDDR23_MA_SHIFT |
+                                    (sdram_params->phy_timing.mr11 &
+                                     LPDDR23_OP_MASK) << LPDDR23_OP_SHIFT);
+       }
+}
+
+static u32 data_training(struct chan_info *chan)
+{
+       struct rk322x_ddr_phy *ddr_phy = chan->phy;
+       struct rk322x_ddr_pctl *pctl = chan->pctl;
+       u32 value;
+       u32 bw = (readl(&ddr_phy->ddrphy_reg[0]) >> 4) & 0xf;
+       u32 ret;
+
+       /* disable auto refresh */
+       value = readl(&pctl->trefi) | (1 << 31);
+       writel(1 << 31, &pctl->trefi);
+
+       clrsetbits_le32(&ddr_phy->ddrphy_reg[2], 0x30,
+                       DQS_SQU_CAL_SEL_CS0);
+       setbits_le32(&ddr_phy->ddrphy_reg[2], DQS_SQU_CAL_START);
+
+       rockchip_udelay(30);
+       ret = readl(&ddr_phy->ddrphy_reg[0xff]);
+
+       clrbits_le32(&ddr_phy->ddrphy_reg[2],
+                    DQS_SQU_CAL_START);
+
+       /*
+        * since data training will take about 20us, so send some auto
+        * refresh(about 7.8us) to complement the lost time
+        */
+       send_command(pctl, 3, PREA_CMD, 0);
+       send_command(pctl, 3, REF_CMD, 0);
+
+       writel(value, &pctl->trefi);
+
+       if (ret & 0x10) {
+               ret = -1;
+       } else {
+               ret = (ret & 0xf) ^ bw;
+               ret = (ret == 0) ? 0 : -1;
+       }
+       return ret;
+}
+
+static void move_to_config_state(struct rk322x_ddr_pctl *pctl)
+{
+       unsigned int state;
+
+       while (1) {
+               state = readl(&pctl->stat) & PCTL_STAT_MASK;
+               switch (state) {
+               case LOW_POWER:
+                       writel(WAKEUP_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MASK)
+                               != ACCESS)
+                               ;
+                       /*
+                        * If at low power state, need wakeup first, and then
+                        * enter the config, so fallthrough
+                        */
+               case ACCESS:
+                       /* fallthrough */
+               case INIT_MEM:
+                       writel(CFG_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MASK) != CONFIG)
+                               ;
+                       break;
+               case CONFIG:
+                       return;
+               default:
+                       break;
+               }
+       }
+}
+
+static void move_to_access_state(struct rk322x_ddr_pctl *pctl)
+{
+       unsigned int state;
+
+       while (1) {
+               state = readl(&pctl->stat) & PCTL_STAT_MASK;
+               switch (state) {
+               case LOW_POWER:
+                       writel(WAKEUP_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MASK) != ACCESS)
+                               ;
+                       break;
+               case INIT_MEM:
+                       writel(CFG_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MASK) != CONFIG)
+                               ;
+                       /* fallthrough */
+               case CONFIG:
+                       writel(GO_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MASK) != ACCESS)
+                               ;
+                       break;
+               case ACCESS:
+                       return;
+               default:
+                       break;
+               }
+       }
+}
+
+static void move_to_lowpower_state(struct rk322x_ddr_pctl *pctl)
+{
+       unsigned int state;
+
+       while (1) {
+               state = readl(&pctl->stat) & PCTL_STAT_MASK;
+               switch (state) {
+               case INIT_MEM:
+                       writel(CFG_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MASK) != CONFIG)
+                               ;
+                       /* fallthrough */
+               case CONFIG:
+                       writel(GO_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MASK) != ACCESS)
+                               ;
+                       break;
+               case ACCESS:
+                       writel(SLEEP_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MASK) !=
+                              LOW_POWER)
+                               ;
+                       break;
+               case LOW_POWER:
+                       return;
+               default:
+                       break;
+               }
+       }
+}
+
+/* pctl should in low power mode when call this function */
+static void phy_softreset(struct dram_info *dram)
+{
+       struct rk322x_ddr_phy *ddr_phy = dram->chan[0].phy;
+       struct rk322x_grf *grf = dram->grf;
+
+       writel(GRF_DDRPHY_BUFFEREN_CORE_EN, &grf->soc_con[0]);
+       clrbits_le32(&ddr_phy->ddrphy_reg[0], 0x3 << 2);
+       rockchip_udelay(1);
+       setbits_le32(&ddr_phy->ddrphy_reg[0], 1 << 2);
+       rockchip_udelay(5);
+       setbits_le32(&ddr_phy->ddrphy_reg[0], 1 << 3);
+       writel(GRF_DDRPHY_BUFFEREN_CORE_DIS, &grf->soc_con[0]);
+}
+
+/* bw: 2: 32bit, 1:16bit */
+static void set_bw(struct dram_info *dram, u32 bw)
+{
+       struct rk322x_ddr_pctl *pctl = dram->chan[0].pctl;
+       struct rk322x_ddr_phy *ddr_phy = dram->chan[0].phy;
+       struct rk322x_grf *grf = dram->grf;
+
+       if (bw == 1) {
+               setbits_le32(&pctl->ppcfg, 1);
+               clrbits_le32(&ddr_phy->ddrphy_reg[0], 0xc << 4);
+               writel(GRF_MSCH_NOC_16BIT_EN, &grf->soc_con[0]);
+               clrbits_le32(&ddr_phy->ddrphy_reg[0x46], 0x8);
+               clrbits_le32(&ddr_phy->ddrphy_reg[0x56], 0x8);
+       } else {
+               clrbits_le32(&pctl->ppcfg, 1);
+               setbits_le32(&ddr_phy->ddrphy_reg[0], 0xf << 4);
+               writel(GRF_DDR_32BIT_EN | GRF_MSCH_NOC_32BIT_EN,
+                      &grf->soc_con[0]);
+               setbits_le32(&ddr_phy->ddrphy_reg[0x46], 0x8);
+               setbits_le32(&ddr_phy->ddrphy_reg[0x56], 0x8);
+       }
+}
+
+static void pctl_cfg(struct rk322x_ddr_pctl *pctl,
+                    struct rk322x_sdram_params *sdram_params,
+                    struct rk322x_grf *grf)
+{
+       u32 burst_len;
+       u32 bw;
+       u32 dramtype = sdram_params->base.dramtype;
+
+       if (sdram_params->ch[0].bw == 2)
+               bw = GRF_DDR_32BIT_EN | GRF_MSCH_NOC_32BIT_EN;
+       else
+               bw = GRF_MSCH_NOC_16BIT_EN;
+
+       writel(DFI_INIT_START | DFI_DATA_BYTE_DISABLE_EN, &pctl->dfistcfg0);
+       writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN, &pctl->dfistcfg1);
+       writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2);
+       writel(0x51010, &pctl->dfilpcfg0);
+
+       writel(1, &pctl->dfitphyupdtype0);
+       writel(0x0d, &pctl->dfitphyrdlat);
+       writel(0, &pctl->dfitphywrdata);
+
+       writel(0, &pctl->dfiupdcfg);
+       copy_to_reg(&pctl->togcnt1u, &sdram_params->pctl_timing.togcnt1u,
+                   sizeof(struct rk322x_pctl_timing));
+       if (dramtype == DDR3) {
+               writel((1 << 3) | (1 << 11),
+                      &pctl->dfiodtcfg);
+               writel(7 << 16, &pctl->dfiodtcfg1);
+               writel((readl(&pctl->tcl) - 1) / 2 - 1, &pctl->dfitrddataen);
+               writel((readl(&pctl->tcwl) - 1) / 2 - 1, &pctl->dfitphywrlat);
+               writel(500, &pctl->trsth);
+               writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT | DDR3_EN |
+                      DDR2_DDR3_BL_8 | (6 - 4) << TFAW_SHIFT | PD_EXIT_SLOW |
+                      1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT,
+                      &pctl->mcfg);
+               writel(bw | GRF_DDR3_EN, &grf->soc_con[0]);
+       } else {
+               if (sdram_params->phy_timing.bl & PHT_BL_8)
+                       burst_len = MDDR_LPDDR2_BL_8;
+               else
+                       burst_len = MDDR_LPDDR2_BL_4;
+
+               writel(readl(&pctl->tcl) / 2 - 1, &pctl->dfitrddataen);
+               writel(readl(&pctl->tcwl) / 2 - 1, &pctl->dfitphywrlat);
+               writel(0, &pctl->trsth);
+               if (dramtype == LPDDR2) {
+                       writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT |
+                              LPDDR2_S4 | LPDDR2_EN | burst_len |
+                              (6 - 4) << TFAW_SHIFT | PD_EXIT_FAST |
+                              1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT,
+                              &pctl->mcfg);
+                       writel(0, &pctl->dfiodtcfg);
+                       writel(0, &pctl->dfiodtcfg1);
+               } else {
+                       writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT |
+                              LPDDR2_S4 | LPDDR3_EN | burst_len |
+                              (6 - 4) << TFAW_SHIFT | PD_EXIT_FAST |
+                              1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT,
+                              &pctl->mcfg);
+                       writel((1 << 3) | (1 << 2), &pctl->dfiodtcfg);
+                       writel((7 << 16) | 4, &pctl->dfiodtcfg1);
+               }
+               writel(bw | GRF_LPDDR2_3_EN, &grf->soc_con[0]);
+       }
+       setbits_le32(&pctl->scfg, 1);
+}
+
+static void phy_cfg(struct chan_info *chan,
+                   struct rk322x_sdram_params *sdram_params)
+{
+       struct rk322x_ddr_phy *ddr_phy = chan->phy;
+       struct rk322x_service_sys *axi_bus = chan->msch;
+       struct rk322x_msch_timings *noc_timing = &sdram_params->base.noc_timing;
+       struct rk322x_phy_timing *phy_timing = &sdram_params->phy_timing;
+       struct rk322x_pctl_timing *pctl_timing = &sdram_params->pctl_timing;
+       u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
+
+       writel(noc_timing->ddrtiming, &axi_bus->ddrtiming);
+       writel(noc_timing->ddrmode, &axi_bus->ddrmode);
+       writel(noc_timing->readlatency, &axi_bus->readlatency);
+       writel(noc_timing->activate, &axi_bus->activate);
+       writel(noc_timing->devtodev, &axi_bus->devtodev);
+
+       switch (sdram_params->base.dramtype) {
+       case DDR3:
+               writel(PHY_DDR3 | phy_timing->bl, &ddr_phy->ddrphy_reg[1]);
+               break;
+       case LPDDR2:
+               writel(PHY_LPDDR2 | phy_timing->bl, &ddr_phy->ddrphy_reg[1]);
+               break;
+       default:
+               writel(PHY_LPDDR2 | phy_timing->bl, &ddr_phy->ddrphy_reg[1]);
+               break;
+       }
+
+       writel(phy_timing->cl_al, &ddr_phy->ddrphy_reg[0xb]);
+       writel(pctl_timing->tcwl, &ddr_phy->ddrphy_reg[0xc]);
+
+       cmd_drv = PHY_RON_RTT_34OHM;
+       clk_drv = PHY_RON_RTT_45OHM;
+       dqs_drv = PHY_RON_RTT_34OHM;
+       if (sdram_params->base.dramtype == LPDDR2)
+               dqs_odt = PHY_RON_RTT_DISABLE;
+       else
+               dqs_odt = PHY_RON_RTT_225OHM;
+
+       writel(cmd_drv, &ddr_phy->ddrphy_reg[0x11]);
+       clrsetbits_le32(&ddr_phy->ddrphy_reg[0x12], (0x1f << 3), cmd_drv << 3);
+       writel(clk_drv, &ddr_phy->ddrphy_reg[0x16]);
+       writel(clk_drv, &ddr_phy->ddrphy_reg[0x18]);
+
+       writel(dqs_drv, &ddr_phy->ddrphy_reg[0x20]);
+       writel(dqs_drv, &ddr_phy->ddrphy_reg[0x2f]);
+       writel(dqs_drv, &ddr_phy->ddrphy_reg[0x30]);
+       writel(dqs_drv, &ddr_phy->ddrphy_reg[0x3f]);
+       writel(dqs_drv, &ddr_phy->ddrphy_reg[0x40]);
+       writel(dqs_drv, &ddr_phy->ddrphy_reg[0x4f]);
+       writel(dqs_drv, &ddr_phy->ddrphy_reg[0x50]);
+       writel(dqs_drv, &ddr_phy->ddrphy_reg[0x5f]);
+
+       writel(dqs_odt, &ddr_phy->ddrphy_reg[0x21]);
+       writel(dqs_odt, &ddr_phy->ddrphy_reg[0x2e]);
+       writel(dqs_odt, &ddr_phy->ddrphy_reg[0x31]);
+       writel(dqs_odt, &ddr_phy->ddrphy_reg[0x3e]);
+       writel(dqs_odt, &ddr_phy->ddrphy_reg[0x41]);
+       writel(dqs_odt, &ddr_phy->ddrphy_reg[0x4e]);
+       writel(dqs_odt, &ddr_phy->ddrphy_reg[0x51]);
+       writel(dqs_odt, &ddr_phy->ddrphy_reg[0x5e]);
+}
+
+void dram_cfg_rbc(struct chan_info *chan,
+                 struct rk322x_sdram_params *sdram_params)
+{
+       char noc_config;
+       int i = 0;
+       struct rk322x_sdram_channel *config = &sdram_params->ch[0];
+       struct rk322x_service_sys *axi_bus = chan->msch;
+
+       move_to_config_state(chan->pctl);
+
+       if ((config->rank == 2) && (config->cs1_row == config->cs0_row)) {
+               if ((config->col + config->bw) == 12) {
+                       i = 14;
+                       goto finish;
+               } else if ((config->col + config->bw) == 11) {
+                       i = 15;
+                       goto finish;
+               }
+       }
+       noc_config = ((config->cs0_row - 13) << 4) | ((config->bk - 2) << 2) |
+                               (config->col + config->bw - 11);
+       for (i = 0; i < 11; i++) {
+               if (noc_config == ddr_cfg_2_rbc[i])
+                       break;
+       }
+
+       if (i < 11)
+               goto finish;
+
+       noc_config = ((config->bk - 2) << 6) | ((config->cs0_row - 13) << 4) |
+                               (config->col + config->bw - 11);
+
+       for (i = 11; i < 14; i++) {
+               if (noc_config == ddr_cfg_2_rbc[i])
+                       break;
+       }
+       if (i < 14)
+               goto finish;
+       else
+               i = 0;
+
+finish:
+       writel(i, &axi_bus->ddrconf);
+       move_to_access_state(chan->pctl);
+}
+
+static void dram_all_config(const struct dram_info *dram,
+                           struct rk322x_sdram_params *sdram_params)
+{
+       struct rk322x_sdram_channel *info = &sdram_params->ch[0];
+       u32 sys_reg = 0;
+
+       sys_reg |= sdram_params->base.dramtype << SYS_REG_DDRTYPE_SHIFT;
+       sys_reg |= (1 - 1) << SYS_REG_NUM_CH_SHIFT;
+       sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(0);
+       sys_reg |= 1 << SYS_REG_CHINFO_SHIFT(0);
+       sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(0);
+       sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(0);
+       sys_reg |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(0);
+       sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(0);
+       sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(0);
+       sys_reg |= (2 >> info->bw) << SYS_REG_BW_SHIFT(0);
+       sys_reg |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(0);
+
+       writel(sys_reg, &dram->grf->os_reg[2]);
+}
+
+#define TEST_PATTEN    0x5aa5f00f
+
+static int dram_cap_detect(struct dram_info *dram,
+                          struct rk322x_sdram_params *sdram_params)
+{
+       u32 bw, row, col, addr;
+       u32 ret = 0;
+       struct rk322x_service_sys *axi_bus = dram->chan[0].msch;
+
+       if (sdram_params->base.dramtype == DDR3)
+               sdram_params->ch[0].dbw = 1;
+       else
+               sdram_params->ch[0].dbw = 2;
+
+       move_to_config_state(dram->chan[0].pctl);
+       /* bw detect */
+       set_bw(dram, 2);
+       if (data_training(&dram->chan[0]) == 0) {
+               bw = 2;
+       } else {
+               bw = 1;
+               set_bw(dram, 1);
+               move_to_lowpower_state(dram->chan[0].pctl);
+               phy_softreset(dram);
+               move_to_config_state(dram->chan[0].pctl);
+               if (data_training(&dram->chan[0])) {
+                       printf("BW detect error\n");
+                       ret = -EINVAL;
+               }
+       }
+       sdram_params->ch[0].bw = bw;
+       sdram_params->ch[0].bk = 3;
+
+       if (bw == 2)
+               writel(6, &axi_bus->ddrconf);
+       else
+               writel(3, &axi_bus->ddrconf);
+       move_to_access_state(dram->chan[0].pctl);
+       for (col = 11; col >= 9; col--) {
+               writel(0, CONFIG_SYS_SDRAM_BASE);
+               addr = CONFIG_SYS_SDRAM_BASE +
+                       (1 << (col + bw - 1));
+               writel(TEST_PATTEN, addr);
+               if ((readl(addr) == TEST_PATTEN) &&
+                   (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+                       break;
+       }
+       if (col == 8) {
+               printf("Col detect error\n");
+               ret = -EINVAL;
+               goto out;
+       } else {
+               sdram_params->ch[0].col = col;
+       }
+
+       writel(10, &axi_bus->ddrconf);
+
+       /* Detect row*/
+       for (row = 16; row >= 12; row--) {
+               writel(0, CONFIG_SYS_SDRAM_BASE);
+               addr = CONFIG_SYS_SDRAM_BASE + (1u << (row + 11 + 3 - 1));
+               writel(TEST_PATTEN, addr);
+               if ((readl(addr) == TEST_PATTEN) &&
+                   (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+                       break;
+       }
+       if (row == 11) {
+               printf("Row detect error\n");
+               ret = -EINVAL;
+       } else {
+               sdram_params->ch[0].cs1_row = row;
+               sdram_params->ch[0].row_3_4 = 0;
+               sdram_params->ch[0].cs0_row = row;
+       }
+       /* cs detect */
+       writel(0, CONFIG_SYS_SDRAM_BASE);
+       writel(TEST_PATTEN, CONFIG_SYS_SDRAM_BASE + (1u << 30));
+       writel(~TEST_PATTEN, CONFIG_SYS_SDRAM_BASE + (1u << 30) + 4);
+       if ((readl(CONFIG_SYS_SDRAM_BASE + (1u << 30)) == TEST_PATTEN) &&
+           (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+               sdram_params->ch[0].rank = 2;
+       else
+               sdram_params->ch[0].rank = 1;
+out:
+       return ret;
+}
+
+static int sdram_init(struct dram_info *dram,
+                     struct rk322x_sdram_params *sdram_params)
+{
+       int ret;
+
+       ret = clk_set_rate(&dram->ddr_clk,
+                          sdram_params->base.ddr_freq * MHz * 2);
+       if (ret < 0) {
+               printf("Could not set DDR clock\n");
+               return ret;
+       }
+
+       phy_pctrl_reset(dram->cru, dram->chan[0].phy);
+       phy_dll_bypass_set(dram->chan[0].phy, sdram_params->base.ddr_freq);
+       pctl_cfg(dram->chan[0].pctl, sdram_params, dram->grf);
+       phy_cfg(&dram->chan[0], sdram_params);
+       writel(POWER_UP_START, &dram->chan[0].pctl->powctl);
+       while (!(readl(&dram->chan[0].pctl->powstat) & POWER_UP_DONE))
+               ;
+       memory_init(&dram->chan[0], sdram_params);
+       move_to_access_state(dram->chan[0].pctl);
+       ret = dram_cap_detect(dram, sdram_params);
+       if (ret)
+               goto out;
+       dram_cfg_rbc(&dram->chan[0], sdram_params);
+       dram_all_config(dram, sdram_params);
+out:
+       return ret;
+}
+
+static int rk322x_dmc_ofdata_to_platdata(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+       struct rk322x_sdram_params *params = dev_get_platdata(dev);
+       const void *blob = gd->fdt_blob;
+       int node = dev_of_offset(dev);
+       int ret;
+
+       params->num_channels = 1;
+
+       ret = fdtdec_get_int_array(blob, node, "rockchip,pctl-timing",
+                                  (u32 *)&params->pctl_timing,
+                                  sizeof(params->pctl_timing) / sizeof(u32));
+       if (ret) {
+               printf("%s: Cannot read rockchip,pctl-timing\n", __func__);
+               return -EINVAL;
+       }
+       ret = fdtdec_get_int_array(blob, node, "rockchip,phy-timing",
+                                  (u32 *)&params->phy_timing,
+                                  sizeof(params->phy_timing) / sizeof(u32));
+       if (ret) {
+               printf("%s: Cannot read rockchip,phy-timing\n", __func__);
+               return -EINVAL;
+       }
+       ret = fdtdec_get_int_array(blob, node, "rockchip,sdram-params",
+                                  (u32 *)&params->base,
+                                  sizeof(params->base) / sizeof(u32));
+       if (ret) {
+               printf("%s: Cannot read rockchip,sdram-params\n", __func__);
+               return -EINVAL;
+       }
+       ret = regmap_init_mem(dev, &params->map);
+       if (ret)
+               return ret;
+#endif
+
+       return 0;
+}
+#endif /* CONFIG_TPL_BUILD */
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int conv_of_platdata(struct udevice *dev)
+{
+       struct rk322x_sdram_params *plat = dev_get_platdata(dev);
+       struct dtd_rockchip_rk322x_dmc *of_plat = &plat->of_plat;
+       int ret;
+
+       memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing,
+              sizeof(plat->pctl_timing));
+       memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing,
+              sizeof(plat->phy_timing));
+       memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
+
+       plat->num_channels = 1;
+       ret = regmap_init_mem_platdata(dev, of_plat->reg,
+                                      ARRAY_SIZE(of_plat->reg) / 2,
+                                      &plat->map);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+#endif
+
+static int rk322x_dmc_probe(struct udevice *dev)
+{
+#ifdef CONFIG_TPL_BUILD
+       struct rk322x_sdram_params *plat = dev_get_platdata(dev);
+       int ret;
+       struct udevice *dev_clk;
+#endif
+       struct dram_info *priv = dev_get_priv(dev);
+
+       priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+#ifdef CONFIG_TPL_BUILD
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+       ret = conv_of_platdata(dev);
+       if (ret)
+               return ret;
+#endif
+
+       priv->chan[0].msch = syscon_get_first_range(ROCKCHIP_SYSCON_MSCH);
+       priv->chan[0].pctl = regmap_get_range(plat->map, 0);
+       priv->chan[0].phy = regmap_get_range(plat->map, 1);
+       ret = rockchip_get_clk(&dev_clk);
+       if (ret)
+               return ret;
+       priv->ddr_clk.id = CLK_DDR;
+       ret = clk_request(dev_clk, &priv->ddr_clk);
+       if (ret)
+               return ret;
+
+       priv->cru = rockchip_get_cru();
+       if (IS_ERR(priv->cru))
+               return PTR_ERR(priv->cru);
+       ret = sdram_init(priv, plat);
+       if (ret)
+               return ret;
+#else
+       priv->info.base = CONFIG_SYS_SDRAM_BASE;
+       priv->info.size = rockchip_sdram_size(
+                       (phys_addr_t)&priv->grf->os_reg[2]);
+#endif
+
+       return 0;
+}
+
+static int rk322x_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+       struct dram_info *priv = dev_get_priv(dev);
+
+       *info = priv->info;
+
+       return 0;
+}
+
+static struct ram_ops rk322x_dmc_ops = {
+       .get_info = rk322x_dmc_get_info,
+};
+
+static const struct udevice_id rk322x_dmc_ids[] = {
+       { .compatible = "rockchip,rk3228-dmc" },
+       { }
+};
+
+U_BOOT_DRIVER(dmc_rk322x) = {
+       .name = "rockchip_rk322x_dmc",
+       .id = UCLASS_RAM,
+       .of_match = rk322x_dmc_ids,
+       .ops = &rk322x_dmc_ops,
+#ifdef CONFIG_TPL_BUILD
+       .ofdata_to_platdata = rk322x_dmc_ofdata_to_platdata,
+#endif
+       .probe = rk322x_dmc_probe,
+       .priv_auto_alloc_size = sizeof(struct dram_info),
+#ifdef CONFIG_TPL_BUILD
+       .platdata_auto_alloc_size = sizeof(struct rk322x_sdram_params),
+#endif
+};
+
index 291ef9576ad485511aad1a56a98cd756bff7d1e1..eda252d0b30f65f3fbc8724b8798ab9a699b0931 100644 (file)
@@ -563,6 +563,7 @@ static const struct dm_spi_ops davinci_spi_ops = {
 static const struct udevice_id davinci_spi_ids[] = {
        { .compatible = "ti,keystone-spi" },
        { .compatible = "ti,dm6441-spi" },
+       { .compatible = "ti,da830-spi" },
        { }
 };
 
index daf021b647e6fdfa6d6baf091eaad707f58b55bb..b6535705a52003a5f047ec2d0aceb3af62abcc47 100644 (file)
@@ -22,8 +22,8 @@ extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __initdata_begin[], __initdata_end[];
 extern char __start_rodata[], __end_rodata[];
-extern char __efi_hello_world_begin[];
-extern char __efi_hello_world_end[];
+extern char __efi_helloworld_begin[];
+extern char __efi_helloworld_end[];
 
 /* Start and end of .ctors section - used for constructor calls. */
 extern char __ctors_start[], __ctors_end[];
index 1965812a9d5a39f0148ce133a895a69b4058d07b..41b4d7efa82b3f88994b95a61071310ae51462fe 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef BLK_H
 #define BLK_H
 
+#include <efi.h>
+
 #ifdef CONFIG_SYS_64BIT_LBA
 typedef uint64_t lbaint_t;
 #define LBAFlength "ll"
@@ -40,6 +42,17 @@ enum if_type {
 #define BLK_PRD_SIZE           20
 #define BLK_REV_SIZE           8
 
+/*
+ * Identifies the partition table type (ie. MBR vs GPT GUID) signature
+ */
+enum sig_type {
+       SIG_TYPE_NONE,
+       SIG_TYPE_MBR,
+       SIG_TYPE_GUID,
+
+       SIG_TYPE_COUNT                  /* Number of signature types */
+};
+
 /*
  * With driver model (CONFIG_BLK) this is uclass platform data, accessible
  * with dev_get_uclass_platdata(dev)
@@ -67,6 +80,11 @@ struct blk_desc {
        char            vendor[BLK_VEN_SIZE + 1]; /* device vendor string */
        char            product[BLK_PRD_SIZE + 1]; /* device product number */
        char            revision[BLK_REV_SIZE + 1]; /* firmware revision */
+       enum sig_type   sig_type;       /* Partition table signature type */
+       union {
+               uint32_t mbr_sig;       /* MBR integer signature */
+               efi_guid_t guid_sig;    /* GPT GUID Signature */
+       };
 #if CONFIG_IS_ENABLED(BLK)
        /*
         * For now we have a few functions which take struct blk_desc as a
index 9ed6b9892cd4a1aca02119319c6eb080ec241208..e0d0034ed344df59391f26cd58f79454b28afa1a 100644 (file)
 
 #define BOOTENV_SHARED_EFI                                                \
        "boot_efi_binary="                                                \
+               "if fdt addr ${fdt_addr_r}; then "                        \
+                       "bootefi bootmgr ${fdt_addr_r};"                  \
+               "else "                                                   \
+                       "bootefi bootmgr ${fdtcontroladdr};"              \
+               "fi;"                                                     \
                "load ${devtype} ${devnum}:${distro_bootpart} "           \
                        "${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; "      \
                "if fdt addr ${fdt_addr_r}; then "                        \
index 708a98f8270948e9edbe772528c1520e1e1061ef..adb33a9e3ead9621dd0e3c11ff95efcafc638229 100644 (file)
@@ -21,6 +21,7 @@
  * header. That is 0x800FFFC0--0x80100000 should not be used for any
  * other needs.
  */
+
 #define CONFIG_SYS_TEXT_BASE           0x80100000
 #define CONFIG_SYS_SPL_MALLOC_START    0x80208000
 #define CONFIG_SYS_SPL_MALLOC_SIZE     0x100000
 
 /* Hardware drivers */
 
-/* NS16550 Configuration */
-#define CONFIG_SYS_NS16550_SERIAL
-#define CONFIG_SYS_NS16550_REG_SIZE    (-4)
-
-/* select serial console configuration */
-#define CONFIG_CONS_INDEX              3
-#define CONFIG_SYS_NS16550_COM3                OMAP34XX_UART3
-#define CONFIG_SERIAL3                 3       /* UART3 on AM3517 EVM */
-
-
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
 
@@ -72,7 +63,6 @@
 #endif /* CONFIG_USB_MUSB_AM35X */
 
 /* I2C */
-#define CONFIG_SYS_I2C
 #define CONFIG_SYS_OMAP24_I2C_SPEED    100000
 #define CONFIG_SYS_OMAP24_I2C_SLAVE    1
 
 #define CONFIG_SPL_FRAMEWORK
 #undef CONFIG_SPL_TEXT_BASE
 #define CONFIG_SPL_TEXT_BASE           0x40200000
-#define CONFIG_SPL_MAX_SIZE            (SRAM_SCRATCH_SPACE_ADDR - \
-                                        CONFIG_SPL_TEXT_BASE)
 
 #undef CONFIG_SPL_BSS_START_ADDR
 #define CONFIG_SPL_BSS_START_ADDR      0x80000000
index b84f6e3480cb118d9fbb14f9de249341c9d186b4..7ee69b0c787ecfc17b585b7ff3efeb8a06bc2636 100644 (file)
 #define NANDBOOT
 #endif /* CONFIG_NAND */
 
+#if defined(CONFIG_TI_SECURE_DEVICE)
+/* Avoid relocating onto firewalled area at end of DRAM */
+#define CONFIG_PRAM (64 * 1024)
+#endif /* CONFIG_TI_SECURE_DEVICE */
+
 #endif /* __CONFIG_AM43XX_EVM_H */
index 0c70c5305033e30fa757af80801148b648d507d8..bf555ccdc2ed4c430f3aaca582dee15bf90b162d 100644 (file)
@@ -44,7 +44,8 @@
 #define PARTS_DEFAULT \
        /* Linux partitions */ \
        "uuid_disk=${uuid_gpt_disk};" \
-       "name=rootfs,start=2MiB,size=-,uuid=${uuid_gpt_rootfs}\0" \
+       "name=bootloader,start=384K,size=1792K,uuid=${uuid_gpt_bootloader};" \
+       "name=rootfs,start=2688K,size=-,uuid=${uuid_gpt_rootfs}\0" \
        /* Android partitions */ \
        "partitions_android=" \
        "uuid_disk=${uuid_gpt_disk};" \
index c05c64cad731bd7356f4097ee0b4adfae977352f..821b1fe53495527f9e0071ab1224d89008ddd3c4 100644 (file)
 #define CONFIG_USE_SPIFLASH
 #endif
 
+/*
+* Disable DM_* for SPL build and can be re-enabled after adding
+* DM support in SPL
+*/
+#ifdef CONFIG_SPL_BUILD
+#undef CONFIG_DM_SPI
+#undef CONFIG_DM_SPI_FLASH
+#undef CONFIG_DM_I2C
+#undef CONFIG_DM_I2C_COMPAT
+#endif
 /*
  * SoC Configuration
  */
 /*
  * Serial Driver info
  */
+
+#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_DIRECT_NOR_BOOT)
 #define CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE    -4      /* NS16550 register size */
 #define CONFIG_SYS_NS16550_COM1        DAVINCI_UART2_BASE /* Base address of UART2 */
+#endif
 #define CONFIG_SYS_NS16550_CLK clk_get(DAVINCI_UART2_CLKID)
 #define CONFIG_CONS_INDEX      1               /* use UART0 for console */
 
 #define CONFIG_SPI
 #define CONFIG_DAVINCI_SPI
-#define CONFIG_SYS_SPI_BASE            DAVINCI_SPI1_BASE
 #define CONFIG_SYS_SPI_CLK             clk_get(DAVINCI_SPI1_CLKID)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_SPI_BASE            DAVINCI_SPI1_BASE
 #define CONFIG_SF_DEFAULT_SPEED                30000000
 #define CONFIG_ENV_SPI_MAX_HZ  CONFIG_SF_DEFAULT_SPEED
+#endif
 
 #ifdef CONFIG_USE_SPIFLASH
 #define CONFIG_SPL_SPI_LOAD
 /*
  * I2C Configuration
  */
-#define CONFIG_SYS_I2C
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_SYS_I2C_DAVINCI
-#define CONFIG_SYS_DAVINCI_I2C_SPEED           25000
-#define CONFIG_SYS_DAVINCI_I2C_SLAVE   10 /* Bogus, master-only in U-Boot */
 #define CONFIG_SYS_I2C_EXPANDER_ADDR   0x20
+#endif
 
 /*
  * Flash & Environment
 #define CONFIG_ENV_SIZE                        (64 << 10)
 #define CONFIG_ENV_OFFSET              (512 << 10)
 #define CONFIG_ENV_SECT_SIZE           (64 << 10)
+#ifdef CONFIG_SPL_BUILD
+#undef CONFIG_SPI_FLASH_MTD
+#endif
+#define CONFIG_MTD_DEVICE              /* needed for mtdparts commands */
+#define CONFIG_MTD_PARTITIONS          /* required for UBI partition support */
+#define MTDIDS_DEFAULT                 "nor0=spi0.0"
+#define MTDPARTS_DEFAULT               "mtdparts=spi0.0:"\
+                                               "512k(u-boot.ais),"\
+                                               "64k(u-boot-env),"\
+                                               "7552k(kernel-spare),"\
+                                               "64k(MAC-Address)"
 #endif
 
 /*
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_REVISION_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
-#define CONFIG_EXTRA_ENV_SETTINGS      "hwconfig=dsp:wake=yes"
+
+#define CONFIG_BOOTCOMMAND \
+               "run envboot; " \
+               "run mmcboot; "
+
+#define DEFAULT_LINUX_BOOT_ENV \
+       "loadaddr=0xc0700000\0" \
+       "fdtaddr=0xc0600000\0" \
+       "scriptaddr=0xc0600000\0"
+
+#include <environment/ti/mmc.h>
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+       DEFAULT_LINUX_BOOT_ENV \
+       DEFAULT_MMC_TI_ARGS \
+       "bootpart=0:2\0" \
+       "bootdir=/boot\0" \
+       "bootfile=zImage\0" \
+       "fdtfile=da850-evm.dtb\0" \
+       "boot_fdt=yes\0" \
+       "boot_fit=0\0" \
+       "console=ttyS2,115200n8\0" \
+       "hwconfig=dsp:wake=yes"
 
 #ifdef CONFIG_CMD_BDI
 #define CONFIG_CLOCKS
index 6c0fc35d3a358bd54a9cf7c168ea74ed66cff34f..1555fc1b5041e2f0b6606cb424cdba3a7af57981 100644 (file)
@@ -51,7 +51,8 @@
 #define PARTS_DEFAULT \
        /* Linux partitions */ \
        "uuid_disk=${uuid_gpt_disk};" \
-       "name=rootfs,start=2MiB,size=-,uuid=${uuid_gpt_rootfs}\0" \
+       "name=bootloader,start=384K,size=1792K,uuid=${uuid_gpt_bootloader};" \
+       "name=rootfs,start=2688K,size=-,uuid=${uuid_gpt_rootfs}\0" \
        /* Android partitions */ \
        "partitions_android=" \
        "uuid_disk=${uuid_gpt_disk};" \
index 015f25a774006dd290d8db0542b9f3ecffafbf5d..66ead6c117230aacede8099e0ee634a0bee9bd1d 100644 (file)
 #include <configs/rk3399_common.h>
 
 #define CONFIG_SYS_MMC_ENV_DEV 1
-/*
- * SPL @ 32k for ~36k
- * ENV @ 96k
- * u-boot @ 128K
- */
-#define CONFIG_ENV_OFFSET (96 * 1024)
 
 #define SDRAM_BANK_SIZE                        (2UL << 30)
 
index 195074040573009a47c06728c0a91d5b860178f6..df81c09d8636e95e10e8324d5c972b01b972ca9e 100644 (file)
@@ -38,7 +38,7 @@
                         "setenv name_fdt keystone-k2g-ice.dtb; " \
                "else if test $name_fdt = undefined; then " \
                        "echo WARNING: Could not determine device tree to use;"\
-               "fi;fi;fi;\0" \
+               "fi;fi;fi; setenv fdtfile ${name_fdt}\0" \
        "name_mon=skern-k2g.bin\0"                                      \
        "name_ubi=k2g-evm-ubifs.ubi\0"                                  \
        "name_uboot=u-boot-spi-k2g-evm.gph\0"                           \
index e9e3c4013c3c9637e7dbc0de2fd7f480bbb89a1d..34f255847a8c940c793a291c1da72e69795f9804 100644 (file)
 #define CONFIG_SYS_INIT_SP_ADDR                0x00100000
 #define CONFIG_SYS_LOAD_ADDR           0x00800800
 #define CONFIG_SPL_STACK               0xff718000
-#define CONFIG_SPL_TEXT_BASE           0xff704004
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_TPL_BOOTROM_SUPPORT)
+# define CONFIG_SPL_TEXT_BASE          0x0
+#else
+# define CONFIG_SPL_TEXT_BASE          0xff704004
+#endif
 
 /* MMC/SD IP block */
 #define CONFIG_BOUNCE_BUFFER
index 2b2b85d085b4d4f3b7520e410c7e6b429202ec13..53046a2110ed6fc68503efc286a354ddabebd5f8 100644 (file)
                                        "${bootdir}/${fit_bootfile}\0"  \
        "get_uboot_net=dhcp ${loadaddr} ${tftp_root}/${name_uboot}\0"   \
        "get_uboot_nfs=nfs ${loadaddr} ${nfs_root}/boot/${name_uboot}\0" \
-       "burn_uboot_spi=sf probe; sf erase 0 0x80000; "         \
+       "burn_uboot_spi=sf probe; sf erase 0 0x90000; "         \
                "sf write ${loadaddr} 0 ${filesize}\0"          \
        "burn_uboot_nand=nand erase 0 0x100000; "                       \
                "nand write ${loadaddr} 0 ${filesize}\0"                \
index 9d6c80f5499468cf12f4bcd25b6bb7bc3c0a3775..8774e4243042ee1a2dfc18bb9dd3269645193435 100644 (file)
 #define CONFIG_SYS_MMC_ENV_DEV 1
 #undef CONFIG_CMD_USB_MASS_STORAGE
 
+#ifndef CONFIG_TPL_BUILD
+
+#define CONFIG_SPL_OS_BOOT
+
+/* Falcon Mode */
+#define CONFIG_SPL_FS_LOAD_ARGS_NAME   "args"
+#define CONFIG_SPL_FS_LOAD_KERNEL_NAME "uImage"
+#define CONFIG_CMD_SPL
+#define CONFIG_SYS_SPL_ARGS_ADDR       0x0ffe5000
+#define CONFIG_CMD_SPL_WRITE_SIZE      (128 * SZ_1K)
+
+/* Falcon Mode - MMC support: args@1MB kernel@2MB */
+#define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR  0x800   /* 1MB */
+#define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS (CONFIG_CMD_SPL_WRITE_SIZE / 512)
+#define CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR        0x1000  /* 2MB */
+#endif
+
 #endif
index d2ad3bb52dcf4c1d8ec749b7ae2f4446a7b5a0fb..7defc6b282c46adf11f9e8ab58fc939aa30a3062 100644 (file)
@@ -39,6 +39,7 @@
 #define SCLK_MAC_TX                    88
 #define SCLK_MACREF                    89
 #define SCLK_MACREF_OUT                        90
+#define SCLK_SARADC                    91
 
 
 /* aclk gates */
@@ -67,6 +68,7 @@
 #define PCLK_TIMER                     270
 #define PCLK_PERI                      271
 #define PCLK_GMAC                      272
+#define PCLK_SARADC                    273
 
 /* hclk gates */
 #define HCLK_I2S0_8CH                  320
index 02b78b31b129928446ff1f71297b5d2b8e7e2eb3..dc8edc8743aca2f1b30f967c268c63ee616dbaa2 100644 (file)
 
 struct efi_device_path;
 
+typedef struct {
+       u8 b[16];
+} efi_guid_t;
+
 #define EFI_BITS_PER_LONG      BITS_PER_LONG
 
 /*
@@ -77,6 +81,8 @@ struct efi_device_path;
 #define EFI_IP_ADDRESS_CONFLICT                (EFI_ERROR_MASK | 34)
 #define EFI_HTTP_ERROR                 (EFI_ERROR_MASK | 35)
 
+#define EFI_WARN_DELETE_FAILURE        2
+
 typedef unsigned long efi_status_t;
 typedef u64 efi_physical_addr_t;
 typedef u64 efi_virtual_addr_t;
@@ -116,7 +122,7 @@ enum efi_mem_type {
        /* The code portions of a loaded Boot Services Driver */
        EFI_BOOT_SERVICES_CODE,
        /*
-        * The data portions of a loaded Boot Serves Driver and
+        * The data portions of a loaded Boot Services Driver and
         * the default data allocation type used by a Boot Services
         * Driver to allocate pool memory.
         */
@@ -318,6 +324,25 @@ extern char image_base[];
 /* Start and end of U-Boot image (for payload) */
 extern char _binary_u_boot_bin_start[], _binary_u_boot_bin_end[];
 
+/*
+ * Variable Attributes
+ */
+#define EFI_VARIABLE_NON_VOLATILE       0x0000000000000001
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
+#define EFI_VARIABLE_RUNTIME_ACCESS     0x0000000000000004
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020
+#define EFI_VARIABLE_APPEND_WRITE      0x0000000000000040
+
+#define EFI_VARIABLE_MASK      (EFI_VARIABLE_NON_VOLATILE | \
+                               EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+                               EFI_VARIABLE_RUNTIME_ACCESS | \
+                               EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
+                               EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
+                               EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
+                               EFI_VARIABLE_APPEND_WRITE)
+
 /**
  * efi_get_sys_table() - Get access to the main EFI system table
  *
index ec1b321e8e70bc1158fe6503bfaf9f0afc94bcb0..c3b9032a48d2919d6c0cf5a673bc9319f6a5ce1f 100644 (file)
@@ -29,6 +29,8 @@ enum efi_timer_delay {
 };
 
 #define UINTN size_t
+typedef long INTN;
+typedef uint16_t *efi_string_t;
 
 #define EVT_TIMER                              0x80000000
 #define EVT_RUNTIME                            0x40000000
@@ -211,6 +213,10 @@ struct efi_runtime_services {
        EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
 
+#define EFI_GLOBAL_VARIABLE_GUID \
+       EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, \
+                0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c)
+
 #define LOADED_IMAGE_PROTOCOL_GUID \
        EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, \
                 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
@@ -284,28 +290,93 @@ struct efi_device_path {
        u8 type;
        u8 sub_type;
        u16 length;
-};
+} __packed;
 
 struct efi_mac_addr {
        u8 addr[32];
-};
+} __packed;
+
+#define DEVICE_PATH_TYPE_HARDWARE_DEVICE       0x01
+#  define DEVICE_PATH_SUB_TYPE_VENDOR          0x04
+
+struct efi_device_path_vendor {
+       struct efi_device_path dp;
+       efi_guid_t guid;
+       u8 vendor_data[];
+} __packed;
+
+#define DEVICE_PATH_TYPE_ACPI_DEVICE           0x02
+#  define DEVICE_PATH_SUB_TYPE_ACPI_DEVICE     0x01
+
+#define EFI_PNP_ID(ID)                         (u32)(((ID) << 16) | 0x41D0)
+#define EISA_PNP_ID(ID)                                EFI_PNP_ID(ID)
+#define EISA_PNP_NUM(ID)                       ((ID) >> 16)
+
+struct efi_device_path_acpi_path {
+       struct efi_device_path dp;
+       u32 hid;
+       u32 uid;
+} __packed;
 
 #define DEVICE_PATH_TYPE_MESSAGING_DEVICE      0x03
+#  define DEVICE_PATH_SUB_TYPE_MSG_USB         0x05
 #  define DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR    0x0b
+#  define DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS   0x0f
+#  define DEVICE_PATH_SUB_TYPE_MSG_SD          0x1a
+#  define DEVICE_PATH_SUB_TYPE_MSG_MMC         0x1d
+
+struct efi_device_path_usb {
+       struct efi_device_path dp;
+       u8 parent_port_number;
+       u8 usb_interface;
+} __packed;
 
 struct efi_device_path_mac_addr {
        struct efi_device_path dp;
        struct efi_mac_addr mac;
        u8 if_type;
-};
+} __packed;
+
+struct efi_device_path_usb_class {
+       struct efi_device_path dp;
+       u16 vendor_id;
+       u16 product_id;
+       u8 device_class;
+       u8 device_subclass;
+       u8 device_protocol;
+} __packed;
+
+struct efi_device_path_sd_mmc_path {
+       struct efi_device_path dp;
+       u8 slot_number;
+} __packed;
 
 #define DEVICE_PATH_TYPE_MEDIA_DEVICE          0x04
+#  define DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH 0x01
+#  define DEVICE_PATH_SUB_TYPE_CDROM_PATH      0x02
 #  define DEVICE_PATH_SUB_TYPE_FILE_PATH       0x04
 
+struct efi_device_path_hard_drive_path {
+       struct efi_device_path dp;
+       u32 partition_number;
+       u64 partition_start;
+       u64 partition_end;
+       u8 partition_signature[16];
+       u8 partmap_type;
+       u8 signature_type;
+} __packed;
+
+struct efi_device_path_cdrom_path {
+       struct efi_device_path dp;
+       u32 boot_entry;
+       u64 partition_start;
+       u64 partition_end;
+} __packed;
+
 struct efi_device_path_file_path {
        struct efi_device_path dp;
-       u16 str[32];
-};
+       u16 str[];
+} __packed;
 
 #define BLOCK_IO_GUID \
        EFI_GUID(0x964e5b21, 0x6459, 0x11d2, \
@@ -358,10 +429,10 @@ struct efi_simple_text_output_protocol {
        void *reset;
        efi_status_t (EFIAPI *output_string)(
                        struct efi_simple_text_output_protocol *this,
-                       const unsigned short *str);
+                       const efi_string_t str);
        efi_status_t (EFIAPI *test_string)(
                        struct efi_simple_text_output_protocol *this,
-                       const unsigned short *str);
+                       const efi_string_t str);
        efi_status_t(EFIAPI *query_mode)(
                        struct efi_simple_text_output_protocol *this,
                        unsigned long mode_number, unsigned long *columns,
@@ -423,22 +494,14 @@ struct efi_console_control_protocol
        EFI_GUID(0x8b843e20, 0x8132, 0x4852, \
                 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c)
 
-struct efi_device_path_protocol
-{
-       uint8_t type;
-       uint8_t sub_type;
-       uint16_t length;
-       uint8_t data[];
-};
-
 struct efi_device_path_to_text_protocol
 {
        uint16_t *(EFIAPI *convert_device_node_to_text)(
-                       struct efi_device_path_protocol *device_node,
+                       struct efi_device_path *device_node,
                        bool display_only,
                        bool allow_shortcuts);
        uint16_t *(EFIAPI *convert_device_path_to_text)(
-                       struct efi_device_path_protocol *device_path,
+                       struct efi_device_path *device_path,
                        bool display_only,
                        bool allow_shortcuts);
 };
@@ -609,4 +672,69 @@ struct efi_pxe {
        struct efi_pxe_mode *mode;
 };
 
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
+       EFI_GUID(0x964e5b22, 0x6459, 0x11d2, \
+                0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_FILE_PROTOCOL_REVISION 0x00010000
+
+struct efi_file_handle {
+       u64 rev;
+       efi_status_t (EFIAPI *open)(struct efi_file_handle *file,
+                       struct efi_file_handle **new_handle,
+                       s16 *file_name, u64 open_mode, u64 attributes);
+       efi_status_t (EFIAPI *close)(struct efi_file_handle *file);
+       efi_status_t (EFIAPI *delete)(struct efi_file_handle *file);
+       efi_status_t (EFIAPI *read)(struct efi_file_handle *file,
+                       u64 *buffer_size, void *buffer);
+       efi_status_t (EFIAPI *write)(struct efi_file_handle *file,
+                       u64 *buffer_size, void *buffer);
+       efi_status_t (EFIAPI *getpos)(struct efi_file_handle *file,
+                       u64 *pos);
+       efi_status_t (EFIAPI *setpos)(struct efi_file_handle *file,
+                       u64 pos);
+       efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *file,
+                       efi_guid_t *info_type, u64 *buffer_size, void *buffer);
+       efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *file,
+                       efi_guid_t *info_type, u64 buffer_size, void *buffer);
+       efi_status_t (EFIAPI *flush)(struct efi_file_handle *file);
+};
+
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
+       EFI_GUID(0x964e5b22, 0x6459, 0x11d2, \
+                0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000
+
+struct efi_simple_file_system_protocol {
+       u64 rev;
+       efi_status_t (EFIAPI *open_volume)(struct efi_simple_file_system_protocol *this,
+                       struct efi_file_handle **root);
+};
+
+#define EFI_FILE_INFO_GUID \
+       EFI_GUID(0x9576e92, 0x6d3f, 0x11d2, \
+                0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_FILE_MODE_READ     0x0000000000000001
+#define EFI_FILE_MODE_WRITE    0x0000000000000002
+#define EFI_FILE_MODE_CREATE   0x8000000000000000
+
+#define EFI_FILE_READ_ONLY     0x0000000000000001
+#define EFI_FILE_HIDDEN                0x0000000000000002
+#define EFI_FILE_SYSTEM                0x0000000000000004
+#define EFI_FILE_RESERVED      0x0000000000000008
+#define EFI_FILE_DIRECTORY     0x0000000000000010
+#define EFI_FILE_ARCHIVE       0x0000000000000020
+#define EFI_FILE_VALID_ATTR    0x0000000000000037
+
+struct efi_file_info {
+       u64 size;
+       u64 file_size;
+       u64 physical_size;
+       struct efi_time create_time;
+       struct efi_time last_access_time;
+       struct efi_time modification_time;
+       u64 attribute;
+       s16 file_name[0];
+};
+
 #endif
index 1179234f6836b6e7aaa942cbed3e1a701aee2737..2f081f899658ceca83fa8f0abbf96c5c87f43814 100644 (file)
@@ -17,6 +17,7 @@
 
 int __efi_entry_check(void);
 int __efi_exit_check(void);
+const char *__efi_nesting(void);
 const char *__efi_nesting_inc(void);
 const char *__efi_nesting_dec(void);
 
@@ -41,9 +42,22 @@ const char *__efi_nesting_dec(void);
        })
 
 /*
- * Callback into UEFI world from u-boot:
+ * Call non-void UEFI function from u-boot and retrieve return value:
  */
-#define EFI_CALL(exp) do { \
+#define EFI_CALL(exp) ({ \
+       debug("%sEFI: Call: %s\n", __efi_nesting_inc(), #exp); \
+       assert(__efi_exit_check()); \
+       typeof(exp) _r = exp; \
+       assert(__efi_entry_check()); \
+       debug("%sEFI: %lu returned by %s\n", __efi_nesting_dec(), \
+             (unsigned long)((uintptr_t)_r & ~EFI_ERROR_MASK), #exp); \
+       _r; \
+})
+
+/*
+ * Call void UEFI function from u-boot:
+ */
+#define EFI_CALL_VOID(exp) do { \
        debug("%sEFI: Call: %s\n", __efi_nesting_inc(), #exp); \
        assert(__efi_exit_check()); \
        exp; \
@@ -51,6 +65,13 @@ const char *__efi_nesting_dec(void);
        debug("%sEFI: Return From: %s\n", __efi_nesting_dec(), #exp); \
        } while(0)
 
+/*
+ * Write GUID
+ */
+#define EFI_PRINT_GUID(txt, guid) ({ \
+       debug("%sEFI: %s %pUl\n", __efi_nesting(), txt, guid); \
+       })
+
 extern struct efi_runtime_services efi_runtime_services;
 extern struct efi_system_table systab;
 
@@ -59,10 +80,15 @@ extern struct efi_simple_input_interface efi_con_in;
 extern const struct efi_console_control_protocol efi_console_control;
 extern const struct efi_device_path_to_text_protocol efi_device_path_to_text;
 
+uint16_t *efi_dp_str(struct efi_device_path *dp);
+
+extern const efi_guid_t efi_global_variable_guid;
 extern const efi_guid_t efi_guid_console_control;
 extern const efi_guid_t efi_guid_device_path;
 extern const efi_guid_t efi_guid_loaded_image;
 extern const efi_guid_t efi_guid_device_path_to_text_protocol;
+extern const efi_guid_t efi_simple_file_system_protocol_guid;
+extern const efi_guid_t efi_file_info_guid;
 
 extern unsigned int __efi_runtime_start, __efi_runtime_stop;
 extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
@@ -110,7 +136,8 @@ struct efi_object {
  * @nofify_function:   Function to call when the event is triggered
  * @notify_context:    Data to be passed to the notify function
  * @trigger_type:      Type of timer, see efi_set_timer
- * @signaled:          The notify function was already called
+ * @queued:            The notification functionis queued
+ * @signaled:          The event occured
  */
 struct efi_event {
        uint32_t type;
@@ -120,6 +147,7 @@ struct efi_event {
        u64 trigger_next;
        u64 trigger_time;
        enum efi_timer_delay trigger_type;
+       int queued;
        int signaled;
 };
 
@@ -134,10 +162,13 @@ int efi_disk_register(void);
 /* Called by bootefi to make GOP (graphical) interface available */
 int efi_gop_register(void);
 /* Called by bootefi to make the network interface available */
-int efi_net_register(void **handle);
+int efi_net_register(void);
 /* Called by bootefi to make SMBIOS tables available */
 void efi_smbios_register(void);
 
+struct efi_simple_file_system_protocol *
+efi_fs_from_path(struct efi_device_path *fp);
+
 /* Called by networking code to memorize the dhcp ack package */
 void efi_net_set_dhcp_ack(void *pkt, int len);
 
@@ -166,6 +197,14 @@ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type,
 /* Call this to signal an event */
 void efi_signal_event(struct efi_event *event);
 
+/* open file system: */
+struct efi_simple_file_system_protocol *efi_simple_file_system(
+               struct blk_desc *desc, int part, struct efi_device_path *dp);
+
+/* open file from device-path: */
+struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp);
+
+
 /* Generic EFI memory allocator, call this to get memory */
 void *efi_alloc(uint64_t len, int memory_type);
 /* More specific EFI memory allocator, called by EFI payloads */
@@ -191,12 +230,43 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
 int efi_memory_init(void);
 /* Adds new or overrides configuration table entry to the system table */
 efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table);
+void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj,
+                           struct efi_device_path *device_path,
+                           struct efi_device_path *file_path);
+efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
+                                     void **buffer);
 
 #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
 extern void *efi_bounce_buffer;
 #define EFI_LOADER_BOUNCE_BUFFER_SIZE (64 * 1024 * 1024)
 #endif
 
+
+struct efi_device_path *efi_dp_next(const struct efi_device_path *dp);
+int efi_dp_match(struct efi_device_path *a, struct efi_device_path *b);
+struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
+                                  struct efi_device_path **rem);
+unsigned efi_dp_size(const struct efi_device_path *dp);
+struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp);
+struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
+                                     const struct efi_device_path *dp2);
+struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
+                                          const struct efi_device_path *node);
+
+
+struct efi_device_path *efi_dp_from_dev(struct udevice *dev);
+struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part);
+struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
+                                        const char *path);
+struct efi_device_path *efi_dp_from_eth(void);
+void efi_dp_split_file_path(struct efi_device_path *full_path,
+                           struct efi_device_path **device_path,
+                           struct efi_device_path **file_path);
+
+#define EFI_DP_TYPE(_dp, _type, _subtype) \
+       (((_dp)->type == DEVICE_PATH_TYPE_##_type) && \
+        ((_dp)->sub_type == DEVICE_PATH_SUB_TYPE_##_subtype))
+
 /* Convert strings from normal C strings to uEFI strings */
 static inline void ascii2unicode(u16 *unicode, const char *ascii)
 {
@@ -233,6 +303,28 @@ efi_status_t __efi_runtime EFIAPI efi_get_time(
                        struct efi_time_cap *capabilities);
 void efi_get_time_init(void);
 
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
+/*
+ * Entry point for the tests of the EFI API.
+ * It is called by 'bootefi selftest'
+ */
+efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
+                                struct efi_system_table *systab);
+#endif
+
+efi_status_t EFIAPI efi_get_variable(s16 *variable_name,
+               efi_guid_t *vendor, u32 *attributes,
+               unsigned long *data_size, void *data);
+efi_status_t EFIAPI efi_get_next_variable(
+               unsigned long *variable_name_size,
+               s16 *variable_name, efi_guid_t *vendor);
+efi_status_t EFIAPI efi_set_variable(s16 *variable_name,
+               efi_guid_t *vendor, u32 attributes,
+               unsigned long data_size, void *data);
+
+void *efi_bootmgr_load(struct efi_device_path **device_path,
+                      struct efi_device_path **file_path);
+
 #else /* defined(EFI_LOADER) && !defined(CONFIG_SPL_BUILD) */
 
 /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
diff --git a/include/efi_selftest.h b/include/efi_selftest.h
new file mode 100644 (file)
index 0000000..76304a2
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *  EFI application loader
+ *
+ *  Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _EFI_SELFTEST_H
+#define _EFI_SELFTEST_H
+
+#include <common.h>
+#include <efi.h>
+#include <efi_api.h>
+#include <linker_lists.h>
+
+/*
+ * Prints an error message.
+ *
+ * @...        format string followed by fields to print
+ */
+#define efi_st_error(...) \
+       efi_st_printf("%s(%u):\nERROR: ", __FILE__, __LINE__); \
+       efi_st_printf(__VA_ARGS__) \
+
+/*
+ * A test may be setup and executed at boottime,
+ * it may be setup at boottime and executed at runtime,
+ * or it may be setup and executed at runtime.
+ */
+enum efi_test_phase {
+       EFI_EXECUTE_BEFORE_BOOTTIME_EXIT = 1,
+       EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+       EFI_SETUP_AFTER_BOOTTIME_EXIT,
+};
+
+extern struct efi_simple_text_output_protocol *con_out;
+extern struct efi_simple_input_interface *con_in;
+
+/*
+ * Exit the boot services.
+ *
+ * The size of the memory map is determined.
+ * Pool memory is allocated to copy the memory map.
+ * The memory amp is copied and the map key is obtained.
+ * The map key is used to exit the boot services.
+ */
+void efi_st_exit_boot_services(void);
+
+/*
+ * Print a pointer to an u16 string
+ *
+ * @pointer: pointer
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+void efi_st_printf(const char *fmt, ...)
+                __attribute__ ((format (__printf__, 1, 2)));
+
+/*
+ * Reads an Unicode character from the input device.
+ *
+ * @return: Unicode character
+ */
+u16 efi_st_get_key(void);
+
+/**
+ * struct efi_unit_test - EFI unit test
+ *
+ * An efi_unit_test provides a interface to an EFI unit test.
+ *
+ * @name:      name of unit test
+ * @phase:     specifies when setup and execute are executed
+ * @setup:     set up the unit test
+ * @teardown:  tear down the unit test
+ * @execute:   execute the unit test
+ */
+struct efi_unit_test {
+       const char *name;
+       const enum efi_test_phase phase;
+       int (*setup)(const efi_handle_t handle,
+                    const struct efi_system_table *systable);
+       int (*execute)(void);
+       int (*teardown)(void);
+};
+
+/* Declare a new EFI unit test */
+#define EFI_UNIT_TEST(__name)                                          \
+       ll_entry_declare(struct efi_unit_test, __name, efi_unit_test)
+
+#endif /* _EFI_SELFTEST_H */
index 5b1b97bafef2433dfd58e6cddf891f46e40f1946..799d9840aa2ebf0c8d2dc6d6150fae0356cac595 100644 (file)
        "partitions=" PARTS_DEFAULT "\0" \
        "optargs=\0" \
        "dofastboot=0\0" \
+       "emmc_linux_boot=" \
+               "echo Trying to boot Linux from eMMC ...; " \
+               "setenv mmcdev 1; " \
+               "setenv bootpart 1:2; " \
+               "setenv mmcroot /dev/mmcblk0p2 rw; " \
+               "run mmcboot;\0" \
        "emmc_android_boot=" \
+               "echo Trying to boot Android from eMMC ...; " \
                "setenv eval_bootargs setenv bootargs $bootargs; " \
                "run eval_bootargs; " \
                "setenv mmcdev 1; " \
@@ -44,7 +51,6 @@
                "part size mmc ${mmcdev} ${boot_part} boot_size; " \
                "mmc read ${fdtaddr} ${fdt_start} ${fdt_size}; " \
                "mmc read ${loadaddr} ${boot_start} ${boot_size}; " \
-               "echo Booting from eMMC ...; " \
                "bootm $loadaddr $loadaddr $fdtaddr;\0"
 
 #ifdef CONFIG_OMAP54XX
        "run findfdt; " \
        "run envboot; " \
        "run mmcboot;" \
-       "setenv mmcdev 1; " \
-       "setenv bootpart 1:2; " \
-       "setenv mmcroot /dev/mmcblk0p2 rw; " \
-       "run mmcboot;" \
+       "run emmc_linux_boot; " \
        "run emmc_android_boot; " \
        ""
 
index 86117a7ce5d3c57e80c1ec9dc8293718b5c78c32..b2e820ef8ada0549db9b19014799a5105039fd42 100644 (file)
@@ -280,8 +280,9 @@ struct part_driver {
 #define U_BOOT_PART_TYPE(__name)                                       \
        ll_entry_declare(struct part_driver, __name, part_driver)
 
-#if CONFIG_IS_ENABLED(EFI_PARTITION)
 #include <part_efi.h>
+
+#if CONFIG_IS_ENABLED(EFI_PARTITION)
 /* disk/part_efi.c */
 /**
  * write_gpt_table() - Write the GUID Partition Table to disk
index 317c044795caf68081aee879dc20c40835091256..31e6bc6e140fe2956b15da1012b74be71bf422c0 100644 (file)
 /* linux/include/efi.h */
 typedef u16 efi_char16_t;
 
-typedef struct {
-       u8 b[16];
-} efi_guid_t;
-
 /* based on linux/include/genhd.h */
 struct partition {
        u8 boot_ind;            /* 0x80 - active */
index deb35a0ea452e43ce99c7ba31cae621c5f271a5f..4ef3e92efafcbc29d7c1453c5a41bc7ecd47fe48 100644 (file)
@@ -62,6 +62,12 @@ typedef struct _IMAGE_DATA_DIRECTORY {
 
 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
 
+/* PE32+ Subsystem type for EFI images */
+#define IMAGE_SUBSYSTEM_EFI_APPLICATION         10
+#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER      12
+#define IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER      13
+
 typedef struct _IMAGE_OPTIONAL_HEADER64 {
        uint16_t Magic; /* 0x20b */
        uint8_t  MajorLinkerVersion;
index faf4538fb5fe200146809a8ae6afd0affe97a397..8e1c9d1bb70a787d70941e02547e66cb77712429 100644 (file)
@@ -9,6 +9,7 @@ ifndef CONFIG_SPL_BUILD
 
 obj-$(CONFIG_EFI) += efi/
 obj-$(CONFIG_EFI_LOADER) += efi_loader/
+obj-$(CONFIG_EFI_LOADER) += efi_selftest/
 obj-$(CONFIG_LZMA) += lzma/
 obj-$(CONFIG_LZO) += lzo/
 obj-$(CONFIG_BZIP2) += bzip2/
index 30bf343a36522d24bbb5e655b6451cae2eeccd70..ddb978f650fffb308084cc56225594a0e3d2d5d3 100644 (file)
 CFLAGS_helloworld.o := $(CFLAGS_EFI)
 CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI)
 
-efiprogs-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += helloworld.efi
-always := $(efiprogs-y)
+ifneq ($(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),)
+always += helloworld.efi
+endif
 
 obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
 obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o
-obj-y += efi_memory.o efi_device_path_to_text.o
+obj-y += efi_memory.o efi_device_path_to_text.o efi_device_path.o
+obj-y += efi_file.o efi_variable.o efi_bootmgr.o
 obj-$(CONFIG_LCD) += efi_gop.o
 obj-$(CONFIG_DM_VIDEO) += efi_gop.o
 obj-$(CONFIG_PARTITIONS) += efi_disk.o
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
new file mode 100644 (file)
index 0000000..857d88a
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ *  EFI utils
+ *
+ *  Copyright (c) 2017 Rob Clark
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <malloc.h>
+#include <efi_loader.h>
+
+static const struct efi_boot_services *bs;
+static const struct efi_runtime_services *rs;
+
+#define LOAD_OPTION_ACTIVE             0x00000001
+#define LOAD_OPTION_FORCE_RECONNECT    0x00000002
+#define LOAD_OPTION_HIDDEN             0x00000008
+
+/*
+ * bootmgr implements the logic of trying to find a payload to boot
+ * based on the BootOrder + BootXXXX variables, and then loading it.
+ *
+ * TODO detecting a special key held (f9?) and displaying a boot menu
+ * like you would get on a PC would be clever.
+ *
+ * TODO if we had a way to write and persist variables after the OS
+ * has started, we'd also want to check OsIndications to see if we
+ * should do normal or recovery boot.
+ */
+
+
+/*
+ * See section 3.1.3 in the v2.7 UEFI spec for more details on
+ * the layout of EFI_LOAD_OPTION.  In short it is:
+ *
+ *    typedef struct _EFI_LOAD_OPTION {
+ *        UINT32 Attributes;
+ *        UINT16 FilePathListLength;
+ *        // CHAR16 Description[];   <-- variable length, NULL terminated
+ *        // EFI_DEVICE_PATH_PROTOCOL FilePathList[];  <-- FilePathListLength bytes
+ *        // UINT8 OptionalData[];
+ *    } EFI_LOAD_OPTION;
+ */
+struct load_option {
+       u32 attributes;
+       u16 file_path_length;
+       u16 *label;
+       struct efi_device_path *file_path;
+       u8 *optional_data;
+};
+
+/* parse an EFI_LOAD_OPTION, as described above */
+static void parse_load_option(struct load_option *lo, void *ptr)
+{
+       lo->attributes = *(u32 *)ptr;
+       ptr += sizeof(u32);
+
+       lo->file_path_length = *(u16 *)ptr;
+       ptr += sizeof(u16);
+
+       lo->label = ptr;
+       ptr += (utf16_strlen(lo->label) + 1) * 2;
+
+       lo->file_path = ptr;
+       ptr += lo->file_path_length;
+
+       lo->optional_data = ptr;
+}
+
+/* free() the result */
+static void *get_var(u16 *name, const efi_guid_t *vendor,
+                    unsigned long *size)
+{
+       efi_guid_t *v = (efi_guid_t *)vendor;
+       efi_status_t ret;
+       void *buf = NULL;
+
+       *size = 0;
+       EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf));
+       if (ret == EFI_BUFFER_TOO_SMALL) {
+               buf = malloc(*size);
+               EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf));
+       }
+
+       if (ret != EFI_SUCCESS) {
+               free(buf);
+               *size = 0;
+               return NULL;
+       }
+
+       return buf;
+}
+
+/*
+ * Attempt to load load-option number 'n', returning device_path and file_path
+ * if successful.  This checks that the EFI_LOAD_OPTION is active (enabled)
+ * and that the specified file to boot exists.
+ */
+static void *try_load_entry(uint16_t n, struct efi_device_path **device_path,
+                           struct efi_device_path **file_path)
+{
+       struct load_option lo;
+       u16 varname[] = L"Boot0000";
+       u16 hexmap[] = L"0123456789ABCDEF";
+       void *load_option, *image = NULL;
+       unsigned long size;
+
+       varname[4] = hexmap[(n & 0xf000) >> 12];
+       varname[5] = hexmap[(n & 0x0f00) >> 8];
+       varname[6] = hexmap[(n & 0x00f0) >> 4];
+       varname[7] = hexmap[(n & 0x000f) >> 0];
+
+       load_option = get_var(varname, &efi_global_variable_guid, &size);
+       if (!load_option)
+               return NULL;
+
+       parse_load_option(&lo, load_option);
+
+       if (lo.attributes & LOAD_OPTION_ACTIVE) {
+               efi_status_t ret;
+               u16 *str = NULL;
+
+               debug("%s: trying to load \"%ls\" from: %ls\n", __func__,
+                     lo.label, (str = efi_dp_str(lo.file_path)));
+               efi_free_pool(str);
+
+               ret = efi_load_image_from_path(lo.file_path, &image);
+
+               if (ret != EFI_SUCCESS)
+                       goto error;
+
+               printf("Booting: %ls\n", lo.label);
+               efi_dp_split_file_path(lo.file_path, device_path, file_path);
+       }
+
+error:
+       free(load_option);
+
+       return image;
+}
+
+/*
+ * Attempt to load, in the order specified by BootOrder EFI variable, the
+ * available load-options, finding and returning the first one that can
+ * be loaded successfully.
+ */
+void *efi_bootmgr_load(struct efi_device_path **device_path,
+                      struct efi_device_path **file_path)
+{
+       uint16_t *bootorder;
+       unsigned long size;
+       void *image = NULL;
+       int i, num;
+
+       __efi_entry_check();
+
+       bs = systab.boottime;
+       rs = systab.runtime;
+
+       bootorder = get_var(L"BootOrder", &efi_global_variable_guid, &size);
+       if (!bootorder)
+               goto error;
+
+       num = size / sizeof(uint16_t);
+       for (i = 0; i < num; i++) {
+               debug("%s: trying to load Boot%04X\n", __func__, bootorder[i]);
+               image = try_load_entry(bootorder[i], device_path, file_path);
+               if (image)
+                       break;
+       }
+
+       free(bootorder);
+
+error:
+       __efi_exit_check();
+
+       return image;
+}
index 43f32385fae01fbdbbcfdbae2e9c4d78e7918477..9e741c3cf3c73b008ce9e4186c6bf448bf803f8a 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <efi_loader.h>
+#include <environment.h>
 #include <malloc.h>
 #include <asm/global_data.h>
 #include <libfdt_env.h>
@@ -18,6 +19,9 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* Task priority level */
+static UINTN efi_tpl = TPL_APPLICATION;
+
 /* This list contains all the EFI objects our payload has access to */
 LIST_HEAD(efi_obj_list);
 
@@ -109,6 +113,11 @@ static const char *indent_string(int level)
        return &indent[max - level];
 }
 
+const char *__efi_nesting(void)
+{
+       return indent_string(nesting_level);
+}
+
 const char *__efi_nesting_inc(void)
 {
        return indent_string(nesting_level++);
@@ -154,12 +163,15 @@ static u64 efi_div10(u64 a)
 
 void efi_signal_event(struct efi_event *event)
 {
-       if (event->signaled)
-               return;
-       event->signaled = 1;
-       if (event->type & EVT_NOTIFY_SIGNAL) {
-               EFI_CALL(event->notify_function(event, event->notify_context));
+       if (event->notify_function) {
+               event->queued = 1;
+               /* Check TPL */
+               if (efi_tpl >= event->notify_tpl)
+                       return;
+               EFI_CALL_VOID(event->notify_function(event,
+                                                    event->notify_context));
        }
+       event->queued = 0;
 }
 
 static efi_status_t efi_unsupported(const char *funcname)
@@ -170,14 +182,31 @@ static efi_status_t efi_unsupported(const char *funcname)
 
 static unsigned long EFIAPI efi_raise_tpl(UINTN new_tpl)
 {
+       UINTN old_tpl = efi_tpl;
+
        EFI_ENTRY("0x%zx", new_tpl);
-       return EFI_EXIT(0);
+
+       if (new_tpl < efi_tpl)
+               debug("WARNING: new_tpl < current_tpl in %s\n", __func__);
+       efi_tpl = new_tpl;
+       if (efi_tpl > TPL_HIGH_LEVEL)
+               efi_tpl = TPL_HIGH_LEVEL;
+
+       EFI_EXIT(EFI_SUCCESS);
+       return old_tpl;
 }
 
 static void EFIAPI efi_restore_tpl(UINTN old_tpl)
 {
        EFI_ENTRY("0x%zx", old_tpl);
-       efi_unsupported(__func__);
+
+       if (old_tpl > efi_tpl)
+               debug("WARNING: old_tpl > current_tpl in %s\n", __func__);
+       efi_tpl = old_tpl;
+       if (efi_tpl > TPL_HIGH_LEVEL)
+               efi_tpl = TPL_HIGH_LEVEL;
+
+       EFI_EXIT(EFI_SUCCESS);
 }
 
 static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type,
@@ -270,6 +299,7 @@ efi_status_t efi_create_event(uint32_t type, UINTN notify_tpl,
                efi_events[i].notify_context = notify_context;
                /* Disable timers on bootup */
                efi_events[i].trigger_next = -1ULL;
+               efi_events[i].queued = 0;
                efi_events[i].signaled = 0;
                *event = &efi_events[i];
                return EFI_SUCCESS;
@@ -301,16 +331,25 @@ void efi_timer_check(void)
        u64 now = timer_get_us();
 
        for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
-               if (!efi_events[i].type ||
-                   !(efi_events[i].type & EVT_TIMER) ||
-                   efi_events[i].trigger_type == EFI_TIMER_STOP ||
+               if (!efi_events[i].type)
+                       continue;
+               if (efi_events[i].queued)
+                       efi_signal_event(&efi_events[i]);
+               if (!(efi_events[i].type & EVT_TIMER) ||
                    now < efi_events[i].trigger_next)
                        continue;
-               if (efi_events[i].trigger_type == EFI_TIMER_PERIODIC) {
+               switch (efi_events[i].trigger_type) {
+               case EFI_TIMER_RELATIVE:
+                       efi_events[i].trigger_type = EFI_TIMER_STOP;
+                       break;
+               case EFI_TIMER_PERIODIC:
                        efi_events[i].trigger_next +=
                                efi_events[i].trigger_time;
-                       efi_events[i].signaled = 0;
+                       break;
+               default:
+                       continue;
                }
+               efi_events[i].signaled = 1;
                efi_signal_event(&efi_events[i]);
        }
        WATCHDOG_RESET();
@@ -347,6 +386,7 @@ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type,
                }
                event->trigger_type = type;
                event->trigger_time = trigger_time;
+               event->signaled = 0;
                return EFI_SUCCESS;
        }
        return EFI_INVALID_PARAMETER;
@@ -371,6 +411,9 @@ static efi_status_t EFIAPI efi_wait_for_event(unsigned long num_events,
        /* Check parameters */
        if (!num_events || !event)
                return EFI_EXIT(EFI_INVALID_PARAMETER);
+       /* Check TPL */
+       if (efi_tpl != TPL_APPLICATION)
+               return EFI_EXIT(EFI_UNSUPPORTED);
        for (i = 0; i < num_events; ++i) {
                for (j = 0; j < ARRAY_SIZE(efi_events); ++j) {
                        if (event[i] == &efi_events[j])
@@ -380,6 +423,8 @@ static efi_status_t EFIAPI efi_wait_for_event(unsigned long num_events,
 known_event:
                if (!event[i]->type || event[i]->type & EVT_NOTIFY_SIGNAL)
                        return EFI_EXIT(EFI_INVALID_PARAMETER);
+               if (!event[i]->signaled)
+                       efi_signal_event(event[i]);
        }
 
        /* Wait for signal */
@@ -412,7 +457,11 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event)
        for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
                if (event != &efi_events[i])
                        continue;
-               efi_signal_event(event);
+               if (event->signaled)
+                       break;
+               event->signaled = 1;
+               if (event->type & EVT_NOTIFY_SIGNAL)
+                       efi_signal_event(event);
                break;
        }
        return EFI_EXIT(EFI_SUCCESS);
@@ -427,6 +476,7 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
                if (event == &efi_events[i]) {
                        event->type = 0;
                        event->trigger_next = -1ULL;
+                       event->queued = 0;
                        event->signaled = 0;
                        return EFI_EXIT(EFI_SUCCESS);
                }
@@ -445,6 +495,8 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event)
                        continue;
                if (!event->type || event->type & EVT_NOTIFY_SIGNAL)
                        break;
+               if (!event->signaled)
+                       efi_signal_event(event);
                if (event->signaled)
                        return EFI_EXIT(EFI_SUCCESS);
                return EFI_EXIT(EFI_NOT_READY);
@@ -513,7 +565,7 @@ static efi_status_t EFIAPI efi_install_protocol_interface_ext(void **handle,
                        efi_guid_t *protocol, int protocol_interface_type,
                        void *protocol_interface)
 {
-       EFI_ENTRY("%p, %p, %d, %p", handle, protocol, protocol_interface_type,
+       EFI_ENTRY("%p, %pUl, %d, %p", handle, protocol, protocol_interface_type,
                  protocol_interface);
 
        return EFI_EXIT(efi_install_protocol_interface(handle, protocol,
@@ -525,7 +577,7 @@ static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle,
                        efi_guid_t *protocol, void *old_interface,
                        void *new_interface)
 {
-       EFI_ENTRY("%p, %p, %p, %p", handle, protocol, old_interface,
+       EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface,
                  new_interface);
        return EFI_EXIT(EFI_ACCESS_DENIED);
 }
@@ -574,7 +626,7 @@ out:
 static efi_status_t EFIAPI efi_uninstall_protocol_interface_ext(void *handle,
                        efi_guid_t *protocol, void *protocol_interface)
 {
-       EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface);
+       EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface);
 
        return EFI_EXIT(efi_uninstall_protocol_interface(handle, protocol,
                                                         protocol_interface));
@@ -584,7 +636,7 @@ static efi_status_t EFIAPI efi_register_protocol_notify(efi_guid_t *protocol,
                                                        struct efi_event *event,
                                                        void **registration)
 {
-       EFI_ENTRY("%p, %p, %p", protocol, event, registration);
+       EFI_ENTRY("%pUl, %p, %p", protocol, event, registration);
        return EFI_EXIT(EFI_OUT_OF_RESOURCES);
 }
 
@@ -654,7 +706,7 @@ static efi_status_t EFIAPI efi_locate_handle_ext(
                        efi_guid_t *protocol, void *search_key,
                        unsigned long *buffer_size, efi_handle_t *buffer)
 {
-       EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
+       EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key,
                  buffer_size, buffer);
 
        return EFI_EXIT(efi_locate_handle(search_type, protocol, search_key,
@@ -665,8 +717,17 @@ static efi_status_t EFIAPI efi_locate_device_path(efi_guid_t *protocol,
                        struct efi_device_path **device_path,
                        efi_handle_t *device)
 {
-       EFI_ENTRY("%p, %p, %p", protocol, device_path, device);
-       return EFI_EXIT(EFI_NOT_FOUND);
+       struct efi_object *efiobj;
+
+       EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device);
+
+       efiobj = efi_dp_find_obj(*device_path, device_path);
+       if (!efiobj)
+               return EFI_EXIT(EFI_NOT_FOUND);
+
+       *device = efiobj->handle;
+
+       return EFI_EXIT(EFI_SUCCESS);
 }
 
 /* Collapses configuration table entries, removing index i */
@@ -713,10 +774,87 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table
 static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
                                                               void *table)
 {
-       EFI_ENTRY("%p, %p", guid, table);
+       EFI_ENTRY("%pUl, %p", guid, table);
        return EFI_EXIT(efi_install_configuration_table(guid, table));
 }
 
+/* Initialize a loaded_image_info + loaded_image_info object with correct
+ * protocols, boot-device, etc.
+ */
+void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj,
+                           struct efi_device_path *device_path,
+                           struct efi_device_path *file_path)
+{
+       obj->handle = info;
+
+       /*
+        * When asking for the device path interface, return
+        * bootefi_device_path
+        */
+       obj->protocols[0].guid = &efi_guid_device_path;
+       obj->protocols[0].protocol_interface = device_path;
+
+       /*
+        * When asking for the loaded_image interface, just
+        * return handle which points to loaded_image_info
+        */
+       obj->protocols[1].guid = &efi_guid_loaded_image;
+       obj->protocols[1].protocol_interface = info;
+
+       obj->protocols[2].guid = &efi_guid_console_control;
+       obj->protocols[2].protocol_interface = (void *)&efi_console_control;
+
+       obj->protocols[3].guid = &efi_guid_device_path_to_text_protocol;
+       obj->protocols[3].protocol_interface =
+               (void *)&efi_device_path_to_text;
+
+       info->file_path = file_path;
+       info->device_handle = efi_dp_find_obj(device_path, NULL);
+
+       list_add_tail(&obj->link, &efi_obj_list);
+}
+
+efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
+                                     void **buffer)
+{
+       struct efi_file_info *info = NULL;
+       struct efi_file_handle *f;
+       static efi_status_t ret;
+       uint64_t bs;
+
+       f = efi_file_from_path(file_path);
+       if (!f)
+               return EFI_DEVICE_ERROR;
+
+       bs = 0;
+       EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
+                                 &bs, info));
+       if (ret == EFI_BUFFER_TOO_SMALL) {
+               info = malloc(bs);
+               EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
+                                         &bs, info));
+       }
+       if (ret != EFI_SUCCESS)
+               goto error;
+
+       ret = efi_allocate_pool(EFI_LOADER_DATA, info->file_size, buffer);
+       if (ret)
+               goto error;
+
+       EFI_CALL(ret = f->read(f, &info->file_size, *buffer));
+
+error:
+       free(info);
+       EFI_CALL(f->close(f));
+
+       if (ret != EFI_SUCCESS) {
+               efi_free_pool(*buffer);
+               *buffer = NULL;
+       }
+
+       return ret;
+}
+
 static efi_status_t EFIAPI efi_load_image(bool boot_policy,
                                          efi_handle_t parent_image,
                                          struct efi_device_path *file_path,
@@ -724,25 +862,40 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
                                          unsigned long source_size,
                                          efi_handle_t *image_handle)
 {
-       static struct efi_object loaded_image_info_obj = {
-               .protocols = {
-                       {
-                               .guid = &efi_guid_loaded_image,
-                       },
-               },
-       };
        struct efi_loaded_image *info;
        struct efi_object *obj;
 
        EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image,
                  file_path, source_buffer, source_size, image_handle);
-       info = malloc(sizeof(*info));
-       loaded_image_info_obj.protocols[0].protocol_interface = info;
-       obj = malloc(sizeof(loaded_image_info_obj));
-       memset(info, 0, sizeof(*info));
-       memcpy(obj, &loaded_image_info_obj, sizeof(loaded_image_info_obj));
-       obj->handle = info;
-       info->file_path = file_path;
+
+       info = calloc(1, sizeof(*info));
+       obj = calloc(1, sizeof(*obj));
+
+       if (!source_buffer) {
+               struct efi_device_path *dp, *fp;
+               efi_status_t ret;
+
+               ret = efi_load_image_from_path(file_path, &source_buffer);
+               if (ret != EFI_SUCCESS) {
+                       free(info);
+                       free(obj);
+                       return EFI_EXIT(ret);
+               }
+
+               /*
+                * split file_path which contains both the device and
+                * file parts:
+                */
+               efi_dp_split_file_path(file_path, &dp, &fp);
+
+               efi_setup_loaded_image(info, obj, dp, fp);
+       } else {
+               /* In this case, file_path is the "device" path, ie.
+                * something like a HARDWARE_DEVICE:MEMORY_MAPPED
+                */
+               efi_setup_loaded_image(info, obj, file_path, NULL);
+       }
+
        info->reserved = efi_load_pe(source_buffer, info);
        if (!info->reserved) {
                free(info);
@@ -751,7 +904,6 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
        }
 
        *image_handle = info;
-       list_add_tail(&obj->link, &efi_obj_list);
 
        return EFI_EXIT(EFI_SUCCESS);
 }
@@ -793,6 +945,15 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
        EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status,
                  exit_data_size, exit_data);
 
+       /* Make sure entry/exit counts for EFI world cross-overs match */
+       __efi_exit_check();
+
+       /*
+        * But longjmp out with the U-Boot gd, not the application's, as
+        * the other end is a setjmp call inside EFI context.
+        */
+       efi_restore_gd();
+
        loaded_image_info->exit_status = exit_status;
        longjmp(&loaded_image_info->exit_jmp, 1);
 
@@ -840,8 +1001,24 @@ static void efi_exit_caches(void)
 static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle,
                                                  unsigned long map_key)
 {
+       int i;
+
        EFI_ENTRY("%p, %ld", image_handle, map_key);
 
+       /* Notify that ExitBootServices is invoked. */
+       for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
+               if (efi_events[i].type != EVT_SIGNAL_EXIT_BOOT_SERVICES)
+                       continue;
+               efi_signal_event(&efi_events[i]);
+       }
+       /* Make sure that notification functions are not called anymore */
+       efi_tpl = TPL_HIGH_LEVEL;
+
+#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
+       /* save any EFI variables that have been written: */
+       env_save();
+#endif
+
        board_quiesce_devices();
 
        /* Fix up caches for EFI payloads if necessary */
@@ -906,7 +1083,7 @@ static efi_status_t EFIAPI efi_close_protocol(void *handle,
                                              void *agent_handle,
                                              void *controller_handle)
 {
-       EFI_ENTRY("%p, %p, %p, %p", handle, protocol, agent_handle,
+       EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
                  controller_handle);
        return EFI_EXIT(EFI_NOT_FOUND);
 }
@@ -916,7 +1093,7 @@ static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle,
                        struct efi_open_protocol_info_entry **entry_buffer,
                        unsigned long *entry_count)
 {
-       EFI_ENTRY("%p, %p, %p, %p", handle, protocol, entry_buffer,
+       EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, entry_buffer,
                  entry_count);
        return EFI_EXIT(EFI_NOT_FOUND);
 }
@@ -982,7 +1159,7 @@ static efi_status_t EFIAPI efi_locate_handle_buffer(
        efi_status_t r;
        unsigned long buffer_size = 0;
 
-       EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
+       EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key,
                  no_handles, buffer);
 
        if (!no_handles || !buffer) {
@@ -1014,11 +1191,13 @@ static efi_status_t EFIAPI efi_locate_protocol(efi_guid_t *protocol,
        struct list_head *lhandle;
        int i;
 
-       EFI_ENTRY("%p, %p, %p", protocol, registration, protocol_interface);
+       EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface);
 
        if (!protocol || !protocol_interface)
                return EFI_EXIT(EFI_INVALID_PARAMETER);
 
+       EFI_PRINT_GUID("protocol", protocol);
+
        list_for_each(lhandle, &efi_obj_list) {
                struct efi_object *efiobj;
 
@@ -1122,7 +1301,7 @@ static efi_status_t EFIAPI efi_open_protocol(
        int i;
        efi_status_t r = EFI_INVALID_PARAMETER;
 
-       EFI_ENTRY("%p, %p, %p, %p, %p, 0x%x", handle, protocol,
+       EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol,
                  protocol_interface, agent_handle, controller_handle,
                  attributes);
 
@@ -1132,6 +1311,8 @@ static efi_status_t EFIAPI efi_open_protocol(
                goto out;
        }
 
+       EFI_PRINT_GUID("protocol", protocol);
+
        switch (attributes) {
        case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
        case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
index 3fc82b87261cba504da576393fb589d769b6eaa1..fd5398d61d94ff40fa83884de8c3dea26a8944c2 100644 (file)
@@ -8,7 +8,10 @@
 
 #include <common.h>
 #include <charset.h>
+#include <dm/device.h>
 #include <efi_loader.h>
+#include <stdio_dev.h>
+#include <video_console.h>
 
 static bool console_size_queried;
 
@@ -137,34 +140,46 @@ static efi_status_t EFIAPI efi_cout_reset(
        return EFI_EXIT(EFI_UNSUPPORTED);
 }
 
-static void print_unicode_in_utf8(u16 c)
-{
-       char utf8[MAX_UTF8_PER_UTF16] = { 0 };
-       utf16_to_utf8((u8 *)utf8, &c, 1);
-       puts(utf8);
-}
-
 static efi_status_t EFIAPI efi_cout_output_string(
                        struct efi_simple_text_output_protocol *this,
-                       const unsigned short *string)
+                       const efi_string_t string)
 {
-       struct cout_mode *mode;
-       u16 ch;
+       struct simple_text_output_mode *con = &efi_con_mode;
+       struct cout_mode *mode = &efi_cout_modes[con->mode];
 
-       mode = &efi_cout_modes[efi_con_mode.mode];
        EFI_ENTRY("%p, %p", this, string);
-       for (;(ch = *string); string++) {
-               print_unicode_in_utf8(ch);
-               efi_con_mode.cursor_column++;
-               if (ch == '\n') {
-                       efi_con_mode.cursor_column = 1;
-                       efi_con_mode.cursor_row++;
-               } else if (efi_con_mode.cursor_column > mode->columns) {
-                       efi_con_mode.cursor_column = 1;
-                       efi_con_mode.cursor_row++;
+
+       unsigned int n16 = utf16_strlen(string);
+       char buf[MAX_UTF8_PER_UTF16 * n16 + 1];
+       char *p;
+
+       *utf16_to_utf8((u8 *)buf, string, n16) = '\0';
+
+       fputs(stdout, buf);
+
+       for (p = buf; *p; p++) {
+               switch (*p) {
+               case '\r':   /* carriage-return */
+                       con->cursor_column = 0;
+                       break;
+               case '\n':   /* newline */
+                       con->cursor_column = 0;
+                       con->cursor_row++;
+                       break;
+               case '\t':   /* tab, assume 8 char align */
+                       break;
+               case '\b':   /* backspace */
+                       con->cursor_column = max(0, con->cursor_column - 1);
+                       break;
+               default:
+                       con->cursor_column++;
+                       break;
                }
-               if (efi_con_mode.cursor_row > mode->rows)
-                       efi_con_mode.cursor_row = mode->rows;
+               if (con->cursor_column >= mode->columns) {
+                       con->cursor_column = 0;
+                       con->cursor_row++;
+               }
+               con->cursor_row = min(con->cursor_row, (s32)mode->rows - 1);
        }
 
        return EFI_EXIT(EFI_SUCCESS);
@@ -172,7 +187,7 @@ static efi_status_t EFIAPI efi_cout_output_string(
 
 static efi_status_t EFIAPI efi_cout_test_string(
                        struct efi_simple_text_output_protocol *this,
-                       const unsigned short *string)
+                       const efi_string_t string)
 {
        EFI_ENTRY("%p, %p", this, string);
        return EFI_EXIT(EFI_SUCCESS);
@@ -186,6 +201,34 @@ static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols)
        return (mode->rows == rows) && (mode->columns == cols);
 }
 
+static int query_console_serial(int *rows, int *cols)
+{
+       /* Ask the terminal about its size */
+       int n[3];
+       u64 timeout;
+
+       /* Empty input buffer */
+       while (tstc())
+               getc();
+
+       printf(ESC"[18t");
+
+       /* Check if we have a terminal that understands */
+       timeout = timer_get_us() + 1000000;
+       while (!tstc())
+               if (timer_get_us() > timeout)
+                       return -1;
+
+       /* Read {depth,rows,cols} */
+       if (term_read_reply(n, 3, 't'))
+               return -1;
+
+       *cols = n[2];
+       *rows = n[1];
+
+       return 0;
+}
+
 static efi_status_t EFIAPI efi_cout_query_mode(
                        struct efi_simple_text_output_protocol *this,
                        unsigned long mode_number, unsigned long *columns,
@@ -194,34 +237,24 @@ static efi_status_t EFIAPI efi_cout_query_mode(
        EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows);
 
        if (!console_size_queried) {
-               /* Ask the terminal about its size */
-               int n[3];
-               int cols;
-               int rows;
-               u64 timeout;
+               const char *stdout_name = env_get("stdout");
+               int rows, cols;
 
                console_size_queried = true;
 
-               /* Empty input buffer */
-               while (tstc())
-                       getc();
-
-               printf(ESC"[18t");
-
-               /* Check if we have a terminal that understands */
-               timeout = timer_get_us() + 1000000;
-               while (!tstc())
-                       if (timer_get_us() > timeout)
-                               goto out;
-
-               /* Read {depth,rows,cols} */
-               if (term_read_reply(n, 3, 't')) {
+               if (stdout_name && !strcmp(stdout_name, "vidconsole") &&
+                   IS_ENABLED(CONFIG_DM_VIDEO)) {
+                       struct stdio_dev *stdout_dev =
+                               stdio_get_by_name("vidconsole");
+                       struct udevice *dev = stdout_dev->priv;
+                       struct vidconsole_priv *priv =
+                               dev_get_uclass_priv(dev);
+                       rows = priv->rows;
+                       cols = priv->cols;
+               } else if (query_console_serial(&rows, &cols)) {
                        goto out;
                }
 
-               cols = n[2];
-               rows = n[1];
-
                /* Test if we can have Mode 1 */
                if (cols >= 80 && rows >= 50) {
                        efi_cout_modes[1].present = 1;
@@ -426,8 +459,10 @@ static void EFIAPI efi_console_timer_notify(struct efi_event *event,
                                            void *context)
 {
        EFI_ENTRY("%p, %p", event, context);
-       if (tstc())
+       if (tstc()) {
+               efi_con_in.wait_for_key->signaled = 1;
                efi_signal_event(efi_con_in.wait_for_key);
+               }
        EFI_EXIT(EFI_SUCCESS);
 }
 
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
new file mode 100644 (file)
index 0000000..5d5c3b3
--- /dev/null
@@ -0,0 +1,563 @@
+/*
+ * EFI device path from u-boot device-model mapping
+ *
+ * (C) Copyright 2017 Rob Clark
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <dm.h>
+#include <usb.h>
+#include <mmc.h>
+#include <efi_loader.h>
+#include <inttypes.h>
+#include <part.h>
+
+/* template END node: */
+static const struct efi_device_path END = {
+       .type     = DEVICE_PATH_TYPE_END,
+       .sub_type = DEVICE_PATH_SUB_TYPE_END,
+       .length   = sizeof(END),
+};
+
+#define U_BOOT_GUID \
+       EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \
+                0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b)
+
+/* template ROOT node: */
+static const struct efi_device_path_vendor ROOT = {
+       .dp = {
+               .type     = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
+               .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
+               .length   = sizeof(ROOT),
+       },
+       .guid = U_BOOT_GUID,
+};
+
+static void *dp_alloc(size_t sz)
+{
+       void *buf;
+
+       if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) != EFI_SUCCESS)
+               return NULL;
+
+       return buf;
+}
+
+/*
+ * Iterate to next block in device-path, terminating (returning NULL)
+ * at /End* node.
+ */
+struct efi_device_path *efi_dp_next(const struct efi_device_path *dp)
+{
+       if (dp == NULL)
+               return NULL;
+       if (dp->type == DEVICE_PATH_TYPE_END)
+               return NULL;
+       dp = ((void *)dp) + dp->length;
+       if (dp->type == DEVICE_PATH_TYPE_END)
+               return NULL;
+       return (struct efi_device_path *)dp;
+}
+
+/*
+ * Compare two device-paths, stopping when the shorter of the two hits
+ * an End* node.  This is useful to, for example, compare a device-path
+ * representing a device with one representing a file on the device, or
+ * a device with a parent device.
+ */
+int efi_dp_match(struct efi_device_path *a, struct efi_device_path *b)
+{
+       while (1) {
+               int ret;
+
+               ret = memcmp(&a->length, &b->length, sizeof(a->length));
+               if (ret)
+                       return ret;
+
+               ret = memcmp(a, b, a->length);
+               if (ret)
+                       return ret;
+
+               a = efi_dp_next(a);
+               b = efi_dp_next(b);
+
+               if (!a || !b)
+                       return 0;
+       }
+}
+
+
+/*
+ * See UEFI spec (section 3.1.2, about short-form device-paths..
+ * tl;dr: we can have a device-path that starts with a USB WWID
+ * or USB Class node, and a few other cases which don't encode
+ * the full device path with bus hierarchy:
+ *
+ *   - MESSAGING:USB_WWID
+ *   - MESSAGING:USB_CLASS
+ *   - MEDIA:FILE_PATH
+ *   - MEDIA:HARD_DRIVE
+ *   - MESSAGING:URI
+ */
+static struct efi_device_path *shorten_path(struct efi_device_path *dp)
+{
+       while (dp) {
+               /*
+                * TODO: Add MESSAGING:USB_WWID and MESSAGING:URI..
+                * in practice fallback.efi just uses MEDIA:HARD_DRIVE
+                * so not sure when we would see these other cases.
+                */
+               if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) ||
+                   EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) ||
+                   EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH))
+                       return dp;
+
+               dp = efi_dp_next(dp);
+       }
+
+       return dp;
+}
+
+static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
+                                  struct efi_device_path **rem)
+{
+       struct efi_object *efiobj;
+
+       list_for_each_entry(efiobj, &efi_obj_list, link) {
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
+                       struct efi_handler *handler = &efiobj->protocols[i];
+                       struct efi_device_path *obj_dp;
+
+                       if (!handler->guid)
+                               break;
+
+                       if (guidcmp(handler->guid, &efi_guid_device_path))
+                               continue;
+
+                       obj_dp = handler->protocol_interface;
+
+                       do {
+                               if (efi_dp_match(dp, obj_dp) == 0) {
+                                       if (rem) {
+                                               *rem = ((void *)dp) +
+                                                       efi_dp_size(obj_dp);
+                                       }
+                                       return efiobj;
+                               }
+
+                               obj_dp = shorten_path(efi_dp_next(obj_dp));
+                       } while (short_path && obj_dp);
+               }
+       }
+
+       return NULL;
+}
+
+
+/*
+ * Find an efiobj from device-path, if 'rem' is not NULL, returns the
+ * remaining part of the device path after the matched object.
+ */
+struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
+                                  struct efi_device_path **rem)
+{
+       struct efi_object *efiobj;
+
+       efiobj = find_obj(dp, false, rem);
+
+       if (!efiobj)
+               efiobj = find_obj(dp, true, rem);
+
+       return efiobj;
+}
+
+/* return size not including End node: */
+unsigned efi_dp_size(const struct efi_device_path *dp)
+{
+       unsigned sz = 0;
+
+       while (dp) {
+               sz += dp->length;
+               dp = efi_dp_next(dp);
+       }
+
+       return sz;
+}
+
+struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
+{
+       struct efi_device_path *ndp;
+       unsigned sz = efi_dp_size(dp) + sizeof(END);
+
+       if (!dp)
+               return NULL;
+
+       ndp = dp_alloc(sz);
+       memcpy(ndp, dp, sz);
+
+       return ndp;
+}
+
+struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
+                                     const struct efi_device_path *dp2)
+{
+       struct efi_device_path *ret;
+
+       if (!dp1) {
+               ret = efi_dp_dup(dp2);
+       } else if (!dp2) {
+               ret = efi_dp_dup(dp1);
+       } else {
+               /* both dp1 and dp2 are non-null */
+               unsigned sz1 = efi_dp_size(dp1);
+               unsigned sz2 = efi_dp_size(dp2);
+               void *p = dp_alloc(sz1 + sz2 + sizeof(END));
+               memcpy(p, dp1, sz1);
+               memcpy(p + sz1, dp2, sz2);
+               memcpy(p + sz1 + sz2, &END, sizeof(END));
+               ret = p;
+       }
+
+       return ret;
+}
+
+struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
+                                          const struct efi_device_path *node)
+{
+       struct efi_device_path *ret;
+
+       if (!node && !dp) {
+               ret = efi_dp_dup(&END);
+       } else if (!node) {
+               ret = efi_dp_dup(dp);
+       } else if (!dp) {
+               unsigned sz = node->length;
+               void *p = dp_alloc(sz + sizeof(END));
+               memcpy(p, node, sz);
+               memcpy(p + sz, &END, sizeof(END));
+               ret = p;
+       } else {
+               /* both dp and node are non-null */
+               unsigned sz = efi_dp_size(dp);
+               void *p = dp_alloc(sz + node->length + sizeof(END));
+               memcpy(p, dp, sz);
+               memcpy(p + sz, node, node->length);
+               memcpy(p + sz + node->length, &END, sizeof(END));
+               ret = p;
+       }
+
+       return ret;
+}
+
+#ifdef CONFIG_DM
+/* size of device-path not including END node for device and all parents
+ * up to the root device.
+ */
+static unsigned dp_size(struct udevice *dev)
+{
+       if (!dev || !dev->driver)
+               return sizeof(ROOT);
+
+       switch (dev->driver->id) {
+       case UCLASS_ROOT:
+       case UCLASS_SIMPLE_BUS:
+               /* stop traversing parents at this point: */
+               return sizeof(ROOT);
+       case UCLASS_MMC:
+               return dp_size(dev->parent) +
+                       sizeof(struct efi_device_path_sd_mmc_path);
+       case UCLASS_MASS_STORAGE:
+       case UCLASS_USB_HUB:
+               return dp_size(dev->parent) +
+                       sizeof(struct efi_device_path_usb_class);
+       default:
+               /* just skip over unknown classes: */
+               return dp_size(dev->parent);
+       }
+}
+
+static void *dp_fill(void *buf, struct udevice *dev)
+{
+       if (!dev || !dev->driver)
+               return buf;
+
+       switch (dev->driver->id) {
+       case UCLASS_ROOT:
+       case UCLASS_SIMPLE_BUS: {
+               /* stop traversing parents at this point: */
+               struct efi_device_path_vendor *vdp = buf;
+               *vdp = ROOT;
+               return &vdp[1];
+       }
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
+       case UCLASS_MMC: {
+               struct efi_device_path_sd_mmc_path *sddp =
+                       dp_fill(buf, dev->parent);
+               struct mmc *mmc = mmc_get_mmc_dev(dev);
+               struct blk_desc *desc = mmc_get_blk_desc(mmc);
+
+               sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+               sddp->dp.sub_type = (desc->if_type == IF_TYPE_MMC) ?
+                       DEVICE_PATH_SUB_TYPE_MSG_MMC :
+                       DEVICE_PATH_SUB_TYPE_MSG_SD;
+               sddp->dp.length   = sizeof(*sddp);
+               sddp->slot_number = dev->seq;
+
+               return &sddp[1];
+       }
+#endif
+       case UCLASS_MASS_STORAGE:
+       case UCLASS_USB_HUB: {
+               struct efi_device_path_usb_class *udp =
+                       dp_fill(buf, dev->parent);
+               struct usb_device *udev = dev_get_parent_priv(dev);
+               struct usb_device_descriptor *desc = &udev->descriptor;
+
+               udp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+               udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS;
+               udp->dp.length   = sizeof(*udp);
+               udp->vendor_id   = desc->idVendor;
+               udp->product_id  = desc->idProduct;
+               udp->device_class    = desc->bDeviceClass;
+               udp->device_subclass = desc->bDeviceSubClass;
+               udp->device_protocol = desc->bDeviceProtocol;
+
+               return &udp[1];
+       }
+       default:
+               debug("unhandled device class: %s (%u)\n",
+                     dev->name, dev->driver->id);
+               return dp_fill(buf, dev->parent);
+       }
+}
+
+/* Construct a device-path from a device: */
+struct efi_device_path *efi_dp_from_dev(struct udevice *dev)
+{
+       void *buf, *start;
+
+       start = buf = dp_alloc(dp_size(dev) + sizeof(END));
+       buf = dp_fill(buf, dev);
+       *((struct efi_device_path *)buf) = END;
+
+       return start;
+}
+#endif
+
+static unsigned dp_part_size(struct blk_desc *desc, int part)
+{
+       unsigned dpsize;
+
+#ifdef CONFIG_BLK
+       dpsize = dp_size(desc->bdev->parent);
+#else
+       dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
+#endif
+
+       if (part == 0) /* the actual disk, not a partition */
+               return dpsize;
+
+       if (desc->part_type == PART_TYPE_ISO)
+               dpsize += sizeof(struct efi_device_path_cdrom_path);
+       else
+               dpsize += sizeof(struct efi_device_path_hard_drive_path);
+
+       return dpsize;
+}
+
+static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
+{
+       disk_partition_t info;
+
+#ifdef CONFIG_BLK
+       buf = dp_fill(buf, desc->bdev->parent);
+#else
+       /*
+        * We *could* make a more accurate path, by looking at if_type
+        * and handling all the different cases like we do for non-
+        * legacy (ie CONFIG_BLK=y) case.  But most important thing
+        * is just to have a unique device-path for if_type+devnum.
+        * So map things to a fictional USB device:
+        */
+       struct efi_device_path_usb *udp;
+
+       memcpy(buf, &ROOT, sizeof(ROOT));
+       buf += sizeof(ROOT);
+
+       udp = buf;
+       udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+       udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
+       udp->dp.length = sizeof(*udp);
+       udp->parent_port_number = desc->if_type;
+       udp->usb_interface = desc->devnum;
+       buf = &udp[1];
+#endif
+
+       if (part == 0) /* the actual disk, not a partition */
+               return buf;
+
+       part_get_info(desc, part, &info);
+
+       if (desc->part_type == PART_TYPE_ISO) {
+               struct efi_device_path_cdrom_path *cddp = buf;
+
+               cddp->boot_entry = part - 1;
+               cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+               cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
+               cddp->dp.length = sizeof(*cddp);
+               cddp->partition_start = info.start;
+               cddp->partition_end = info.size;
+
+               buf = &cddp[1];
+       } else {
+               struct efi_device_path_hard_drive_path *hddp = buf;
+
+               hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+               hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
+               hddp->dp.length = sizeof(*hddp);
+               hddp->partition_number = part - 1;
+               hddp->partition_start = info.start;
+               hddp->partition_end = info.size;
+               if (desc->part_type == PART_TYPE_EFI)
+                       hddp->partmap_type = 2;
+               else
+                       hddp->partmap_type = 1;
+               hddp->signature_type = desc->sig_type;
+               if (hddp->signature_type != 0)
+                       memcpy(hddp->partition_signature, &desc->guid_sig,
+                              sizeof(hddp->partition_signature));
+
+               buf = &hddp[1];
+       }
+
+       return buf;
+}
+
+
+/* Construct a device-path from a partition on a blk device: */
+struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
+{
+       void *buf, *start;
+
+       start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
+
+       buf = dp_part_fill(buf, desc, part);
+
+       *((struct efi_device_path *)buf) = END;
+
+       return start;
+}
+
+/* convert path to an UEFI style path (ie. DOS style backslashes and utf16) */
+static void path_to_uefi(u16 *uefi, const char *path)
+{
+       while (*path) {
+               char c = *(path++);
+               if (c == '/')
+                       c = '\\';
+               *(uefi++) = c;
+       }
+       *uefi = '\0';
+}
+
+/*
+ * If desc is NULL, this creates a path with only the file component,
+ * otherwise it creates a full path with both device and file components
+ */
+struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
+               const char *path)
+{
+       struct efi_device_path_file_path *fp;
+       void *buf, *start;
+       unsigned dpsize = 0, fpsize;
+
+       if (desc)
+               dpsize = dp_part_size(desc, part);
+
+       fpsize = sizeof(struct efi_device_path) + 2 * (strlen(path) + 1);
+       dpsize += fpsize;
+
+       start = buf = dp_alloc(dpsize + sizeof(END));
+
+       if (desc)
+               buf = dp_part_fill(buf, desc, part);
+
+       /* add file-path: */
+       fp = buf;
+       fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+       fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
+       fp->dp.length = fpsize;
+       path_to_uefi(fp->str, path);
+       buf += fpsize;
+
+       *((struct efi_device_path *)buf) = END;
+
+       return start;
+}
+
+#ifdef CONFIG_NET
+struct efi_device_path *efi_dp_from_eth(void)
+{
+       struct efi_device_path_mac_addr *ndp;
+       void *buf, *start;
+       unsigned dpsize = 0;
+
+       assert(eth_get_dev());
+
+#ifdef CONFIG_DM_ETH
+       dpsize += dp_size(eth_get_dev());
+#else
+       dpsize += sizeof(ROOT);
+#endif
+       dpsize += sizeof(*ndp);
+
+       start = buf = dp_alloc(dpsize + sizeof(END));
+
+#ifdef CONFIG_DM_ETH
+       buf = dp_fill(buf, eth_get_dev());
+#else
+       memcpy(buf, &ROOT, sizeof(ROOT));
+       buf += sizeof(ROOT);
+#endif
+
+       ndp = buf;
+       ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+       ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
+       ndp->dp.length = sizeof(*ndp);
+       memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN);
+       buf = &ndp[1];
+
+       *((struct efi_device_path *)buf) = END;
+
+       return start;
+}
+#endif
+
+/*
+ * Helper to split a full device path (containing both device and file
+ * parts) into it's constituent parts.
+ */
+void efi_dp_split_file_path(struct efi_device_path *full_path,
+                           struct efi_device_path **device_path,
+                           struct efi_device_path **file_path)
+{
+       struct efi_device_path *p, *dp, *fp;
+
+       dp = efi_dp_dup(full_path);
+       p = dp;
+       while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH))
+               p = efi_dp_next(p);
+       fp = efi_dp_dup(p);
+
+       p->type = DEVICE_PATH_TYPE_END;
+       p->sub_type = DEVICE_PATH_SUB_TYPE_END;
+       p->length = sizeof(*p);
+
+       *device_path = dp;
+       *file_path = fp;
+}
index 4b2f43f0c8a65e037eed759426ffa8cb13ff66d4..1a5ef3919bac92035c7a1a112b08a4313a8d6c71 100644 (file)
 const efi_guid_t efi_guid_device_path_to_text_protocol =
                EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
 
-static uint16_t *efi_convert_device_node_to_text(
-               struct efi_device_path_protocol *device_node,
-               bool display_only,
-               bool allow_shortcuts)
+static char *dp_unknown(char *s, struct efi_device_path *dp)
 {
-       unsigned long buffer_size;
-       efi_status_t r;
-       uint16_t *buffer = NULL;
-       int i;
+       s += sprintf(s, "/UNKNOWN(%04x,%04x)", dp->type, dp->sub_type);
+       return s;
+}
 
-       switch (device_node->type) {
-       case DEVICE_PATH_TYPE_END:
-               return NULL;
-       case DEVICE_PATH_TYPE_MESSAGING_DEVICE:
-               switch (device_node->sub_type) {
-               case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: {
-                       struct efi_device_path_mac_addr *dp =
-                               (struct efi_device_path_mac_addr *)device_node;
-
-                       if (dp->if_type != 0 && dp->if_type != 1)
-                               break;
-                       r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
-                                             2 * MAC_OUTPUT_LEN,
-                                             (void **)&buffer);
-                       if (r != EFI_SUCCESS)
-                               return NULL;
-                       sprintf((char *)buffer,
-                               "MAC(%02x%02x%02x%02x%02x%02x,0x%1x)",
-                               dp->mac.addr[0], dp->mac.addr[1],
-                               dp->mac.addr[2], dp->mac.addr[3],
-                               dp->mac.addr[4], dp->mac.addr[5],
-                               dp->if_type);
-                       for (i = MAC_OUTPUT_LEN - 1; i >= 0; --i)
-                               buffer[i] = ((uint8_t *)buffer)[i];
+static char *dp_hardware(char *s, struct efi_device_path *dp)
+{
+       switch (dp->sub_type) {
+       case DEVICE_PATH_SUB_TYPE_VENDOR: {
+               struct efi_device_path_vendor *vdp =
+                       (struct efi_device_path_vendor *)dp;
+               s += sprintf(s, "/VenHw(%pUl)", &vdp->guid);
+               break;
+       }
+       default:
+               s = dp_unknown(s, dp);
+               break;
+       }
+       return s;
+}
+
+static char *dp_acpi(char *s, struct efi_device_path *dp)
+{
+       switch (dp->sub_type) {
+       case DEVICE_PATH_SUB_TYPE_ACPI_DEVICE: {
+               struct efi_device_path_acpi_path *adp =
+                       (struct efi_device_path_acpi_path *)dp;
+               s += sprintf(s, "/Acpi(PNP%04x", EISA_PNP_NUM(adp->hid));
+               if (adp->uid)
+                       s += sprintf(s, ",%d", adp->uid);
+               s += sprintf(s, ")");
+               break;
+       }
+       default:
+               s = dp_unknown(s, dp);
+               break;
+       }
+       return s;
+}
+
+static char *dp_msging(char *s, struct efi_device_path *dp)
+{
+       switch (dp->sub_type) {
+       case DEVICE_PATH_SUB_TYPE_MSG_USB: {
+               struct efi_device_path_usb *udp =
+                       (struct efi_device_path_usb *)dp;
+               s += sprintf(s, "/Usb(0x%x,0x%x)", udp->parent_port_number,
+                            udp->usb_interface);
+               break;
+       }
+       case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: {
+               struct efi_device_path_mac_addr *mdp =
+                       (struct efi_device_path_mac_addr *)dp;
+
+               if (mdp->if_type != 0 && mdp->if_type != 1)
                        break;
-                       }
-               }
+
+               s += sprintf(s, "/MAC(%02x%02x%02x%02x%02x%02x,0x%1x)",
+                       mdp->mac.addr[0], mdp->mac.addr[1],
+                       mdp->mac.addr[2], mdp->mac.addr[3],
+                       mdp->mac.addr[4], mdp->mac.addr[5],
+                       mdp->if_type);
+
+               break;
+       }
+       case DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS: {
+               struct efi_device_path_usb_class *ucdp =
+                       (struct efi_device_path_usb_class *)dp;
+
+               s += sprintf(s, "/USBClass(%x,%x,%x,%x,%x)",
+                       ucdp->vendor_id, ucdp->product_id,
+                       ucdp->device_class, ucdp->device_subclass,
+                       ucdp->device_protocol);
+
+               break;
+       }
+       case DEVICE_PATH_SUB_TYPE_MSG_SD:
+       case DEVICE_PATH_SUB_TYPE_MSG_MMC: {
+               const char *typename =
+                       (dp->sub_type == DEVICE_PATH_SUB_TYPE_MSG_SD) ?
+                                       "SDCard" : "MMC";
+               struct efi_device_path_sd_mmc_path *sddp =
+                       (struct efi_device_path_sd_mmc_path *)dp;
+               s += sprintf(s, "/%s(Slot%u)", typename, sddp->slot_number);
+               break;
+       }
+       default:
+               s = dp_unknown(s, dp);
                break;
-       case DEVICE_PATH_TYPE_MEDIA_DEVICE:
-               switch (device_node->sub_type) {
-               case DEVICE_PATH_SUB_TYPE_FILE_PATH:
-                       buffer_size = device_node->length - 4;
-                       r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
-                                             buffer_size, (void **) &buffer);
-                       if (r != EFI_SUCCESS)
-                               return NULL;
-                       memcpy(buffer, device_node->data, buffer_size);
+       }
+       return s;
+}
+
+static char *dp_media(char *s, struct efi_device_path *dp)
+{
+       switch (dp->sub_type) {
+       case DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH: {
+               struct efi_device_path_hard_drive_path *hddp =
+                       (struct efi_device_path_hard_drive_path *)dp;
+               void *sig = hddp->partition_signature;
+
+               switch (hddp->signature_type) {
+               case SIG_TYPE_MBR:
+                       s += sprintf(s, "/HD(Part%d,Sig%08x)",
+                                    hddp->partition_number,
+                                    *(uint32_t *)sig);
                        break;
+               case SIG_TYPE_GUID:
+                       s += sprintf(s, "/HD(Part%d,Sig%pUl)",
+                                    hddp->partition_number, sig);
+               default:
+                       s += sprintf(s, "/HD(Part%d,MBRType=%02x,SigType=%02x)",
+                                    hddp->partition_number, hddp->partmap_type,
+                                    hddp->signature_type);
                }
+
+               break;
+       }
+       case DEVICE_PATH_SUB_TYPE_CDROM_PATH: {
+               struct efi_device_path_cdrom_path *cddp =
+                       (struct efi_device_path_cdrom_path *)dp;
+               s += sprintf(s, "/CDROM(0x%x)", cddp->boot_entry);
+               break;
+       }
+       case DEVICE_PATH_SUB_TYPE_FILE_PATH: {
+               struct efi_device_path_file_path *fp =
+                       (struct efi_device_path_file_path *)dp;
+               int slen = (dp->length - sizeof(*dp)) / 2;
+               s += sprintf(s, "/%-*ls", slen, fp->str);
                break;
        }
+       default:
+               s = dp_unknown(s, dp);
+               break;
+       }
+       return s;
+}
 
-       /*
-        * For all node types that we do not yet support return
-        * 'UNKNOWN(type,subtype)'.
-        */
-       if (!buffer) {
-               r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
-                                     2 * UNKNOWN_OUTPUT_LEN,
-                                     (void **)&buffer);
-               if (r != EFI_SUCCESS)
-                       return NULL;
-               sprintf((char *)buffer,
-                       "UNKNOWN(%04x,%04x)",
-                       device_node->type,
-                       device_node->sub_type);
-               for (i = UNKNOWN_OUTPUT_LEN - 1; i >= 0; --i)
-                       buffer[i] = ((uint8_t *)buffer)[i];
+static uint16_t *efi_convert_device_node_to_text(
+               struct efi_device_path *dp,
+               bool display_only,
+               bool allow_shortcuts)
+{
+       unsigned long len;
+       efi_status_t r;
+       char buf[512];  /* this ought be be big enough for worst case */
+       char *str = buf;
+       uint16_t *out;
+
+       while (dp) {
+               switch (dp->type) {
+               case DEVICE_PATH_TYPE_HARDWARE_DEVICE:
+                       str = dp_hardware(str, dp);
+                       break;
+               case DEVICE_PATH_TYPE_ACPI_DEVICE:
+                       str = dp_acpi(str, dp);
+                       break;
+               case DEVICE_PATH_TYPE_MESSAGING_DEVICE:
+                       str = dp_msging(str, dp);
+                       break;
+               case DEVICE_PATH_TYPE_MEDIA_DEVICE:
+                       str = dp_media(str, dp);
+                       break;
+               default:
+                       str = dp_unknown(str, dp);
+               }
+
+               dp = efi_dp_next(dp);
        }
 
-       return buffer;
+       *str++ = '\0';
+
+       len = str - buf;
+       r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, 2 * len, (void **)&out);
+       if (r != EFI_SUCCESS)
+               return NULL;
+
+       ascii2unicode(out, buf);
+       out[len - 1] = 0;
+
+       return out;
 }
 
+/* helper for debug prints.. efi_free_pool() the result. */
+uint16_t *efi_dp_str(struct efi_device_path *dp)
+{
+       return efi_convert_device_node_to_text(dp, true, true);
+}
+
+
 static uint16_t EFIAPI *efi_convert_device_node_to_text_ext(
-               struct efi_device_path_protocol *device_node,
+               struct efi_device_path *device_node,
                bool display_only,
                bool allow_shortcuts)
 {
@@ -105,7 +223,7 @@ static uint16_t EFIAPI *efi_convert_device_node_to_text_ext(
 }
 
 static uint16_t EFIAPI *efi_convert_device_path_to_text(
-               struct efi_device_path_protocol *device_path,
+               struct efi_device_path *device_path,
                bool display_only,
                bool allow_shortcuts)
 {
index ed06485e334b771b2e2e8872615952b19735c0f2..eb9ce772d1d6fe00830e9bbc2732917e8136b8af 100644 (file)
@@ -28,11 +28,15 @@ struct efi_disk_obj {
        /* EFI Interface Media descriptor struct, referenced by ops */
        struct efi_block_io_media media;
        /* EFI device path to this block device */
-       struct efi_device_path_file_path *dp;
+       struct efi_device_path *dp;
+       /* partition # */
+       unsigned int part;
+       /* handle to filesys proto (for partition objects) */
+       struct efi_simple_file_system_protocol *volume;
        /* Offset into disk for simple partitions */
        lbaint_t offset;
        /* Internal block device */
-       const struct blk_desc *desc;
+       struct blk_desc *desc;
 };
 
 static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
@@ -47,7 +51,7 @@ enum efi_disk_direction {
        EFI_DISK_WRITE,
 };
 
-static efi_status_t EFIAPI efi_disk_rw_blocks(struct efi_block_io *this,
+static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this,
                        u32 media_id, u64 lba, unsigned long buffer_size,
                        void *buffer, enum efi_disk_direction direction)
 {
@@ -170,28 +174,58 @@ static const struct efi_block_io block_io_disk_template = {
        .flush_blocks = &efi_disk_flush_blocks,
 };
 
+/*
+ * Find filesystem from a device-path.  The passed in path 'p' probably
+ * contains one or more /File(name) nodes, so the comparison stops at
+ * the first /File() node, and returns the pointer to that via 'rp'.
+ * This is mostly intended to be a helper to map a device-path to an
+ * efi_file_handle object.
+ */
+struct efi_simple_file_system_protocol *
+efi_fs_from_path(struct efi_device_path *fp)
+{
+       struct efi_object *efiobj;
+       struct efi_disk_obj *diskobj;
+
+       efiobj = efi_dp_find_obj(fp, NULL);
+       if (!efiobj)
+               return NULL;
+
+       diskobj = container_of(efiobj, struct efi_disk_obj, parent);
+
+       return diskobj->volume;
+}
+
 static void efi_disk_add_dev(const char *name,
                             const char *if_typename,
-                            const struct blk_desc *desc,
+                            struct blk_desc *desc,
                             int dev_index,
-                            lbaint_t offset)
+                            lbaint_t offset,
+                            unsigned int part)
 {
        struct efi_disk_obj *diskobj;
-       struct efi_device_path_file_path *dp;
-       int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
 
        /* Don't add empty devices */
        if (!desc->lba)
                return;
 
-       diskobj = calloc(1, objlen);
+       diskobj = calloc(1, sizeof(*diskobj));
 
        /* Fill in object data */
-       dp = (void *)&diskobj[1];
+       diskobj->dp = efi_dp_from_part(desc, part);
+       diskobj->part = part;
        diskobj->parent.protocols[0].guid = &efi_block_io_guid;
        diskobj->parent.protocols[0].protocol_interface = &diskobj->ops;
        diskobj->parent.protocols[1].guid = &efi_guid_device_path;
-       diskobj->parent.protocols[1].protocol_interface = dp;
+       diskobj->parent.protocols[1].protocol_interface = diskobj->dp;
+       if (part >= 1) {
+               diskobj->volume = efi_simple_file_system(desc, part,
+                                                        diskobj->dp);
+               diskobj->parent.protocols[2].guid =
+                       &efi_simple_file_system_protocol_guid;
+               diskobj->parent.protocols[2].protocol_interface =
+                       diskobj->volume;
+       }
        diskobj->parent.handle = diskobj;
        diskobj->ops = block_io_disk_template;
        diskobj->ifname = if_typename;
@@ -207,17 +241,6 @@ static void efi_disk_add_dev(const char *name,
        diskobj->media.last_block = desc->lba - offset;
        diskobj->ops.media = &diskobj->media;
 
-       /* Fill in device path */
-       diskobj->dp = dp;
-       dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
-       dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
-       dp[0].dp.length = sizeof(*dp);
-       ascii2unicode(dp[0].str, name);
-
-       dp[1].dp.type = DEVICE_PATH_TYPE_END;
-       dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
-       dp[1].dp.length = sizeof(*dp);
-
        /* Hook up to the device list */
        list_add_tail(&diskobj->parent.link, &efi_obj_list);
 }
@@ -236,14 +259,18 @@ static int efi_disk_create_eltorito(struct blk_desc *desc,
        if (desc->part_type != PART_TYPE_ISO)
                return 0;
 
+       /* and devices for each partition: */
        while (!part_get_info(desc, part, &info)) {
                snprintf(devname, sizeof(devname), "%s:%d", pdevname,
                         part);
                efi_disk_add_dev(devname, if_typename, desc, diskid,
-                                info.start);
+                                info.start, part);
                part++;
                disks++;
        }
+
+       /* ... and add block device: */
+       efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0);
 #endif
 
        return disks;
@@ -271,9 +298,22 @@ int efi_disk_register(void)
             uclass_next_device_check(&dev)) {
                struct blk_desc *desc = dev_get_uclass_platdata(dev);
                const char *if_typename = dev->driver->name;
+               disk_partition_t info;
+               int part = 1;
 
                printf("Scanning disk %s...\n", dev->name);
-               efi_disk_add_dev(dev->name, if_typename, desc, desc->devnum, 0);
+
+               /* add devices for each partition: */
+               while (!part_get_info(desc, part, &info)) {
+                       efi_disk_add_dev(dev->name, if_typename, desc,
+                                        desc->devnum, 0, part);
+                       part++;
+               }
+
+               /* ... and add block device: */
+               efi_disk_add_dev(dev->name, if_typename, desc,
+                                desc->devnum, 0, 0);
+
                disks++;
 
                /*
@@ -309,7 +349,7 @@ int efi_disk_register(void)
 
                        snprintf(devname, sizeof(devname), "%s%d",
                                 if_typename, i);
-                       efi_disk_add_dev(devname, if_typename, desc, i, 0);
+                       efi_disk_add_dev(devname, if_typename, desc, i, 0, 0);
                        disks++;
 
                        /*
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
new file mode 100644 (file)
index 0000000..52a4e74
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ *  EFI utils
+ *
+ *  Copyright (c) 2017 Rob Clark
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <efi_loader.h>
+#include <malloc.h>
+#include <fs.h>
+
+struct file_system {
+       struct efi_simple_file_system_protocol base;
+       struct efi_device_path *dp;
+       struct blk_desc *desc;
+       int part;
+};
+#define to_fs(x) container_of(x, struct file_system, base)
+
+struct file_handle {
+       struct efi_file_handle base;
+       struct file_system *fs;
+       loff_t offset;       /* current file position/cursor */
+       int isdir;
+
+       /* for reading a directory: */
+       struct fs_dir_stream *dirs;
+       struct fs_dirent *dent;
+
+       char path[0];
+};
+#define to_fh(x) container_of(x, struct file_handle, base)
+
+static const struct efi_file_handle efi_file_handle_protocol;
+
+static char *basename(struct file_handle *fh)
+{
+       char *s = strrchr(fh->path, '/');
+       if (s)
+               return s + 1;
+       return fh->path;
+}
+
+static int set_blk_dev(struct file_handle *fh)
+{
+       return fs_set_blk_dev_with_part(fh->fs->desc, fh->fs->part);
+}
+
+static int is_dir(struct file_handle *fh)
+{
+       struct fs_dir_stream *dirs;
+
+       set_blk_dev(fh);
+       dirs = fs_opendir(fh->path);
+       if (!dirs)
+               return 0;
+
+       fs_closedir(dirs);
+
+       return 1;
+}
+
+/*
+ * Normalize a path which may include either back or fwd slashes,
+ * double slashes, . or .. entries in the path, etc.
+ */
+static int sanitize_path(char *path)
+{
+       char *p;
+
+       /* backslash to slash: */
+       p = path;
+       while ((p = strchr(p, '\\')))
+               *p++ = '/';
+
+       /* handle double-slashes: */
+       p = path;
+       while ((p = strstr(p, "//"))) {
+               char *src = p + 1;
+               memmove(p, src, strlen(src) + 1);
+       }
+
+       /* handle extra /.'s */
+       p = path;
+       while ((p = strstr(p, "/."))) {
+               /*
+                * You'd be tempted to do this *after* handling ".."s
+                * below to avoid having to check if "/." is start of
+                * a "/..", but that won't have the correct results..
+                * for example, "/foo/./../bar" would get resolved to
+                * "/foo/bar" if you did these two passes in the other
+                * order
+                */
+               if (p[2] == '.') {
+                       p += 2;
+                       continue;
+               }
+               char *src = p + 2;
+               memmove(p, src, strlen(src) + 1);
+       }
+
+       /* handle extra /..'s: */
+       p = path;
+       while ((p = strstr(p, "/.."))) {
+               char *src = p + 3;
+
+               p--;
+
+               /* find beginning of previous path entry: */
+               while (true) {
+                       if (p < path)
+                               return -1;
+                       if (*p == '/')
+                               break;
+                       p--;
+               }
+
+               memmove(p, src, strlen(src) + 1);
+       }
+
+       return 0;
+}
+
+/* NOTE: despite what you would expect, 'file_name' is actually a path.
+ * With windoze style backlashes, ofc.
+ */
+static struct efi_file_handle *file_open(struct file_system *fs,
+               struct file_handle *parent, s16 *file_name, u64 mode)
+{
+       struct file_handle *fh;
+       char f0[MAX_UTF8_PER_UTF16] = {0};
+       int plen = 0;
+       int flen = 0;
+
+       if (file_name) {
+               utf16_to_utf8((u8 *)f0, (u16 *)file_name, 1);
+               flen = utf16_strlen((u16 *)file_name);
+       }
+
+       /* we could have a parent, but also an absolute path: */
+       if (f0[0] == '\\') {
+               plen = 0;
+       } else if (parent) {
+               plen = strlen(parent->path) + 1;
+       }
+
+       /* +2 is for null and '/' */
+       fh = calloc(1, sizeof(*fh) + plen + (flen * MAX_UTF8_PER_UTF16) + 2);
+
+       fh->base = efi_file_handle_protocol;
+       fh->fs = fs;
+
+       if (parent) {
+               char *p = fh->path;
+
+               if (plen > 0) {
+                       strcpy(p, parent->path);
+                       p += plen - 1;
+                       *p++ = '/';
+               }
+
+               utf16_to_utf8((u8 *)p, (u16 *)file_name, flen);
+
+               if (sanitize_path(fh->path))
+                       goto error;
+
+               /* check if file exists: */
+               if (set_blk_dev(fh))
+                       goto error;
+
+               if (!((mode & EFI_FILE_MODE_CREATE) || fs_exists(fh->path)))
+                       goto error;
+
+               /* figure out if file is a directory: */
+               fh->isdir = is_dir(fh);
+       } else {
+               fh->isdir = 1;
+               strcpy(fh->path, "");
+       }
+
+       return &fh->base;
+
+error:
+       free(fh);
+       return NULL;
+}
+
+static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
+               struct efi_file_handle **new_handle,
+               s16 *file_name, u64 open_mode, u64 attributes)
+{
+       struct file_handle *fh = to_fh(file);
+
+       EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle, file_name,
+                 open_mode, attributes);
+
+       *new_handle = file_open(fh->fs, fh, file_name, open_mode);
+       if (!*new_handle)
+               return EFI_EXIT(EFI_NOT_FOUND);
+
+       return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t file_close(struct file_handle *fh)
+{
+       fs_closedir(fh->dirs);
+       free(fh);
+       return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file)
+{
+       struct file_handle *fh = to_fh(file);
+       EFI_ENTRY("%p", file);
+       return EFI_EXIT(file_close(fh));
+}
+
+static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file)
+{
+       struct file_handle *fh = to_fh(file);
+       EFI_ENTRY("%p", file);
+       file_close(fh);
+       return EFI_EXIT(EFI_WARN_DELETE_FAILURE);
+}
+
+static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size,
+               void *buffer)
+{
+       loff_t actread;
+
+       if (fs_read(fh->path, (ulong)buffer, fh->offset,
+                   *buffer_size, &actread))
+               return EFI_DEVICE_ERROR;
+
+       *buffer_size = actread;
+       fh->offset += actread;
+
+       return EFI_SUCCESS;
+}
+
+static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
+               void *buffer)
+{
+       struct efi_file_info *info = buffer;
+       struct fs_dirent *dent;
+       unsigned int required_size;
+
+       if (!fh->dirs) {
+               assert(fh->offset == 0);
+               fh->dirs = fs_opendir(fh->path);
+               if (!fh->dirs)
+                       return EFI_DEVICE_ERROR;
+       }
+
+       /*
+        * So this is a bit awkward.  Since fs layer is stateful and we
+        * can't rewind an entry, in the EFI_BUFFER_TOO_SMALL case below
+        * we might have to return without consuming the dent.. so we
+        * have to stash it for next call.
+        */
+       if (fh->dent) {
+               dent = fh->dent;
+               fh->dent = NULL;
+       } else {
+               dent = fs_readdir(fh->dirs);
+       }
+
+
+       if (!dent) {
+               /* no more files in directory: */
+               /* workaround shim.efi bug/quirk.. as find_boot_csv()
+                * loops through directory contents, it initially calls
+                * read w/ zero length buffer to find out how much mem
+                * to allocate for the EFI_FILE_INFO, then allocates,
+                * and then calls a 2nd time.  If we return size of
+                * zero the first time, it happily passes that to
+                * AllocateZeroPool(), and when that returns NULL it
+                * thinks it is EFI_OUT_OF_RESOURCES.  So on first
+                * call return a non-zero size:
+                */
+               if (*buffer_size == 0)
+                       *buffer_size = sizeof(*info);
+               else
+                       *buffer_size = 0;
+               return EFI_SUCCESS;
+       }
+
+       /* check buffer size: */
+       required_size = sizeof(*info) + 2 * (strlen(dent->name) + 1);
+       if (*buffer_size < required_size) {
+               *buffer_size = required_size;
+               fh->dent = dent;
+               return EFI_BUFFER_TOO_SMALL;
+       }
+
+       *buffer_size = required_size;
+       memset(info, 0, required_size);
+
+       info->size = required_size;
+       info->file_size = dent->size;
+       info->physical_size = dent->size;
+
+       if (dent->type == FS_DT_DIR)
+               info->attribute |= EFI_FILE_DIRECTORY;
+
+       ascii2unicode((u16 *)info->file_name, dent->name);
+
+       fh->offset++;
+
+       return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
+               u64 *buffer_size, void *buffer)
+{
+       struct file_handle *fh = to_fh(file);
+       efi_status_t ret = EFI_SUCCESS;
+
+       EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
+
+       if (set_blk_dev(fh)) {
+               ret = EFI_DEVICE_ERROR;
+               goto error;
+       }
+
+       if (fh->isdir)
+               ret = dir_read(fh, buffer_size, buffer);
+       else
+               ret = file_read(fh, buffer_size, buffer);
+
+error:
+       return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
+               u64 *buffer_size, void *buffer)
+{
+       struct file_handle *fh = to_fh(file);
+       efi_status_t ret = EFI_SUCCESS;
+       loff_t actwrite;
+
+       EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
+
+       if (set_blk_dev(fh)) {
+               ret = EFI_DEVICE_ERROR;
+               goto error;
+       }
+
+       if (fs_write(fh->path, (ulong)buffer, fh->offset, *buffer_size,
+                    &actwrite)) {
+               ret = EFI_DEVICE_ERROR;
+               goto error;
+       }
+
+       *buffer_size = actwrite;
+       fh->offset += actwrite;
+
+error:
+       return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_getpos(struct efi_file_handle *file,
+               u64 *pos)
+{
+       struct file_handle *fh = to_fh(file);
+       EFI_ENTRY("%p, %p", file, pos);
+       *pos = fh->offset;
+       return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file,
+               u64 pos)
+{
+       struct file_handle *fh = to_fh(file);
+       efi_status_t ret = EFI_SUCCESS;
+
+       EFI_ENTRY("%p, %llu", file, pos);
+
+       if (fh->isdir) {
+               if (pos != 0) {
+                       ret = EFI_UNSUPPORTED;
+                       goto error;
+               }
+               fs_closedir(fh->dirs);
+               fh->dirs = NULL;
+       }
+
+       if (pos == ~0ULL) {
+               loff_t file_size;
+
+               if (set_blk_dev(fh)) {
+                       ret = EFI_DEVICE_ERROR;
+                       goto error;
+               }
+
+               if (fs_size(fh->path, &file_size)) {
+                       ret = EFI_DEVICE_ERROR;
+                       goto error;
+               }
+
+               pos = file_size;
+       }
+
+       fh->offset = pos;
+
+error:
+       return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file,
+               efi_guid_t *info_type, u64 *buffer_size, void *buffer)
+{
+       struct file_handle *fh = to_fh(file);
+       efi_status_t ret = EFI_SUCCESS;
+
+       EFI_ENTRY("%p, %p, %p, %p", file, info_type, buffer_size, buffer);
+
+       if (!guidcmp(info_type, &efi_file_info_guid)) {
+               struct efi_file_info *info = buffer;
+               char *filename = basename(fh);
+               unsigned int required_size;
+               loff_t file_size;
+
+               /* check buffer size: */
+               required_size = sizeof(*info) + 2 * (strlen(filename) + 1);
+               if (*buffer_size < required_size) {
+                       *buffer_size = required_size;
+                       ret = EFI_BUFFER_TOO_SMALL;
+                       goto error;
+               }
+
+               if (set_blk_dev(fh)) {
+                       ret = EFI_DEVICE_ERROR;
+                       goto error;
+               }
+
+               if (fs_size(fh->path, &file_size)) {
+                       ret = EFI_DEVICE_ERROR;
+                       goto error;
+               }
+
+               memset(info, 0, required_size);
+
+               info->size = required_size;
+               info->file_size = file_size;
+               info->physical_size = file_size;
+
+               if (fh->isdir)
+                       info->attribute |= EFI_FILE_DIRECTORY;
+
+               ascii2unicode((u16 *)info->file_name, filename);
+       } else {
+               ret = EFI_UNSUPPORTED;
+       }
+
+error:
+       return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file,
+               efi_guid_t *info_type, u64 buffer_size, void *buffer)
+{
+       EFI_ENTRY("%p, %p, %llu, %p", file, info_type, buffer_size, buffer);
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file)
+{
+       EFI_ENTRY("%p", file);
+       return EFI_EXIT(EFI_SUCCESS);
+}
+
+static const struct efi_file_handle efi_file_handle_protocol = {
+       .rev = EFI_FILE_PROTOCOL_REVISION,
+       .open = efi_file_open,
+       .close = efi_file_close,
+       .delete = efi_file_delete,
+       .read = efi_file_read,
+       .write = efi_file_write,
+       .getpos = efi_file_getpos,
+       .setpos = efi_file_setpos,
+       .getinfo = efi_file_getinfo,
+       .setinfo = efi_file_setinfo,
+       .flush = efi_file_flush,
+};
+
+struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
+{
+       struct efi_simple_file_system_protocol *v;
+       struct efi_file_handle *f;
+       efi_status_t ret;
+
+       v = efi_fs_from_path(fp);
+       if (!v)
+               return NULL;
+
+       EFI_CALL(ret = v->open_volume(v, &f));
+       if (ret != EFI_SUCCESS)
+               return NULL;
+
+       /* skip over device-path nodes before the file path: */
+       while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH))
+               fp = efi_dp_next(fp);
+
+       while (fp) {
+               struct efi_device_path_file_path *fdp =
+                       container_of(fp, struct efi_device_path_file_path, dp);
+               struct efi_file_handle *f2;
+
+               if (!EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) {
+                       printf("bad file path!\n");
+                       f->close(f);
+                       return NULL;
+               }
+
+               EFI_CALL(ret = f->open(f, &f2, (s16 *)fdp->str,
+                                      EFI_FILE_MODE_READ, 0));
+               if (ret != EFI_SUCCESS)
+                       return NULL;
+
+               fp = efi_dp_next(fp);
+
+               EFI_CALL(f->close(f));
+               f = f2;
+       }
+
+       return f;
+}
+
+static efi_status_t EFIAPI
+efi_open_volume(struct efi_simple_file_system_protocol *this,
+               struct efi_file_handle **root)
+{
+       struct file_system *fs = to_fs(this);
+
+       EFI_ENTRY("%p, %p", this, root);
+
+       *root = file_open(fs, NULL, NULL, 0);
+
+       return EFI_EXIT(EFI_SUCCESS);
+}
+
+struct efi_simple_file_system_protocol *
+efi_simple_file_system(struct blk_desc *desc, int part,
+                      struct efi_device_path *dp)
+{
+       struct file_system *fs;
+
+       fs = calloc(1, sizeof(*fs));
+       fs->base.rev = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
+       fs->base.open_volume = efi_open_volume;
+       fs->desc = desc;
+       fs->part = part;
+       fs->dp = dp;
+
+       return &fs->base;
+}
index f961407f50ab8e59301aebdf30db57115d170040..af29cc4f04e9849c1ca5a84805a2eab01f28ed02 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
+const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
 const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID;
 const efi_guid_t efi_guid_loaded_image = LOADED_IMAGE_GUID;
+const efi_guid_t efi_simple_file_system_protocol_guid =
+               EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
 
 static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
                        unsigned long rel_size, void *efi_reloc)
@@ -90,6 +94,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
        unsigned long virt_size = 0;
        bool can_run_nt64 = true;
        bool can_run_nt32 = true;
+       uint16_t image_type;
 
 #if defined(CONFIG_ARM64)
        can_run_nt32 = false;
@@ -135,6 +140,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
                entry = efi_reloc + opt->AddressOfEntryPoint;
                rel_size = opt->DataDirectory[rel_idx].Size;
                rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
+               image_type = opt->Subsystem;
        } else if (can_run_nt32 &&
                   (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)) {
                IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
@@ -148,12 +154,32 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
                entry = efi_reloc + opt->AddressOfEntryPoint;
                rel_size = opt->DataDirectory[rel_idx].Size;
                rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
+               image_type = opt->Subsystem;
        } else {
                printf("%s: Invalid optional header magic %x\n", __func__,
                       nt->OptionalHeader.Magic);
                return NULL;
        }
 
+       switch (image_type) {
+       case IMAGE_SUBSYSTEM_EFI_APPLICATION:
+               loaded_image_info->image_code_type = EFI_LOADER_CODE;
+               loaded_image_info->image_data_type = EFI_LOADER_DATA;
+               break;
+       case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
+               loaded_image_info->image_code_type = EFI_BOOT_SERVICES_CODE;
+               loaded_image_info->image_data_type = EFI_BOOT_SERVICES_DATA;
+               break;
+       case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
+       case IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
+               loaded_image_info->image_code_type = EFI_RUNTIME_SERVICES_CODE;
+               loaded_image_info->image_data_type = EFI_RUNTIME_SERVICES_DATA;
+               break;
+       default:
+               printf("%s: invalid image type: %u\n", __func__, image_type);
+               break;
+       }
+
        /* Load sections into RAM */
        for (i = num_sections - 1; i >= 0; i--) {
                IMAGE_SECTION_HEADER *sec = &sections[i];
index 9e079f1fa3a66cc301cd1bf039b7896f97f473f4..d47759e08edc62104db13b0c4cef4ae9234abf82 100644 (file)
@@ -43,7 +43,7 @@ void *efi_bounce_buffer;
  */
 struct efi_pool_allocation {
        u64 num_pages;
-       char data[];
+       char data[] __aligned(ARCH_DMA_MINALIGN);
 };
 
 /*
@@ -356,7 +356,8 @@ efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
 {
        efi_status_t r;
        efi_physical_addr_t t;
-       u64 num_pages = (size + sizeof(u64) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+       u64 num_pages = (size + sizeof(struct efi_pool_allocation) +
+                        EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
 
        if (size == 0) {
                *buffer = NULL;
index 0b949d86e8d5386dfa14c51dd30806994a40d51b..91f1e4a69e15aad0c79e50ad9edbe6473e8ae7ae 100644 (file)
@@ -26,9 +26,6 @@ struct efi_net_obj {
        /* EFI Interface callback struct for network */
        struct efi_simple_network net;
        struct efi_simple_network_mode net_mode;
-       /* Device path to the network adapter */
-       struct efi_device_path_mac_addr dp_mac;
-       struct efi_device_path_file_path dp_end;
        /* PXE struct to transmit dhcp data */
        struct efi_pxe pxe;
        struct efi_pxe_mode pxe_mode;
@@ -210,19 +207,9 @@ void efi_net_set_dhcp_ack(void *pkt, int len)
 }
 
 /* This gets called from do_bootefi_exec(). */
-int efi_net_register(void **handle)
+int efi_net_register(void)
 {
        struct efi_net_obj *netobj;
-       struct efi_device_path_mac_addr dp_net = {
-               .dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE,
-               .dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR,
-               .dp.length = sizeof(dp_net),
-       };
-       struct efi_device_path_file_path dp_end = {
-               .dp.type = DEVICE_PATH_TYPE_END,
-               .dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
-               .dp.length = sizeof(dp_end),
-       };
 
        if (!eth_get_dev()) {
                /* No eth device active, don't expose any */
@@ -236,7 +223,8 @@ int efi_net_register(void **handle)
        netobj->parent.protocols[0].guid = &efi_net_guid;
        netobj->parent.protocols[0].protocol_interface = &netobj->net;
        netobj->parent.protocols[1].guid = &efi_guid_device_path;
-       netobj->parent.protocols[1].protocol_interface = &netobj->dp_mac;
+       netobj->parent.protocols[1].protocol_interface =
+               efi_dp_from_eth();
        netobj->parent.protocols[2].guid = &efi_pxe_guid;
        netobj->parent.protocols[2].protocol_interface = &netobj->pxe;
        netobj->parent.handle = &netobj->net;
@@ -255,9 +243,6 @@ int efi_net_register(void **handle)
        netobj->net.receive = efi_net_receive;
        netobj->net.mode = &netobj->net_mode;
        netobj->net_mode.state = EFI_NETWORK_STARTED;
-       netobj->dp_mac = dp_net;
-       netobj->dp_end = dp_end;
-       memcpy(netobj->dp_mac.mac.addr, eth_get_ethaddr(), 6);
        memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6);
        netobj->net_mode.max_packet_size = PKTSIZE;
 
@@ -268,8 +253,5 @@ int efi_net_register(void **handle)
        /* Hook net up to the device list */
        list_add_tail(&netobj->parent.link, &efi_obj_list);
 
-       if (handle)
-               *handle = &netobj->net;
-
        return 0;
 }
index ad7f3754bd0970b5209f756d5f1d7ce4883e4587..8104e08c466ca1853bcc6461cb696c99b15814b7 100644 (file)
@@ -184,7 +184,16 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
                /* Clean up system table */
                .ptr = &systab.boottime,
                .patchto = NULL,
-       },
+       }, {
+               .ptr = &efi_runtime_services.get_variable,
+               .patchto = &efi_device_error,
+       }, {
+               .ptr = &efi_runtime_services.get_next_variable,
+               .patchto = &efi_device_error,
+       }, {
+               .ptr = &efi_runtime_services.set_variable,
+               .patchto = &efi_device_error,
+       }
 };
 
 static bool efi_runtime_tobedetached(void *p)
@@ -243,7 +252,8 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map)
 
                /* Check if the relocation is inside bounds */
                if (map && ((newaddr < map->virtual_start) ||
-                   newaddr > (map->virtual_start + (map->num_pages << 12)))) {
+                   newaddr > (map->virtual_start +
+                             (map->num_pages << EFI_PAGE_SHIFT)))) {
                        if (!efi_runtime_tobedetached(p))
                                printf("U-Boot EFI: Relocation at %p is out of "
                                       "range (%lx)\n", p, newaddr);
@@ -269,7 +279,8 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
                        uint32_t descriptor_version,
                        struct efi_mem_desc *virtmap)
 {
-       ulong runtime_start = (ulong)&__efi_runtime_start & ~0xfffULL;
+       ulong runtime_start = (ulong)&__efi_runtime_start &
+                             ~(ulong)EFI_PAGE_MASK;
        int n = memory_map_size / descriptor_size;
        int i;
 
@@ -382,9 +393,9 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
        .set_wakeup_time = (void *)&efi_unimplemented,
        .set_virtual_address_map = &efi_set_virtual_address_map,
        .convert_pointer = (void *)&efi_invalid_parameter,
-       .get_variable = (void *)&efi_device_error,
-       .get_next_variable = (void *)&efi_device_error,
-       .set_variable = (void *)&efi_device_error,
+       .get_variable = efi_get_variable,
+       .get_next_variable = efi_get_next_variable,
+       .set_variable = efi_set_variable,
        .get_next_high_mono_count = (void *)&efi_device_error,
        .reset_system = &efi_reset_system_boottime,
 };
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
new file mode 100644 (file)
index 0000000..6c177da
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ *  EFI utils
+ *
+ *  Copyright (c) 2017 Rob Clark
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <malloc.h>
+#include <charset.h>
+#include <efi_loader.h>
+
+#define READ_ONLY BIT(31)
+
+/*
+ * Mapping between EFI variables and u-boot variables:
+ *
+ *   efi_$guid_$varname = {attributes}(type)value
+ *
+ * For example:
+ *
+ *   efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=
+ *      "{ro,boot,run}(blob)0000000000000000"
+ *   efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=
+ *      "(blob)00010000"
+ *
+ * The attributes are a comma separated list of these possible
+ * attributes:
+ *
+ *   + ro   - read-only
+ *   + boot - boot-services access
+ *   + run  - runtime access
+ *
+ * NOTE: with current implementation, no variables are available after
+ * ExitBootServices, and all are persisted (if possible).
+ *
+ * If not specified, the attributes default to "{boot}".
+ *
+ * The required type is one of:
+ *
+ *   + utf8 - raw utf8 string
+ *   + blob - arbitrary length hex string
+ *
+ * Maybe a utf16 type would be useful to for a string value to be auto
+ * converted to utf16?
+ */
+
+#define MAX_VAR_NAME 31
+#define MAX_NATIVE_VAR_NAME \
+       (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx_") + \
+               (MAX_VAR_NAME * MAX_UTF8_PER_UTF16))
+
+static int hex(unsigned char ch)
+{
+       if (ch >= 'a' && ch <= 'f')
+               return ch-'a'+10;
+       if (ch >= '0' && ch <= '9')
+               return ch-'0';
+       if (ch >= 'A' && ch <= 'F')
+               return ch-'A'+10;
+       return -1;
+}
+
+static const char *hex2mem(u8 *mem, const char *hexstr, int count)
+{
+       memset(mem, 0, count/2);
+
+       do {
+               int nibble;
+
+               *mem = 0;
+
+               if (!count || !*hexstr)
+                       break;
+
+               nibble = hex(*hexstr);
+               if (nibble < 0)
+                       break;
+
+               *mem = nibble;
+               count--;
+               hexstr++;
+
+               if (!count || !*hexstr)
+                       break;
+
+               nibble = hex(*hexstr);
+               if (nibble < 0)
+                       break;
+
+               *mem = (*mem << 4) | nibble;
+               count--;
+               hexstr++;
+               mem++;
+
+       } while (1);
+
+       if (*hexstr)
+               return hexstr;
+
+       return NULL;
+}
+
+static char *mem2hex(char *hexstr, const u8 *mem, int count)
+{
+       static const char hexchars[] = "0123456789abcdef";
+
+       while (count-- > 0) {
+               u8 ch = *mem++;
+               *hexstr++ = hexchars[ch >> 4];
+               *hexstr++ = hexchars[ch & 0xf];
+       }
+
+       return hexstr;
+}
+
+static efi_status_t efi_to_native(char *native, s16 *variable_name,
+               efi_guid_t *vendor)
+{
+       size_t len;
+
+       len = utf16_strlen((u16 *)variable_name);
+       if (len >= MAX_VAR_NAME)
+               return EFI_DEVICE_ERROR;
+
+       native += sprintf(native, "efi_%pUl_", vendor);
+       native  = (char *)utf16_to_utf8((u8 *)native, (u16 *)variable_name, len);
+       *native = '\0';
+
+       return EFI_SUCCESS;
+}
+
+static const char *prefix(const char *str, const char *prefix)
+{
+       size_t n = strlen(prefix);
+       if (!strncmp(prefix, str, n))
+               return str + n;
+       return NULL;
+}
+
+/* parse attributes part of variable value, if present: */
+static const char *parse_attr(const char *str, u32 *attrp)
+{
+       u32 attr = 0;
+       char sep = '{';
+
+       if (*str != '{') {
+               *attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS;
+               return str;
+       }
+
+       while (*str == sep) {
+               const char *s;
+
+               str++;
+
+               if ((s = prefix(str, "ro"))) {
+                       attr |= READ_ONLY;
+               } else if ((s = prefix(str, "boot"))) {
+                       attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
+               } else if ((s = prefix(str, "run"))) {
+                       attr |= EFI_VARIABLE_RUNTIME_ACCESS;
+               } else {
+                       printf("invalid attribute: %s\n", str);
+                       break;
+               }
+
+               str = s;
+               sep = ',';
+       }
+
+       str++;
+
+       *attrp = attr;
+
+       return str;
+}
+
+/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetVariable.28.29 */
+efi_status_t EFIAPI efi_get_variable(s16 *variable_name,
+               efi_guid_t *vendor, u32 *attributes,
+               unsigned long *data_size, void *data)
+{
+       char native_name[MAX_NATIVE_VAR_NAME + 1];
+       efi_status_t ret;
+       unsigned long in_size;
+       const char *val, *s;
+       u32 attr;
+
+       EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
+                 data_size, data);
+
+       if (!variable_name || !vendor || !data_size)
+               return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+       ret = efi_to_native(native_name, variable_name, vendor);
+       if (ret)
+               return EFI_EXIT(ret);
+
+       debug("%s: get '%s'\n", __func__, native_name);
+
+       val = env_get(native_name);
+       if (!val)
+               return EFI_EXIT(EFI_NOT_FOUND);
+
+       val = parse_attr(val, &attr);
+
+       in_size = *data_size;
+
+       if ((s = prefix(val, "(blob)"))) {
+               unsigned len = strlen(s);
+
+               /* two characters per byte: */
+               len = DIV_ROUND_UP(len, 2);
+               *data_size = len;
+
+               if (in_size < len)
+                       return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+
+               if (!data)
+                       return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+               if (hex2mem(data, s, len * 2))
+                       return EFI_EXIT(EFI_DEVICE_ERROR);
+
+               debug("%s: got value: \"%s\"\n", __func__, s);
+       } else if ((s = prefix(val, "(utf8)"))) {
+               unsigned len = strlen(s) + 1;
+
+               *data_size = len;
+
+               if (in_size < len)
+                       return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+
+               if (!data)
+                       return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+               memcpy(data, s, len);
+               ((char *)data)[len] = '\0';
+
+               debug("%s: got value: \"%s\"\n", __func__, (char *)data);
+       } else {
+               debug("%s: invalid value: '%s'\n", __func__, val);
+               return EFI_EXIT(EFI_DEVICE_ERROR);
+       }
+
+       if (attributes)
+               *attributes = attr & EFI_VARIABLE_MASK;
+
+       return EFI_EXIT(EFI_SUCCESS);
+}
+
+/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetNextVariableName.28.29 */
+efi_status_t EFIAPI efi_get_next_variable(
+               unsigned long *variable_name_size,
+               s16 *variable_name, efi_guid_t *vendor)
+{
+       EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
+
+       return EFI_EXIT(EFI_DEVICE_ERROR);
+}
+
+/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVariable.28.29 */
+efi_status_t EFIAPI efi_set_variable(s16 *variable_name,
+               efi_guid_t *vendor, u32 attributes,
+               unsigned long data_size, void *data)
+{
+       char native_name[MAX_NATIVE_VAR_NAME + 1];
+       efi_status_t ret = EFI_SUCCESS;
+       char *val, *s;
+       u32 attr;
+
+       EFI_ENTRY("\"%ls\" %pUl %x %lu %p", variable_name, vendor, attributes,
+                 data_size, data);
+
+       if (!variable_name || !vendor)
+               return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+       ret = efi_to_native(native_name, variable_name, vendor);
+       if (ret)
+               return EFI_EXIT(ret);
+
+#define ACCESS_ATTR (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)
+
+       if ((data_size == 0) || !(attributes & ACCESS_ATTR)) {
+               /* delete the variable: */
+               env_set(native_name, NULL);
+               return EFI_EXIT(EFI_SUCCESS);
+       }
+
+       val = env_get(native_name);
+       if (val) {
+               parse_attr(val, &attr);
+
+               if (attr & READ_ONLY)
+                       return EFI_EXIT(EFI_WRITE_PROTECTED);
+       }
+
+       val = malloc(2 * data_size + strlen("{ro,run,boot}(blob)") + 1);
+       if (!val)
+               return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+       s = val;
+
+       /* store attributes: */
+       attributes &= (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS);
+       s += sprintf(s, "{");
+       while (attributes) {
+               u32 attr = 1 << (ffs(attributes) - 1);
+
+               if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS)
+                       s += sprintf(s, "boot");
+               else if (attr == EFI_VARIABLE_RUNTIME_ACCESS)
+                       s += sprintf(s, "run");
+
+               attributes &= ~attr;
+               if (attributes)
+                       s += sprintf(s, ",");
+       }
+       s += sprintf(s, "}");
+
+       /* store payload: */
+       s += sprintf(s, "(blob)");
+       s = mem2hex(s, data, data_size);
+       *s = '\0';
+
+       debug("%s: setting: %s=%s\n", __func__, native_name, val);
+
+       if (env_set(native_name, val))
+               ret = EFI_DEVICE_ERROR;
+
+       free(val);
+
+       return EFI_EXIT(ret);
+}
diff --git a/lib/efi_selftest/Kconfig b/lib/efi_selftest/Kconfig
new file mode 100644 (file)
index 0000000..3b5f3a1
--- /dev/null
@@ -0,0 +1,7 @@
+config CMD_BOOTEFI_SELFTEST
+       bool "Allow booting an EFI efi_selftest"
+       depends on CMD_BOOTEFI
+       help
+         This adds an EFI test application to U-Boot that can be executed
+         with the 'bootefi selftest' command. It provides extended tests of
+         the EFI API implementation.
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
new file mode 100644 (file)
index 0000000..30f1960
--- /dev/null
@@ -0,0 +1,26 @@
+:
+# (C) Copyright 2017, Heinrich Schuchardt <xypron.glpk@gmx.de>
+#
+#  SPDX-License-Identifier:     GPL-2.0+
+#
+
+# This file only gets included with CONFIG_EFI_LOADER set, so all
+# object inclusion implicitly depends on it
+
+CFLAGS_efi_selftest.o := $(CFLAGS_EFI)
+CFLAGS_REMOVE_efi_selftest.o := $(CFLAGS_NON_EFI)
+CFLAGS_efi_selftest_console.o := $(CFLAGS_EFI)
+CFLAGS_REMOVE_efi_selftest_console.o := $(CFLAGS_NON_EFI)
+CFLAGS_efi_selftest_events.o := $(CFLAGS_EFI)
+CFLAGS_REMOVE_efi_selftest_events.o := $(CFLAGS_NON_EFI)
+CFLAGS_efi_selftest_exitbootservices.o := $(CFLAGS_EFI)
+CFLAGS_REMOVE_efi_selftest_exitbootservices.o := $(CFLAGS_NON_EFI)
+CFLAGS_efi_selftest_tpl.o := $(CFLAGS_EFI)
+CFLAGS_REMOVE_efi_selftest_tpl.o := $(CFLAGS_NON_EFI)
+
+obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += \
+efi_selftest.o \
+efi_selftest_console.o \
+efi_selftest_events.o \
+efi_selftest_exitbootservices.o \
+efi_selftest_tpl.o
diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c
new file mode 100644 (file)
index 0000000..efec832
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * EFI efi_selftest
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <efi_selftest.h>
+#include <vsprintf.h>
+
+static const struct efi_system_table *systable;
+static const struct efi_boot_services *boottime;
+static const struct efi_runtime_services *runtime;
+static efi_handle_t handle;
+static u16 reset_message[] = L"Selftest completed";
+
+/*
+ * Exit the boot services.
+ *
+ * The size of the memory map is determined.
+ * Pool memory is allocated to copy the memory map.
+ * The memory amp is copied and the map key is obtained.
+ * The map key is used to exit the boot services.
+ */
+void efi_st_exit_boot_services(void)
+{
+       unsigned long  map_size = 0;
+       unsigned long  map_key;
+       unsigned long desc_size;
+       u32 desc_version;
+       efi_status_t ret;
+       struct efi_mem_desc *memory_map;
+
+       ret = boottime->get_memory_map(&map_size, NULL, &map_key, &desc_size,
+                                      &desc_version);
+       if (ret != EFI_BUFFER_TOO_SMALL) {
+               efi_st_printf("ERROR: GetMemoryMap did not return "
+                             "EFI_BUFFER_TOO_SMALL\n");
+               return;
+       }
+       /* Allocate extra space for newly allocated memory */
+       map_size += sizeof(struct efi_mem_desc);
+       ret = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
+                                     (void **)&memory_map);
+       if (ret != EFI_SUCCESS) {
+               efi_st_printf("ERROR: AllocatePool did not return "
+                             "EFI_SUCCESS\n");
+               return;
+       }
+       ret = boottime->get_memory_map(&map_size, memory_map, &map_key,
+                                      &desc_size, &desc_version);
+       if (ret != EFI_SUCCESS) {
+               efi_st_printf("ERROR: GetMemoryMap did not return "
+                             "EFI_SUCCESS\n");
+               return;
+       }
+       ret = boottime->exit_boot_services(handle, map_key);
+       if (ret != EFI_SUCCESS) {
+               efi_st_printf("ERROR: ExitBootServices did not return "
+                             "EFI_SUCCESS\n");
+               return;
+       }
+       efi_st_printf("\nBoot services terminated\n");
+}
+
+/*
+ * Set up a test.
+ *
+ * @test       the test to be executed
+ * @failures   counter that will be incremented if a failure occurs
+ */
+static int setup(struct efi_unit_test *test, unsigned int *failures)
+{
+       int ret;
+
+       if (!test->setup)
+               return 0;
+       efi_st_printf("\nSetting up '%s'\n", test->name);
+       ret = test->setup(handle, systable);
+       if (ret) {
+               efi_st_printf("ERROR: Setting up '%s' failed\n", test->name);
+               ++*failures;
+       } else {
+               efi_st_printf("Setting up '%s' succeeded\n", test->name);
+       }
+       return ret;
+}
+
+/*
+ * Execute a test.
+ *
+ * @test       the test to be executed
+ * @failures   counter that will be incremented if a failure occurs
+ */
+static int execute(struct efi_unit_test *test, unsigned int *failures)
+{
+       int ret;
+
+       if (!test->execute)
+               return 0;
+       efi_st_printf("\nExecuting '%s'\n", test->name);
+       ret = test->execute();
+       if (ret) {
+               efi_st_printf("ERROR: Executing '%s' failed\n", test->name);
+               ++*failures;
+       } else {
+               efi_st_printf("Executing '%s' succeeded\n", test->name);
+       }
+       return ret;
+}
+
+/*
+ * Tear down a test.
+ *
+ * @test       the test to be torn down
+ * @failures   counter that will be incremented if a failure occurs
+ */
+static int teardown(struct efi_unit_test *test, unsigned int *failures)
+{
+       int ret;
+
+       if (!test->teardown)
+               return 0;
+       efi_st_printf("\nTearing down '%s'\n", test->name);
+       ret = test->teardown();
+       if (ret) {
+               efi_st_printf("ERROR: Tearing down '%s' failed\n", test->name);
+               ++*failures;
+       } else {
+               efi_st_printf("Tearing down '%s' succeeded\n", test->name);
+       }
+       return ret;
+}
+
+/*
+ * Execute selftest of the EFI API
+ *
+ * This is the main entry point of the EFI selftest application.
+ *
+ * All tests use a driver model and are run in three phases:
+ * setup, execute, teardown.
+ *
+ * A test may be setup and executed at boottime,
+ * it may be setup at boottime and executed at runtime,
+ * or it may be setup and executed at runtime.
+ *
+ * After executing all tests the system is reset.
+ *
+ * @image_handle:      handle of the loaded EFI image
+ * @systab:            EFI system table
+ */
+efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
+                                struct efi_system_table *systab)
+{
+       struct efi_unit_test *test;
+       unsigned int failures = 0;
+
+       systable = systab;
+       boottime = systable->boottime;
+       runtime = systable->runtime;
+       handle = image_handle;
+       con_out = systable->con_out;
+       con_in = systable->con_in;
+
+       efi_st_printf("\nTesting EFI API implementation\n");
+
+       efi_st_printf("\nNumber of tests to execute: %u\n",
+                     ll_entry_count(struct efi_unit_test, efi_unit_test));
+
+       /* Execute boottime tests */
+       for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+            test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+               if (test->phase == EFI_EXECUTE_BEFORE_BOOTTIME_EXIT) {
+                       setup(test, &failures);
+                       execute(test, &failures);
+                       teardown(test, &failures);
+               }
+       }
+
+       /* Execute mixed tests */
+       for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+            test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+               if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT)
+                       setup(test, &failures);
+       }
+
+       efi_st_exit_boot_services();
+
+       for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+            test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+               if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT) {
+                       execute(test, &failures);
+                       teardown(test, &failures);
+               }
+       }
+
+       /* Execute runtime tests */
+       for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+            test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+               if (test->phase == EFI_SETUP_AFTER_BOOTTIME_EXIT) {
+                       setup(test, &failures);
+                       execute(test, &failures);
+                       teardown(test, &failures);
+               }
+       }
+
+       /* Give feedback */
+       efi_st_printf("\nSummary: %u failures\n\n", failures);
+
+       /* Reset system */
+       efi_st_printf("Preparing for reset. Press any key.\n");
+       efi_st_get_key();
+       runtime->reset_system(EFI_RESET_WARM, EFI_NOT_READY,
+                             sizeof(reset_message), reset_message);
+       efi_st_printf("\nERROR: reset failed.\n");
+
+       return EFI_UNSUPPORTED;
+}
diff --git a/lib/efi_selftest/efi_selftest_console.c b/lib/efi_selftest/efi_selftest_console.c
new file mode 100644 (file)
index 0000000..7b5b724
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * EFI efi_selftest
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <efi_selftest.h>
+#include <vsprintf.h>
+
+struct efi_simple_text_output_protocol *con_out;
+struct efi_simple_input_interface *con_in;
+
+/*
+ * Print a pointer to an u16 string
+ *
+ * @pointer: pointer
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+static void pointer(void *pointer, u16 **buf)
+{
+       int i;
+       u16 c;
+       uintptr_t p = (uintptr_t)pointer;
+       u16 *pos = *buf;
+
+       for (i = 8 * sizeof(p) - 4; i >= 0; i -= 4) {
+               c = (p >> i) & 0x0f;
+               c += '0';
+               if (c > '9')
+                       c += 'a' - '9' - 1;
+               *pos++ = c;
+       }
+       *pos = 0;
+       *buf = pos;
+}
+
+/*
+ * Print an unsigned 32bit value as decimal number to an u16 string
+ *
+ * @value: value to be printed
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+static void uint2dec(u32 value, u16 **buf)
+{
+       u16 *pos = *buf;
+       int i;
+       u16 c;
+       u64 f;
+
+       /*
+        * Increment by .5 and multiply with
+        * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
+        * to move the first digit to bit 60-63.
+        */
+       f = 0x225C17D0;
+       f += (0x9B5A52DULL * value) >> 28;
+       f += 0x44B82FA0ULL * value;
+
+       for (i = 0; i < 10; ++i) {
+               /* Write current digit */
+               c = f >> 60;
+               if (c || pos != *buf)
+                       *pos++ = c + '0';
+               /* Eliminate current digit */
+               f &= 0xfffffffffffffff;
+               /* Get next digit */
+               f *= 0xaULL;
+       }
+       if (pos == *buf)
+               *pos++ = '0';
+       *pos = 0;
+       *buf = pos;
+}
+
+/*
+ * Print a signed 32bit value as decimal number to an u16 string
+ *
+ * @value: value to be printed
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+static void int2dec(s32 value, u16 **buf)
+{
+       u32 u;
+       u16 *pos = *buf;
+
+       if (value < 0) {
+               *pos++ = '-';
+               u = -value;
+       } else {
+               u = value;
+       }
+       uint2dec(u, &pos);
+       *buf = pos;
+}
+
+/*
+ * Print a formatted string to the EFI console
+ *
+ * @fmt: format string
+ * @...: optional arguments
+ */
+void efi_st_printf(const char *fmt, ...)
+{
+       va_list args;
+       u16 buf[160];
+       const char *c;
+       u16 *pos = buf;
+       const char *s;
+
+       va_start(args, fmt);
+
+       c = fmt;
+       for (; *c; ++c) {
+               switch (*c) {
+               case '\\':
+                       ++c;
+                       switch (*c) {
+                       case '\0':
+                               --c;
+                               break;
+                       case 'n':
+                               *pos++ = '\n';
+                               break;
+                       case 'r':
+                               *pos++ = '\r';
+                               break;
+                       case 't':
+                               *pos++ = '\t';
+                               break;
+                       default:
+                               *pos++ = *c;
+                       }
+                       break;
+               case '%':
+                       ++c;
+                       switch (*c) {
+                       case '\0':
+                               --c;
+                               break;
+                       case 'd':
+                               int2dec(va_arg(args, s32), &pos);
+                               break;
+                       case 'p':
+                               pointer(va_arg(args, void*), &pos);
+                               break;
+                       case 's':
+                               s = va_arg(args, const char *);
+                               for (; *s; ++s)
+                                       *pos++ = *s;
+                               break;
+                       case 'u':
+                               uint2dec(va_arg(args, u32), &pos);
+                               break;
+                       default:
+                               break;
+                       }
+                       break;
+               default:
+                       *pos++ = *c;
+               }
+       }
+       va_end(args);
+       *pos = 0;
+       con_out->output_string(con_out, buf);
+}
+
+/*
+ * Reads an Unicode character from the input device.
+ *
+ * @return: Unicode character
+ */
+u16 efi_st_get_key(void)
+{
+       struct efi_input_key input_key;
+       efi_status_t ret;
+
+       /* Wait for next key */
+       do {
+               ret = con_in->read_key_stroke(con_in, &input_key);
+       } while (ret == EFI_NOT_READY);
+       return input_key.unicode_char;
+}
diff --git a/lib/efi_selftest/efi_selftest_events.c b/lib/efi_selftest/efi_selftest_events.c
new file mode 100644 (file)
index 0000000..c4f6695
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * efi_selftest_events
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This unit test uses timer events to check the implementation
+ * of the following boottime services:
+ * CreateEvent, CloseEvent, WaitForEvent, CheckEvent, SetTimer.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_event *event_notify;
+static struct efi_event *event_wait;
+static unsigned int counter;
+static struct efi_boot_services *boottime;
+
+/*
+ * Notification function, increments a counter.
+ *
+ * @event      notified event
+ * @context    pointer to the counter
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+       if (!context)
+               return;
+       ++*(unsigned int *)context;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create two timer events.
+ * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT.
+ *
+ * @handle:    handle of the loaded image
+ * @systable:  system table
+ */
+static int setup(const efi_handle_t handle,
+                const struct efi_system_table *systable)
+{
+       efi_status_t ret;
+
+       boottime = systable->boottime;
+
+       ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL,
+                                    TPL_CALLBACK, notify, (void *)&counter,
+                                    &event_notify);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not create event\n");
+               return 1;
+       }
+       ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT,
+                                    TPL_CALLBACK, notify, NULL, &event_wait);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not create event\n");
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Close the events created in setup.
+ */
+static int teardown(void)
+{
+       efi_status_t ret;
+
+       if (event_notify) {
+               ret = boottime->close_event(event_notify);
+               event_notify = NULL;
+               if (ret != EFI_SUCCESS) {
+                       efi_st_error("could not close event\n");
+                       return 1;
+               }
+       }
+       if (event_wait) {
+               ret = boottime->close_event(event_wait);
+               event_wait = NULL;
+               if (ret != EFI_SUCCESS) {
+                       efi_st_error("could not close event\n");
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Run a 10 ms periodic timer and check that it is called 10 times
+ * while waiting for 100 ms single shot timer.
+ *
+ * Run a 100 ms single shot timer and check that it is called once
+ * while waiting for 100 ms periodic timer for two periods.
+ */
+static int execute(void)
+{
+       unsigned long index;
+       efi_status_t ret;
+
+       /* Set 10 ms timer */
+       counter = 0;
+       ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not set timer\n");
+               return 1;
+       }
+       /* Set 100 ms timer */
+       ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not set timer\n");
+               return 1;
+       }
+
+       index = 5;
+       ret = boottime->wait_for_event(1, &event_wait, &index);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not wait for event\n");
+               return 1;
+       }
+       ret = boottime->check_event(event_wait);
+       if (ret != EFI_NOT_READY) {
+               efi_st_error("Signaled state was not cleared.\n");
+               efi_st_printf("ret = %u\n", (unsigned int)ret);
+               return 1;
+       }
+       if (index != 0) {
+               efi_st_error("WaitForEvent returned wrong index\n");
+               return 1;
+       }
+       efi_st_printf("Counter periodic: %u\n", counter);
+       if (counter < 8 || counter > 12) {
+               efi_st_error("Incorrect timing of events\n");
+               return 1;
+       }
+       ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0);
+       if (index != 0) {
+               efi_st_error("Could not cancel timer\n");
+               return 1;
+       }
+       /* Set 10 ms timer */
+       counter = 0;
+       ret = boottime->set_timer(event_notify, EFI_TIMER_RELATIVE, 100000);
+       if (index != 0) {
+               efi_st_error("Could not set timer\n");
+               return 1;
+       }
+       /* Set 100 ms timer */
+       ret = boottime->set_timer(event_wait, EFI_TIMER_PERIODIC, 1000000);
+       if (index != 0) {
+               efi_st_error("Could not set timer\n");
+               return 1;
+       }
+       ret = boottime->wait_for_event(1, &event_wait, &index);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not wait for event\n");
+               return 1;
+       }
+       efi_st_printf("Counter single shot: %u\n", counter);
+       if (counter != 1) {
+               efi_st_error("Single shot timer failed\n");
+               return 1;
+       }
+       ret = boottime->wait_for_event(1, &event_wait, &index);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not wait for event\n");
+               return 1;
+       }
+       efi_st_printf("Stopped counter: %u\n", counter);
+       if (counter != 1) {
+               efi_st_error("Stopped timer fired\n");
+               return 1;
+       }
+       ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0);
+       if (index != 0) {
+               efi_st_error("Could not cancel timer\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+EFI_UNIT_TEST(events) = {
+       .name = "event services",
+       .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+       .setup = setup,
+       .execute = execute,
+       .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_exitbootservices.c b/lib/efi_selftest/efi_selftest_exitbootservices.c
new file mode 100644 (file)
index 0000000..60271e6
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * efi_selftest_events
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This unit test checks that the notification function of an
+ * EVT_SIGNAL_EXIT_BOOT_SERVICES event is called exactly once.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_boot_services *boottime;
+static struct efi_event *event_notify;
+static unsigned int counter;
+
+/*
+ * Notification function, increments a counter.
+ *
+ * @event      notified event
+ * @context    pointer to the counter
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+       if (!context)
+               return;
+       ++*(unsigned int *)context;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create an EVT_SIGNAL_EXIT_BOOT_SERVICES event.
+ *
+ * @handle:    handle of the loaded image
+ * @systable:  system table
+ */
+static int setup(const efi_handle_t handle,
+                const struct efi_system_table *systable)
+{
+       efi_status_t ret;
+
+       boottime = systable->boottime;
+
+       counter = 0;
+       ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES,
+                                    TPL_CALLBACK, notify, (void *)&counter,
+                                    &event_notify);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not create event\n");
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Close the event created in setup.
+ */
+static int teardown(void)
+{
+       efi_status_t ret;
+
+       if (event_notify) {
+               ret = boottime->close_event(event_notify);
+               event_notify = NULL;
+               if (ret != EFI_SUCCESS) {
+                       efi_st_error("could not close event\n");
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Check that the notification function of the EVT_SIGNAL_EXIT_BOOT_SERVICES
+ * event has been called.
+ *
+ * Call ExitBootServices again and check that the notification function is
+ * not called again.
+ */
+static int execute(void)
+{
+       if (counter != 1) {
+               efi_st_error("ExitBootServices was not notified");
+               return 1;
+       }
+       efi_st_exit_boot_services();
+       if (counter != 1) {
+               efi_st_error("ExitBootServices was notified twice");
+               return 1;
+       }
+       return 0;
+}
+
+EFI_UNIT_TEST(exitbootservices) = {
+       .name = "ExitBootServices",
+       .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+       .setup = setup,
+       .execute = execute,
+       .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_tpl.c b/lib/efi_selftest/efi_selftest_tpl.c
new file mode 100644 (file)
index 0000000..90ace0f
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * efi_selftest_events
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This unit test uses timer events to check the handling of
+ * task priority levels.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_event *event_notify;
+static struct efi_event *event_wait;
+static unsigned int counter;
+static struct efi_boot_services *boottime;
+
+/*
+ * Notification function, increments a counter.
+ *
+ * @event      notified event
+ * @context    pointer to the counter
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+       if (!context)
+               return;
+       ++*(unsigned int *)context;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create two timer events.
+ * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT.
+ *
+ * @handle:    handle of the loaded image
+ * @systable:  system table
+ */
+static int setup(const efi_handle_t handle,
+                const struct efi_system_table *systable)
+{
+       efi_status_t ret;
+
+       boottime = systable->boottime;
+
+       ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL,
+                                    TPL_CALLBACK, notify, (void *)&counter,
+                                    &event_notify);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not create event\n");
+               return 1;
+       }
+       ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT,
+                                    TPL_HIGH_LEVEL, notify, NULL, &event_wait);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("could not create event\n");
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Close the events created in setup.
+ */
+static int teardown(void)
+{
+       efi_status_t ret;
+
+       if (event_notify) {
+               ret = boottime->close_event(event_notify);
+               event_notify = NULL;
+               if (ret != EFI_SUCCESS) {
+                       efi_st_error("could not close event\n");
+                       return 1;
+               }
+       }
+       if (event_wait) {
+               ret = boottime->close_event(event_wait);
+               event_wait = NULL;
+               if (ret != EFI_SUCCESS) {
+                       efi_st_error("could not close event\n");
+                       return 1;
+               }
+       }
+       boottime->restore_tpl(TPL_APPLICATION);
+       return 0;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Run a 10 ms periodic timer and check that it is called 10 times
+ * while waiting for 100 ms single shot timer.
+ *
+ * Raise the TPL level to the level of the 10 ms timer and observe
+ * that the notification function is not called again.
+ *
+ * Lower the TPL level and check that the queued notification
+ * function is called.
+ */
+static int execute(void)
+{
+       unsigned long index;
+       efi_status_t ret;
+       UINTN old_tpl;
+
+       /* Set 10 ms timer */
+       counter = 0;
+       ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not set timer\n");
+               return 1;
+       }
+       /* Set 100 ms timer */
+       ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not set timer\n");
+               return 1;
+       }
+       index = 5;
+       ret = boottime->wait_for_event(1, &event_wait, &index);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not wait for event\n");
+               return 1;
+       }
+       ret = boottime->check_event(event_wait);
+       if (ret != EFI_NOT_READY) {
+               efi_st_error("Signaled state was not cleared.\n");
+               efi_st_printf("ret = %u\n", (unsigned int)ret);
+               return 1;
+       }
+       if (index != 0) {
+               efi_st_error("WaitForEvent returned wrong index\n");
+               return 1;
+       }
+       efi_st_printf("Counter with TPL level TPL_APPLICATION: %u\n", counter);
+       if (counter < 8 || counter > 12) {
+               efi_st_error("Incorrect timing of events\n");
+               return 1;
+       }
+       ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0);
+       if (index != 0) {
+               efi_st_error("Could not cancel timer\n");
+               return 1;
+       }
+       /* Raise TPL level */
+       old_tpl = boottime->raise_tpl(TPL_CALLBACK);
+       if (old_tpl != TPL_APPLICATION) {
+               efi_st_error("Initial TPL level was not TPL_APPLICATION");
+               return 1;
+       }
+       /* Set 10 ms timer */
+       counter = 0;
+       ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
+       if (index != 0) {
+               efi_st_error("Could not set timer\n");
+               return 1;
+       }
+       /* Set 100 ms timer */
+       ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not set timer\n");
+               return 1;
+       }
+       do {
+               ret = boottime->check_event(event_wait);
+       } while (ret == EFI_NOT_READY);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not check event\n");
+               return 1;
+       }
+       efi_st_printf("Counter with TPL level TPL_CALLBACK: %u\n", counter);
+       if (counter != 0) {
+               efi_st_error("Suppressed timer fired\n");
+               return 1;
+       }
+       /* Set 1 ms timer */
+       ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not set timer\n");
+               return 1;
+       }
+       /* Restore the old TPL level */
+       boottime->restore_tpl(TPL_APPLICATION);
+       ret = boottime->wait_for_event(1, &event_wait, &index);
+       if (ret != EFI_SUCCESS) {
+               efi_st_error("Could not wait for event\n");
+               return 1;
+       }
+       efi_st_printf("Counter with TPL level TPL_APPLICATION: %u\n", counter);
+       if (counter < 1) {
+               efi_st_error("Queued timer event did not fire\n");
+               return 1;
+       }
+       ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0);
+       if (index != 0) {
+               efi_st_error("Could not cancel timer\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+EFI_UNIT_TEST(tpl) = {
+       .name = "task priority levels",
+       .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+       .setup = setup,
+       .execute = execute,
+       .teardown = teardown,
+};
index 2a7ed70cf26b3cd8d72d772d1bb1ae6a6c9f5773..861a3dc3f1d301378c8c807bf576bfcfcc437ab4 100644 (file)
@@ -359,20 +359,22 @@ cmd_S_ttf=                                                \
 $(obj)/%.S: $(src)/%.ttf
        $(call cmd,S_ttf)
 
-# EFI Hello World application
+# EFI applications
+# A Makefile target *.efi is built as EFI application.
+# A Makefile target *_efi.S wraps *.efi as built-in EFI application.
 # ---------------------------------------------------------------------------
 
 # Generate an assembly file to wrap the EFI app
-cmd_S_efi=                                             \
-(                                                      \
-       echo '.section .rodata.efi.init,"a"';           \
-       echo '.balign 16';                              \
-       echo '.global __efi_hello_world_begin';         \
-       echo '__efi_hello_world_begin:';                \
-       echo '.incbin "$<" ';                           \
-       echo '__efi_hello_world_end:';                  \
-       echo '.global __efi_hello_world_end';           \
-       echo '.balign 16';                              \
+cmd_S_efi=                                     \
+(                                              \
+       echo '.section .rodata.$*.init,"a"';    \
+       echo '.balign 16';                      \
+       echo '.global __efi_$*_begin';          \
+       echo '__efi_$*_begin:';                 \
+       echo '.incbin "$<" ';                   \
+       echo '__efi_$*_end:';                   \
+       echo '.global __efi_$*_end';            \
+       echo '.balign 16';                      \
 ) > $@
 
 $(obj)/%_efi.S: $(obj)/%.efi
@@ -383,7 +385,7 @@ cmd_efi_objcopy = $(OBJCOPY) -j .header -j .text -j .sdata -j .data -j \
                .dynamic -j .dynsym  -j .rel* -j .rela* -j .reloc \
                $(if $(EFI_TARGET),$(EFI_TARGET),-O binary) $^ $@
 
-$(obj)/%.efi: $(obj)/%.so
+$(obj)/%.efi: $(obj)/%_efi.so
        $(call cmd,efi_objcopy)
 
 quiet_cmd_efi_ld = LD      $@
@@ -392,9 +394,7 @@ cmd_efi_ld = $(LD) -nostdlib -znocombreloc -T $(EFI_LDS_PATH) -shared \
 
 EFI_LDS_PATH = $(srctree)/arch/$(ARCH)/lib/$(EFI_LDS)
 
-$(obj)/helloworld.so: $(EFI_LDS_PATH)
-
-$(obj)/helloworld.so: $(obj)/helloworld.o arch/$(ARCH)/lib/$(EFI_CRT0) \
+$(obj)/%_efi.so: $(obj)/%.o arch/$(ARCH)/lib/$(EFI_CRT0) \
                arch/$(ARCH)/lib/$(EFI_RELOC)
        $(call cmd,efi_ld)
 
diff --git a/scripts/spelling.txt b/scripts/spelling.txt
new file mode 100644 (file)
index 0000000..400ef35
--- /dev/null
@@ -0,0 +1,1217 @@
+# Originally from Debian's Lintian tool. Various false positives have been
+# removed, and various additions have been made as they've been discovered
+# in the kernel source.
+#
+# License: GPLv2
+#
+# The format of each line is:
+# mistake||correction
+#
+abandonning||abandoning
+abigious||ambiguous
+abitrate||arbitrate
+abov||above
+abreviated||abbreviated
+absense||absence
+absolut||absolute
+absoulte||absolute
+acccess||access
+acceess||access
+acceleratoin||acceleration
+accelleration||acceleration
+accesing||accessing
+accesnt||accent
+accessable||accessible
+accesss||access
+accidentaly||accidentally
+accidentually||accidentally
+accoding||according
+accomodate||accommodate
+accomodates||accommodates
+accordign||according
+accoring||according
+accout||account
+accquire||acquire
+accquired||acquired
+accross||across
+acessable||accessible
+acess||access
+achitecture||architecture
+acient||ancient
+acitions||actions
+acitve||active
+acknowldegement||acknowledgment
+acknowledgement||acknowledgment
+ackowledge||acknowledge
+ackowledged||acknowledged
+acording||according
+activete||activate
+actived||activated
+actualy||actually
+acumulating||accumulating
+acumulator||accumulator
+adapater||adapter
+addional||additional
+additionaly||additionally
+addres||address
+adddress||address
+addreses||addresses
+addresss||address
+aditional||additional
+aditionally||additionally
+aditionaly||additionally
+adminstrative||administrative
+adress||address
+adresses||addresses
+adviced||advised
+afecting||affecting
+againt||against
+agaist||against
+albumns||albums
+alegorical||allegorical
+algined||aligned
+algorith||algorithm
+algorithmical||algorithmically
+algoritm||algorithm
+algoritms||algorithms
+algorrithm||algorithm
+algorritm||algorithm
+aligment||alignment
+alignement||alignment
+allign||align
+alligned||aligned
+allocatote||allocate
+allocatrd||allocated
+allocte||allocate
+allpication||application
+alocate||allocate
+alogirhtms||algorithms
+alogrithm||algorithm
+alot||a lot
+alow||allow
+alows||allows
+altough||although
+alue||value
+ambigious||ambiguous
+amoung||among
+amout||amount
+an union||a union
+an user||a user
+an userspace||a userspace
+an one||a one
+analysator||analyzer
+ang||and
+anniversery||anniversary
+annoucement||announcement
+anomolies||anomalies
+anomoly||anomaly
+anway||anyway
+aplication||application
+appearence||appearance
+applicaion||application
+appliction||application
+applictions||applications
+applys||applies
+appplications||applications
+appropiate||appropriate
+appropriatly||appropriately
+approriate||appropriate
+approriately||appropriately
+apropriate||appropriate
+aquainted||acquainted
+aquired||acquired
+aquisition||acquisition
+arbitary||arbitrary
+architechture||architecture
+arguement||argument
+arguements||arguments
+aritmetic||arithmetic
+arne't||aren't
+arraival||arrival
+artifical||artificial
+artillary||artillery
+asign||assign
+asser||assert
+assertation||assertion
+assiged||assigned
+assigment||assignment
+assigments||assignments
+assistent||assistant
+assocation||association
+associcated||associated
+assotiated||associated
+assum||assume
+assumtpion||assumption
+asuming||assuming
+asycronous||asynchronous
+asynchnous||asynchronous
+atomatically||automatically
+atomicly||atomically
+atempt||attempt
+attachement||attachment
+attched||attached
+attemps||attempts
+attemping||attempting
+attruibutes||attributes
+authentification||authentication
+automaticaly||automatically
+automaticly||automatically
+automatize||automate
+automatized||automated
+automatizes||automates
+autonymous||autonomous
+auxillary||auxiliary
+auxilliary||auxiliary
+avaiable||available
+avaible||available
+availabe||available
+availabled||available
+availablity||availability
+availale||available
+availavility||availability
+availble||available
+availiable||available
+avalable||available
+avaliable||available
+aysnc||async
+backgroud||background
+backword||backward
+backwords||backwards
+bahavior||behavior
+bakup||backup
+baloon||balloon
+baloons||balloons
+bandwith||bandwidth
+banlance||balance
+batery||battery
+beacuse||because
+becasue||because
+becomming||becoming
+becuase||because
+beeing||being
+befor||before
+begining||beginning
+beter||better
+betweeen||between
+bianries||binaries
+bitmast||bitmask
+boardcast||broadcast
+borad||board
+boundry||boundary
+brievely||briefly
+broadcat||broadcast
+cacluated||calculated
+caculation||calculation
+calender||calendar
+calle||called
+callibration||calibration
+calucate||calculate
+calulate||calculate
+cancelation||cancellation
+cancle||cancel
+capabilites||capabilities
+capabitilies||capabilities
+capatibilities||capabilities
+capapbilities||capabilities
+carefuly||carefully
+cariage||carriage
+catagory||category
+cehck||check
+challange||challenge
+challanges||challenges
+chanell||channel
+changable||changeable
+chanined||chained
+channle||channel
+channnel||channel
+charachter||character
+charachters||characters
+charactor||character
+charater||character
+charaters||characters
+charcter||character
+chcek||check
+chck||check
+checksuming||checksumming
+childern||children
+childs||children
+chiled||child
+chked||checked
+chnage||change
+chnages||changes
+chnnel||channel
+choosen||chosen
+chouse||chose
+circumvernt||circumvent
+claread||cleared
+clared||cleared
+closeing||closing
+clustred||clustered
+coexistance||coexistence
+collapsable||collapsible
+colorfull||colorful
+comand||command
+comit||commit
+commerical||commercial
+comming||coming
+comminucation||communication
+commited||committed
+commiting||committing
+committ||commit
+commoditiy||commodity
+comsume||consume
+comsumer||consumer
+comsuming||consuming
+compability||compatibility
+compaibility||compatibility
+compatability||compatibility
+compatable||compatible
+compatibiliy||compatibility
+compatibilty||compatibility
+compatiblity||compatibility
+competion||completion
+compilant||compliant
+compleatly||completely
+completition||completion
+completly||completely
+complient||compliant
+componnents||components
+compoment||component
+compres||compress
+compresion||compression
+comression||compression
+comunication||communication
+conbination||combination
+conditionaly||conditionally
+conected||connected
+connecetd||connected
+configuartion||configuration
+configuratoin||configuration
+configuraton||configuration
+configuretion||configuration
+configutation||configuration
+conider||consider
+conjuction||conjunction
+connectinos||connections
+connnection||connection
+connnections||connections
+consistancy||consistency
+consistant||consistent
+containes||contains
+containts||contains
+contaisn||contains
+contant||contact
+contence||contents
+continous||continuous
+continously||continuously
+continueing||continuing
+contraints||constraints
+contol||control
+contoller||controller
+controled||controlled
+controler||controller
+controll||control
+contruction||construction
+contry||country
+conuntry||country
+convertion||conversion
+convertor||converter
+convienient||convenient
+convinient||convenient
+corected||corrected
+correponding||corresponding
+correponds||corresponds
+correspoding||corresponding
+cotrol||control
+cound||could
+couter||counter
+coutner||counter
+cryptocraphic||cryptographic
+cunter||counter
+curently||currently
+cylic||cyclic
+dafault||default
+deafult||default
+deamon||daemon
+decompres||decompress
+decription||description
+dectected||detected
+defailt||default
+defferred||deferred
+definate||definite
+definately||definitely
+defintion||definition
+defintions||definitions
+defualt||default
+defult||default
+deintializing||deinitializing
+deintialize||deinitialize
+deintialized||deinitialized
+deivce||device
+delared||declared
+delare||declare
+delares||declares
+delaring||declaring
+delemiter||delimiter
+demodualtor||demodulator
+demension||dimension
+dependancies||dependencies
+dependancy||dependency
+dependant||dependent
+depreacted||deprecated
+depreacte||deprecate
+desactivate||deactivate
+desciptor||descriptor
+desciptors||descriptors
+descripton||description
+descrition||description
+descritptor||descriptor
+desctiptor||descriptor
+desriptor||descriptor
+desriptors||descriptors
+destionation||destination
+destory||destroy
+destoryed||destroyed
+destorys||destroys
+destroied||destroyed
+detabase||database
+deteced||detected
+develope||develop
+developement||development
+developped||developed
+developpement||development
+developper||developer
+developpment||development
+deveolpment||development
+devided||divided
+deviece||device
+diable||disable
+dictionnary||dictionary
+didnt||didn't
+diferent||different
+differrence||difference
+diffrent||different
+diffrentiate||differentiate
+difinition||definition
+diplay||display
+direectly||directly
+disassocation||disassociation
+disapear||disappear
+disapeared||disappeared
+disappared||disappeared
+disble||disable
+disbled||disabled
+disconnet||disconnect
+discontinous||discontinuous
+dispertion||dispersion
+dissapears||disappears
+distiction||distinction
+docuentation||documentation
+documantation||documentation
+documentaion||documentation
+documment||document
+doesnt||doesn't
+dorp||drop
+dosen||doesn
+downlad||download
+downlads||downloads
+druing||during
+dynmaic||dynamic
+easilly||easily
+ecspecially||especially
+edditable||editable
+editting||editing
+efective||effective
+efficently||efficiently
+ehther||ether
+eigth||eight
+elementry||elementary
+eletronic||electronic
+embeded||embedded
+enabledi||enabled
+enchanced||enhanced
+encorporating||incorporating
+encrupted||encrypted
+encrypiton||encryption
+encryptio||encryption
+endianess||endianness
+enhaced||enhanced
+enlightnment||enlightenment
+entrys||entries
+enocded||encoded
+enterily||entirely
+enviroiment||environment
+enviroment||environment
+environement||environment
+environent||environment
+eqivalent||equivalent
+equiped||equipped
+equivelant||equivalent
+equivilant||equivalent
+eror||error
+estbalishment||establishment
+etsablishment||establishment
+etsbalishment||establishment
+excecutable||executable
+exceded||exceeded
+excellant||excellent
+exeed||exceed
+existance||existence
+existant||existent
+exixt||exist
+exlcude||exclude
+exlcusive||exclusive
+exmaple||example
+expecially||especially
+explicite||explicit
+explicitely||explicitly
+explict||explicit
+explictely||explicitly
+explictly||explicitly
+expresion||expression
+exprimental||experimental
+extened||extended
+extensability||extensibility
+extention||extension
+extracter||extractor
+falied||failed
+faild||failed
+faill||fail
+failied||failed
+faillure||failure
+failue||failure
+failuer||failure
+faireness||fairness
+falied||failed
+faliure||failure
+fallbck||fallback
+familar||familiar
+fatser||faster
+feauture||feature
+feautures||features
+fetaure||feature
+fetaures||features
+fileystem||filesystem
+fimware||firmware
+finanize||finalize
+findn||find
+finilizes||finalizes
+finsih||finish
+flusing||flushing
+folloing||following
+followign||following
+followings||following
+follwing||following
+forseeable||foreseeable
+forse||force
+fortan||fortran
+forwardig||forwarding
+framming||framing
+framwork||framework
+frequncy||frequency
+frome||from
+fucntion||function
+fuction||function
+fuctions||functions
+funcion||function
+functionallity||functionality
+functionaly||functionally
+functionnality||functionality
+functonality||functionality
+funtion||function
+funtions||functions
+furthur||further
+futhermore||furthermore
+futrue||future
+gaurenteed||guaranteed
+generiously||generously
+genereate||generate
+genric||generic
+globel||global
+grabing||grabbing
+grahical||graphical
+grahpical||graphical
+grapic||graphic
+guage||gauge
+guarenteed||guaranteed
+guarentee||guarantee
+halfs||halves
+hander||handler
+handfull||handful
+hanled||handled
+happend||happened
+harware||hardware
+heirarchically||hierarchically
+helpfull||helpful
+hierachy||hierarchy
+hierarchie||hierarchy
+howver||however
+hsould||should
+hypervior||hypervisor
+hypter||hyper
+identidier||identifier
+iligal||illegal
+illigal||illegal
+imblance||imbalance
+immeadiately||immediately
+immedaite||immediate
+immediatelly||immediately
+immediatly||immediately
+immidiate||immediate
+impelentation||implementation
+impementated||implemented
+implemantation||implementation
+implemenation||implementation
+implementaiton||implementation
+implementated||implemented
+implemention||implementation
+implemetation||implementation
+implemntation||implementation
+implentation||implementation
+implmentation||implementation
+implmenting||implementing
+incomming||incoming
+incompatabilities||incompatibilities
+incompatable||incompatible
+inconsistant||inconsistent
+increas||increase
+incrment||increment
+indendation||indentation
+indended||intended
+independant||independent
+independantly||independently
+independed||independent
+indiate||indicate
+indicat||indicate
+inexpect||inexpected
+infomation||information
+informatiom||information
+informations||information
+informtion||information
+infromation||information
+ingore||ignore
+inital||initial
+initalized||initialized
+initalised||initialized
+initalise||initialize
+initalize||initialize
+initation||initiation
+initators||initiators
+initialiazation||initialization
+initializiation||initialization
+initialzed||initialized
+initilization||initialization
+initilize||initialize
+inofficial||unofficial
+insititute||institute
+instal||install
+instanciated||instantiated
+inteface||interface
+integreated||integrated
+integrety||integrity
+integrey||integrity
+intendet||intended
+intented||intended
+interanl||internal
+interchangable||interchangeable
+interferring||interfering
+interger||integer
+intermittant||intermittent
+internel||internal
+interoprability||interoperability
+interrface||interface
+interrrupt||interrupt
+interrup||interrupt
+interrups||interrupts
+interruptted||interrupted
+interupted||interrupted
+interupt||interrupt
+intial||initial
+intialisation||initialisation
+intialised||initialised
+intialise||initialise
+intialization||initialization
+intialized||initialized
+intialize||initialize
+intregral||integral
+intrrupt||interrupt
+intterrupt||interrupt
+intuative||intuitive
+invaid||invalid
+invalde||invalid
+invalide||invalid
+invalud||invalid
+invididual||individual
+invokation||invocation
+invokations||invocations
+irrelevent||irrelevant
+isnt||isn't
+isssue||issue
+iternations||iterations
+itertation||iteration
+itslef||itself
+jave||java
+jeffies||jiffies
+juse||just
+jus||just
+kown||known
+langage||language
+langauage||language
+langauge||language
+langugage||language
+lauch||launch
+layed||laid
+leightweight||lightweight
+lengh||length
+lenght||length
+lenth||length
+lesstiff||lesstif
+libaries||libraries
+libary||library
+librairies||libraries
+libraris||libraries
+licenceing||licencing
+loggging||logging
+loggin||login
+logile||logfile
+loosing||losing
+losted||lost
+machinary||machinery
+maintainance||maintenance
+maintainence||maintenance
+maintan||maintain
+makeing||making
+malplaced||misplaced
+malplace||misplace
+managable||manageable
+managment||management
+mangement||management
+manoeuvering||maneuvering
+mappping||mapping
+mathimatical||mathematical
+mathimatic||mathematic
+mathimatics||mathematics
+maxium||maximum
+mechamism||mechanism
+meetign||meeting
+ment||meant
+mergable||mergeable
+mesage||message
+messags||messages
+messgaes||messages
+messsage||message
+messsages||messages
+micropone||microphone
+microprocesspr||microprocessor
+milliseonds||milliseconds
+minium||minimum
+minimam||minimum
+minumum||minimum
+misalinged||misaligned
+miscelleneous||miscellaneous
+misformed||malformed
+mispelled||misspelled
+mispelt||misspelt
+mising||missing
+missmanaged||mismanaged
+missmatch||mismatch
+miximum||maximum
+mmnemonic||mnemonic
+mnay||many
+modulues||modules
+momery||memory
+memomry||memory
+monochorome||monochrome
+monochromo||monochrome
+monocrome||monochrome
+mopdule||module
+mroe||more
+mulitplied||multiplied
+multidimensionnal||multidimensional
+multple||multiple
+mumber||number
+muticast||multicast
+mutiple||multiple
+mutli||multi
+nams||names
+navagating||navigating
+nead||need
+neccecary||necessary
+neccesary||necessary
+neccessary||necessary
+necesary||necessary
+neded||needed
+negaive||negative
+negoitation||negotiation
+negotation||negotiation
+nerver||never
+nescessary||necessary
+nessessary||necessary
+noticable||noticeable
+notications||notifications
+notifed||notified
+numebr||number
+numner||number
+obtaion||obtain
+occassionally||occasionally
+occationally||occasionally
+occurance||occurrence
+occurances||occurrences
+occured||occurred
+occurence||occurrence
+occure||occurred
+occured||occurred
+occuring||occurring
+offet||offset
+omited||omitted
+omiting||omitting
+omitt||omit
+ommiting||omitting
+ommitted||omitted
+onself||oneself
+ony||only
+operatione||operation
+opertaions||operations
+optionnal||optional
+optmizations||optimizations
+orientatied||orientated
+orientied||oriented
+orignal||original
+otherise||otherwise
+ouput||output
+oustanding||outstanding
+overaall||overall
+overhread||overhead
+overlaping||overlapping
+overide||override
+overrided||overridden
+overriden||overridden
+overun||overrun
+overwritting||overwriting
+overwriten||overwritten
+pacakge||package
+pachage||package
+packacge||package
+packege||package
+packge||package
+packtes||packets
+pakage||package
+pallette||palette
+paln||plan
+paramameters||parameters
+paramaters||parameters
+paramater||parameter
+parametes||parameters
+parametised||parametrised
+paramter||parameter
+paramters||parameters
+particuarly||particularly
+particularily||particularly
+partiton||partition
+pased||passed
+passin||passing
+pathes||paths
+pecularities||peculiarities
+peformance||performance
+peice||piece
+pendantic||pedantic
+peprocessor||preprocessor
+perfoming||performing
+permissons||permissions
+peroid||period
+persistance||persistence
+persistant||persistent
+plalform||platform
+platfrom||platform
+plattform||platform
+pleaes||please
+ploting||plotting
+plugable||pluggable
+poinnter||pointer
+pointeur||pointer
+poiter||pointer
+posible||possible
+positon||position
+possibilites||possibilities
+powerfull||powerful
+preapre||prepare
+preceeded||preceded
+preceeding||preceding
+preceed||precede
+precendence||precedence
+precission||precision
+preemptable||preemptible
+prefered||preferred
+prefferably||preferably
+premption||preemption
+prepaired||prepared
+pressre||pressure
+primative||primitive
+princliple||principle
+priorty||priority
+privilaged||privileged
+privilage||privilege
+priviledge||privilege
+priviledges||privileges
+probaly||probably
+procceed||proceed
+proccesors||processors
+procesed||processed
+proces||process
+procesing||processing
+processessing||processing
+processess||processes
+processpr||processor
+processsed||processed
+processsing||processing
+procteted||protected
+prodecure||procedure
+progams||programs
+progess||progress
+programers||programmers
+programm||program
+programms||programs
+progresss||progress
+promiscous||promiscuous
+promps||prompts
+pronnounced||pronounced
+prononciation||pronunciation
+pronouce||pronounce
+pronunce||pronounce
+propery||property
+propigate||propagate
+propigation||propagation
+propogate||propagate
+prosess||process
+protable||portable
+protcol||protocol
+protecion||protection
+protocoll||protocol
+promixity||proximity
+psudo||pseudo
+psuedo||pseudo
+psychadelic||psychedelic
+pwoer||power
+quering||querying
+randomally||randomly
+raoming||roaming
+reasearcher||researcher
+reasearchers||researchers
+reasearch||research
+recepient||recipient
+receving||receiving
+recieved||received
+recieve||receive
+reciever||receiver
+recieves||receives
+recogniced||recognised
+recognizeable||recognizable
+recommanded||recommended
+recyle||recycle
+redircet||redirect
+redirectrion||redirection
+reename||rename
+refcounf||refcount
+refence||reference
+refered||referred
+referenace||reference
+refering||referring
+refernces||references
+refernnce||reference
+refrence||reference
+registerd||registered
+registeresd||registered
+registerred||registered
+registes||registers
+registraration||registration
+regsiter||register
+regster||register
+regualar||regular
+reguator||regulator
+regulamentations||regulations
+reigstration||registration
+releated||related
+relevent||relevant
+remoote||remote
+remore||remote
+removeable||removable
+repectively||respectively
+replacable||replaceable
+replacments||replacements
+replys||replies
+reponse||response
+representaion||representation
+reqeust||request
+requestied||requested
+requiere||require
+requirment||requirement
+requred||required
+requried||required
+requst||request
+reseting||resetting
+resizeable||resizable
+resouce||resource
+resouces||resources
+resoures||resources
+responce||response
+ressizes||resizes
+ressource||resource
+ressources||resources
+retransmited||retransmitted
+retreived||retrieved
+retreive||retrieve
+retrive||retrieve
+retuned||returned
+reudce||reduce
+reuest||request
+reuqest||request
+reutnred||returned
+revsion||revision
+rmeoved||removed
+rmeove||remove
+rmeoves||removes
+rountine||routine
+routins||routines
+rquest||request
+runing||running
+runned||ran
+runnning||running
+runtine||runtime
+sacrifying||sacrificing
+safly||safely
+safty||safety
+savable||saveable
+scaned||scanned
+scaning||scanning
+scarch||search
+seach||search
+searchs||searches
+secquence||sequence
+secund||second
+segement||segment
+senarios||scenarios
+sentivite||sensitive
+separatly||separately
+sepcify||specify
+sepc||spec
+seperated||separated
+seperately||separately
+seperate||separate
+seperatly||separately
+seperator||separator
+sepperate||separate
+sequece||sequence
+sequencial||sequential
+serveral||several
+setts||sets
+settting||setting
+shotdown||shutdown
+shoud||should
+shouldnt||shouldn't
+shoule||should
+shrinked||shrunk
+siginificantly||significantly
+signabl||signal
+similary||similarly
+similiar||similar
+simlar||similar
+simliar||similar
+simpified||simplified
+singaled||signaled
+singal||signal
+singed||signed
+sleeped||slept
+softwares||software
+speach||speech
+specfic||specific
+speciefied||specified
+specifc||specific
+specifed||specified
+specificatin||specification
+specificaton||specification
+specifing||specifying
+specifiying||specifying
+speficied||specified
+speicify||specify
+speling||spelling
+spinlcok||spinlock
+spinock||spinlock
+splitted||split
+spreaded||spread
+spurrious||spurious
+sructure||structure
+stablilization||stabilization
+staically||statically
+staion||station
+standardss||standards
+standartization||standardization
+standart||standard
+staticly||statically
+stoped||stopped
+stoppped||stopped
+straming||streaming
+struc||struct
+structres||structures
+stuct||struct
+strucuture||structure
+stucture||structure
+sturcture||structure
+subdirectoires||subdirectories
+suble||subtle
+substract||subtract
+succesfully||successfully
+succesful||successful
+successed||succeeded
+successfull||successful
+successfuly||successfully
+sucessfully||successfully
+sucess||success
+superflous||superfluous
+superseeded||superseded
+suplied||supplied
+suported||supported
+suport||support
+supportet||supported
+suppored||supported
+supportin||supporting
+suppoted||supported
+suppported||supported
+suppport||support
+supress||suppress
+surpresses||suppresses
+susbsystem||subsystem
+suspeneded||suspended
+suspicously||suspiciously
+swaping||swapping
+switchs||switches
+swith||switch
+swithable||switchable
+swithc||switch
+swithced||switched
+swithcing||switching
+swithed||switched
+swithing||switching
+symetric||symmetric
+synax||syntax
+synchonized||synchronized
+syncronize||synchronize
+syncronized||synchronized
+syncronizing||synchronizing
+syncronus||synchronous
+syste||system
+sytem||system
+sythesis||synthesis
+taht||that
+targetted||targeted
+targetting||targeting
+teh||the
+temorary||temporary
+temproarily||temporarily
+therfore||therefore
+thier||their
+threds||threads
+threshhold||threshold
+throught||through
+thses||these
+tiggered||triggered
+tipically||typically
+timout||timeout
+tmis||this
+torerable||tolerable
+tramsmitted||transmitted
+tramsmit||transmit
+tranfer||transfer
+transciever||transceiver
+transferd||transferred
+transfered||transferred
+transfering||transferring
+transision||transition
+transmittd||transmitted
+transormed||transformed
+trasfer||transfer
+trasmission||transmission
+treshold||threshold
+trigerring||triggering
+trun||turn
+ture||true
+tyep||type
+udpate||update
+uesd||used
+uncommited||uncommitted
+unconditionaly||unconditionally
+underun||underrun
+unecessary||unnecessary
+unexecpted||unexpected
+unexepected||unexpected
+unexpcted||unexpected
+unexpectd||unexpected
+unexpeted||unexpected
+unexpexted||unexpected
+unfortunatelly||unfortunately
+unifiy||unify
+unintialized||uninitialized
+unkmown||unknown
+unknonw||unknown
+unknow||unknown
+unkown||unknown
+unneded||unneeded
+unneedingly||unnecessarily
+unnsupported||unsupported
+unmached||unmatched
+unregester||unregister
+unresgister||unregister
+unrgesiter||unregister
+unsinged||unsigned
+unstabel||unstable
+unsolicitied||unsolicited
+unsuccessfull||unsuccessful
+unsuported||unsupported
+untill||until
+unuseful||useless
+upate||update
+usefule||useful
+usefull||useful
+usege||usage
+usera||users
+usualy||usually
+utilites||utilities
+utillities||utilities
+utilties||utilities
+utiltity||utility
+utitity||utility
+utitlty||utility
+vaid||valid
+vaild||valid
+valide||valid
+variantions||variations
+varible||variable
+varient||variant
+vaule||value
+verbse||verbose
+verisons||versions
+verison||version
+verson||version
+vicefersa||vice-versa
+virtal||virtual
+virtaul||virtual
+virtiual||virtual
+visiters||visitors
+vitual||virtual
+wakeus||wakeups
+wating||waiting
+wether||whether
+whataver||whatever
+whcih||which
+whenver||whenever
+wheter||whether
+whe||when
+wierd||weird
+wiil||will
+wirte||write
+withing||within
+wnat||want
+workarould||workaround
+writeing||writing
+writting||writing
+zombe||zombie
+zomebie||zombie
index 829c7efbb2d72c4242ce22e8285b2646884d5dee..ea4b66a41ccb84a202567332560c99ddda85acc5 100644 (file)
@@ -22,12 +22,17 @@ need to implement various "hook" scripts that are called by the test suite at
 the appropriate time.
 
 On Debian or Debian-like distributions, the following packages are required.
-Similar package names should exist in other distributions.
+Some packages are required to execute any test, and others only for specific
+tests. Similar package names should exist in other distributions.
 
 | Package        | Version tested (Ubuntu 14.04) |
 | -------------- | ----------------------------- |
 | python         | 2.7.5-5ubuntu3                |
 | python-pytest  | 2.5.1-1                       |
+| gdisk          | 0.8.8-1ubuntu0.1              |
+| dfu-util       | 0.5-1                         |
+| dtc            | 1.4.0+dfsg-1                  |
+| openssl        | 1.0.1f-1ubuntu2.22            |
 
 The test script supports either:
 
index 65e1d75626cf82105b11130458ac9b264e0ffaa1..6e66a48c15fdad796150467da5d6589bcf5758fb 100644 (file)
@@ -429,12 +429,12 @@ def setup_boardspec(item):
     for board in mark.args:
         if board.startswith('!'):
             if ubconfig.board_type == board[1:]:
-                pytest.skip('board not supported')
+                pytest.skip('board "%s" not supported' % ubconfig.board_type)
                 return
         else:
             required_boards.append(board)
     if required_boards and ubconfig.board_type not in required_boards:
-        pytest.skip('board not supported')
+        pytest.skip('board "%s" not supported' % ubconfig.board_type)
 
 def setup_buildconfigspec(item):
     """Process any 'buildconfigspec' marker for a test.
@@ -455,7 +455,35 @@ def setup_buildconfigspec(item):
         return
     for option in mark.args:
         if not ubconfig.buildconfig.get('config_' + option.lower(), None):
-            pytest.skip('.config feature not enabled')
+            pytest.skip('.config feature "%s" not enabled' % option.lower())
+
+def tool_is_in_path(tool):
+    for path in os.environ["PATH"].split(os.pathsep):
+        fn = os.path.join(path, tool)
+        if os.path.isfile(fn) and os.access(fn, os.X_OK):
+            return True
+    return False
+
+def setup_requiredtool(item):
+    """Process any 'requiredtool' marker for a test.
+
+    Such a marker lists some external tool (binary, executable, application)
+    that the test requires. If tests are being executed on a system that
+    doesn't have the required tool, the test is marked to be skipped.
+
+    Args:
+        item: The pytest test item.
+
+    Returns:
+        Nothing.
+    """
+
+    mark = item.get_marker('requiredtool')
+    if not mark:
+        return
+    for tool in mark.args:
+        if not tool_is_in_path(tool):
+            pytest.skip('tool "%s" not in $PATH' % tool)
 
 def start_test_section(item):
     anchors[item.name] = log.start_section(item.name)
@@ -476,6 +504,7 @@ def pytest_runtest_setup(item):
     start_test_section(item)
     setup_boardspec(item)
     setup_buildconfigspec(item)
+    setup_requiredtool(item)
 
 def pytest_runtest_protocol(item, nextitem):
     """pytest hook: Called to execute a test.
index bf926c3e7762ae37ffc026ebebf58e05641df50a..5bc1bc49d4de2d8f9433507f42bcdfd33a3916a1 100644 (file)
@@ -365,13 +365,13 @@ $(document).ready(function () {
 
         self._terminate_stream()
         self.f.write('<div class="' + note_type + '">\n')
-        if anchor:
-            self.f.write('<a href="#%s">\n' % anchor)
         self.f.write('<pre>')
+        if anchor:
+            self.f.write('<a href="#%s">' % anchor)
         self.f.write(self._escape(msg))
-        self.f.write('\n</pre>\n')
         if anchor:
-            self.f.write('</a>\n')
+            self.f.write('</a>')
+        self.f.write('\n</pre>\n')
         self.f.write('</div>\n')
 
     def start_section(self, marker, anchor=None):
index fba67d585b9faff1db1cade330a0597360b74b95..8f6877c5c2647c43d0ef31d3356f2bbf7afcc964 100644 (file)
@@ -113,6 +113,7 @@ test_sizes_default = (
 first_usb_dev_port = None
 
 @pytest.mark.buildconfigspec('cmd_dfu')
+@pytest.mark.requiredtool('dfu-util')
 def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
     """Test the "dfu" command; the host system must be able to enumerate a USB
     device when "dfu" is running, various DFU transfers are tested, and the
diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py
new file mode 100644 (file)
index 0000000..76e282a
--- /dev/null
@@ -0,0 +1,25 @@
+# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+# Copyright (c) 2017, Heinrich Schuchardt <xypron.glpk@gmx.de>
+#
+# SPDX-License-Identifier: GPL-2.0
+
+# Test efi API implementation
+
+import pytest
+import u_boot_utils
+
+@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
+def test_efi_selftest(u_boot_console):
+       """
+       Run bootefi selftest
+       """
+
+       u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False)
+       m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
+       if m != 0:
+               raise Exception('Failures occured during the EFI selftest')
+       u_boot_console.run_command(cmd='', wait_for_echo=False, wait_for_prompt=False);
+       m = u_boot_console.p.expect(['resetting', 'U-Boot'])
+       if m != 0:
+               raise Exception('Reset failed during the EFI selftest')
+       u_boot_console.restart_uboot();
index 7e6b96dae45a5665d2a50f3f9524093156642e0a..4b32bb18b8b3d6b8296e1b403042379ef70a166e 100755 (executable)
@@ -111,6 +111,7 @@ sb save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('fit_signature')
+@pytest.mark.requiredtool('dtc')
 def test_fit(u_boot_console):
     def make_fname(leaf):
         """Make a temporary filename
index e2bbd08e6d42a6cbc4bb9da73684c37f46c2b95a..ec25fbbc5a1065efef662cc83d16b6088e2fd107 100644 (file)
@@ -38,15 +38,14 @@ class GptTestDiskImage(object):
             fd = os.open(self.path, os.O_RDWR | os.O_CREAT)
             os.ftruncate(fd, 4194304)
             os.close(fd)
-            sgdisk = '/sbin/sgdisk'
-            cmd = (sgdisk, '-U', '375a56f7-d6c9-4e81-b5f0-09d41ca89efe',
+            cmd = ('sgdisk', '-U', '375a56f7-d6c9-4e81-b5f0-09d41ca89efe',
                 self.path)
             u_boot_utils.run_and_log(u_boot_console, cmd)
-            cmd = (sgdisk, '--new=1:2048:2560', self.path)
+            cmd = ('sgdisk', '--new=1:2048:2560', self.path)
             u_boot_utils.run_and_log(u_boot_console, cmd)
-            cmd = (sgdisk, '--new=2:4096:4608', self.path)
+            cmd = ('sgdisk', '--new=2:4096:4608', self.path)
             u_boot_utils.run_and_log(u_boot_console, cmd)
-            cmd = (sgdisk, '-l', self.path)
+            cmd = ('sgdisk', '-l', self.path)
             u_boot_utils.run_and_log(u_boot_console, cmd)
 
 gtdi = None
@@ -64,6 +63,7 @@ def state_disk_image(u_boot_console):
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.requiredtool('sgdisk')
 def test_gpt_guid(state_disk_image, u_boot_console):
     """Test the gpt guid command."""
 
@@ -73,6 +73,7 @@ def test_gpt_guid(state_disk_image, u_boot_console):
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.requiredtool('sgdisk')
 def test_gpt_save_guid(state_disk_image, u_boot_console):
     """Test the gpt guid command to save GUID into a string."""
 
@@ -86,6 +87,7 @@ def test_gpt_save_guid(state_disk_image, u_boot_console):
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.buildconfigspec('cmd_gpt_rename')
+@pytest.mark.requiredtool('sgdisk')
 def test_gpt_rename_partition(state_disk_image, u_boot_console):
     """Test the gpt rename command to write partition names."""
 
@@ -101,6 +103,7 @@ def test_gpt_rename_partition(state_disk_image, u_boot_console):
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.buildconfigspec('cmd_gpt_rename')
 @pytest.mark.buildconfigspec('cmd_part')
+@pytest.mark.requiredtool('sgdisk')
 def test_gpt_swap_partitions(state_disk_image, u_boot_console):
     """Test the gpt swap command to exchange two partition names."""
 
index 6e62820743fe03b63c3c4ce8a1885587b04e53c1..c4da79d11407eca7f62e6db89618cceffe772176 100644 (file)
@@ -31,6 +31,10 @@ import u_boot_utils as util
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('fit_signature')
+@pytest.mark.requiredtool('dtc')
+@pytest.mark.requiredtool('fdtget')
+@pytest.mark.requiredtool('fdtput')
+@pytest.mark.requiredtool('openssl')
 def test_vboot(u_boot_console):
     """Test verified boot signing with mkimage and verification with 'bootm'.
 
index 352ad438eed2955aeb6ec5349fc437032f659c5b..68b470a3a7d9adfc5ec48647d6a6e899b63d8b5d 100644 (file)
@@ -73,6 +73,7 @@ email service. Don't wrestle with internal APIs. Tell me what you need and I
 might add it in a safe way as a client API instead."""
 
 import os
+import platform
 import re
 import sys
 
@@ -137,10 +138,8 @@ class Config(object):
         # The set of all symbols, indexed by name (a string)
         self.syms = {}
         # Python 2/3 compatibility hack. This is the only one needed.
-        if sys.version_info[0] >= 3:
-            self.syms_iter = self.syms.values
-        else:
-            self.syms_iter = self.syms.itervalues
+        self.syms_iter = self.syms.values if sys.version_info[0] >= 3 else \
+                         self.syms.itervalues
 
         # The set of all defined symbols in the configuration in the order they
         # appear in the Kconfig files. This excludes the special symbols n, m,
@@ -173,7 +172,7 @@ class Config(object):
         self.m = register_special_symbol(TRISTATE, "m", "m")
         self.y = register_special_symbol(TRISTATE, "y", "y")
         # DEFCONFIG_LIST uses this
-        register_special_symbol(STRING, "UNAME_RELEASE", os.uname()[2])
+        register_special_symbol(STRING, "UNAME_RELEASE", platform.uname()[2])
 
         # The symbol with "option defconfig_list" set, containing a list of
         # default .config files
@@ -183,16 +182,20 @@ class Config(object):
         self.arch = os.environ.get("ARCH")
         self.srcarch = os.environ.get("SRCARCH")
 
+        # If you set CONFIG_ in the environment, Kconfig will prefix all symbols
+        # with its value when saving the configuration, instead of using the default, "CONFIG_".
+        self.config_prefix = os.environ.get("CONFIG_")
+        if self.config_prefix is None:
+            self.config_prefix = "CONFIG_"
+
         # See Config.__init__(). We need this for get_defconfig_filename().
         self.srctree = os.environ.get("srctree")
         if self.srctree is None:
             self.srctree = "."
 
         self.filename = filename
-        if base_dir is None:
-            self.base_dir = self.srctree
-        else:
-            self.base_dir = os.path.expandvars(base_dir)
+        self.base_dir = self.srctree if base_dir is None else \
+                        os.path.expandvars(base_dir)
 
         # The 'mainmenu' text
         self.mainmenu_text = None
@@ -222,7 +225,8 @@ class Config(object):
         self._transform_m = None
 
         # Parse the Kconfig files
-        self.top_block = self._parse_file(filename, None, None, None)
+        self.top_block = []
+        self._parse_file(filename, None, None, None, self.top_block)
 
         # Build Symbol.dep for all symbols
         self._build_dep()
@@ -405,6 +409,10 @@ class Config(object):
         """
 
         self._warnings = []
+        # Regular expressions for parsing .config files
+        _set_re_match = re.compile(r"{}(\w+)=(.*)".format(self.config_prefix)).match
+        _unset_re_match = re.compile(r"# {}(\w+) is not set".format(self.config_prefix)).match
+
         # Put this first so that a missing file doesn't screw up our state
         filename = os.path.expandvars(filename)
         line_feeder = _FileFeed(filename)
@@ -524,14 +532,12 @@ class Config(object):
         with open(filename, "w") as f:
             # Write header
             if header is not None:
-                f.write(_comment(header))
-                f.write("\n")
+                f.write(_comment(header) + "\n")
 
             # Build and write configuration
             conf_strings = []
             _make_block_conf(self.top_block, conf_strings.append)
-            f.write("\n".join(conf_strings))
-            f.write("\n")
+            f.write("\n".join(conf_strings) + "\n")
 
     def eval(self, s):
         """Returns the value of the expression 's' -- where 's' is represented
@@ -609,16 +615,18 @@ class Config(object):
     # Kconfig parsing
     #
 
-    def _parse_file(self, filename, parent, deps, visible_if_deps, res=None):
-        """Parses the Kconfig file 'filename'. Returns a list with the Items in
-        the file. See _parse_block() for the meaning of the parameters."""
-        return self._parse_block(_FileFeed(filename), None, parent, deps,
-                                 visible_if_deps, res)
+    def _parse_file(self, filename, parent, deps, visible_if_deps, block):
+        """Parses the Kconfig file 'filename'. Appends the Items in the file
+        (and any file it sources) to the list passed in the 'block' parameter.
+        See _parse_block() for the meaning of the parameters."""
+        self._parse_block(_FileFeed(filename), None, parent, deps,
+                          visible_if_deps, block)
 
     def _parse_block(self, line_feeder, end_marker, parent, deps,
-                     visible_if_deps, res=None):
+                     visible_if_deps, block):
         """Parses a block, which is the contents of either a file or an if,
-        menu, or choice statement. Returns a list with the Items in the block.
+        menu, or choice statement. Appends the Items to the list passed in the
+        'block' parameter.
 
         line_feeder: A _FileFeed instance feeding lines from a file. The
           Kconfig language is line-based in practice.
@@ -634,10 +642,7 @@ class Config(object):
         visible_if_deps (default: None): 'visible if' dependencies from
            enclosing menus.
 
-        res (default: None): The list to add items to. If None, a new list is
-           created to hold the items."""
-
-        block = [] if res is None else res
+        block: The list to add items to."""
 
         while 1:
             # Do we already have a tokenized line that we determined wasn't
@@ -656,7 +661,7 @@ class Config(object):
                     if end_marker is not None:
                         raise Kconfig_Syntax_Error("Unexpected end of file {0}"
                                                  .format(line_feeder.filename))
-                    return block
+                    return
 
                 tokens = self._tokenize(line, False, line_feeder.filename,
                                         line_feeder.linenr)
@@ -679,14 +684,13 @@ class Config(object):
                 # choice statements, the choice statement takes precedence.
                 if not sym.is_defined_ or isinstance(parent, Choice):
                     sym.parent = parent
-
                 sym.is_defined_ = True
 
+                self._parse_properties(line_feeder, sym, deps, visible_if_deps)
+
                 self.kconfig_syms.append(sym)
                 block.append(sym)
 
-                self._parse_properties(line_feeder, sym, deps, visible_if_deps)
-
             elif t0 == T_SOURCE:
                 kconfig_file = tokens.get_next()
                 exp_kconfig_file = self._expand_sym_refs(kconfig_file)
@@ -705,7 +709,7 @@ class Config(object):
 
             elif t0 == end_marker:
                 # We have reached the end of the block
-                return block
+                return
 
             elif t0 == T_IF:
                 # If statements are treated as syntactic sugar for adding
@@ -722,38 +726,39 @@ class Config(object):
 
             elif t0 == T_COMMENT:
                 comment = Comment()
-
                 comment.config = self
                 comment.parent = parent
                 comment.filename = line_feeder.filename
                 comment.linenr = line_feeder.linenr
                 comment.text = tokens.get_next()
 
-                self.comments.append(comment)
-                block.append(comment)
-
                 self._parse_properties(line_feeder, comment, deps,
                                        visible_if_deps)
 
+                self.comments.append(comment)
+                block.append(comment)
+
             elif t0 == T_MENU:
                 menu = Menu()
-
                 menu.config = self
                 menu.parent = parent
                 menu.filename = line_feeder.filename
                 menu.linenr = line_feeder.linenr
                 menu.title = tokens.get_next()
 
-                self.menus.append(menu)
-                block.append(menu)
-
-                # Parse properties and contents
                 self._parse_properties(line_feeder, menu, deps,
                                        visible_if_deps)
-                menu.block = self._parse_block(line_feeder, T_ENDMENU, menu,
-                                               menu.dep_expr,
-                                               _make_and(visible_if_deps,
-                                                         menu.visible_if_expr))
+
+                # This needs to go before _parse_block() so that we get the
+                # proper menu ordering in the case of nested functions
+                self.menus.append(menu)
+                # Parse contents and put Items in menu.block
+                self._parse_block(line_feeder, T_ENDMENU, menu, menu.dep_expr,
+                                  _make_and(visible_if_deps,
+                                            menu.visible_if_expr),
+                                  menu.block)
+
+                block.append(menu)
 
             elif t0 == T_CHOICE:
                 name = tokens.get_next()
@@ -775,11 +780,12 @@ class Config(object):
                 choice.def_locations.append((line_feeder.filename,
                                              line_feeder.linenr))
 
-                # Parse properties and contents
                 self._parse_properties(line_feeder, choice, deps,
                                        visible_if_deps)
-                choice.block = self._parse_block(line_feeder, T_ENDCHOICE,
-                                                 choice, deps, visible_if_deps)
+
+                # Parse contents and put Items in choice.block
+                self._parse_block(line_feeder, T_ENDCHOICE, choice, deps,
+                                  visible_if_deps, choice.block)
 
                 choice._determine_actual_symbols()
 
@@ -819,19 +825,19 @@ class Config(object):
             """Parses '<expr1> if <expr2>' constructs, where the 'if' part is
             optional. Returns a tuple containing the parsed expressions, with
             None as the second element if the 'if' part is missing."""
-            val = self._parse_expr(tokens, stmt, line, filename, linenr, False)
-            if tokens.check(T_IF):
-                return (val, self._parse_expr(tokens, stmt, line, filename,
-                                              linenr))
-            return (val, None)
+            return (self._parse_expr(tokens, stmt, line, filename, linenr,
+                                     False),
+                    self._parse_expr(tokens, stmt, line, filename, linenr)
+                    if tokens.check(T_IF) else None)
 
         # In case the symbol is defined in multiple locations, we need to
-        # remember what prompts, defaults, and selects are new for this
-        # definition, as "depends on" should only apply to the local
+        # remember what prompts, defaults, selects, and implies are new for
+        # this definition, as "depends on" should only apply to the local
         # definition.
         new_prompt = None
         new_def_exprs = []
         new_selects = []
+        new_implies = []
 
         # Dependencies from 'depends on' statements
         depends_on_expr = None
@@ -897,18 +903,27 @@ class Config(object):
 
                 line_feeder.unget()
 
-            elif t0 == T_SELECT or t0 == T_IMPLY:
+            elif t0 == T_SELECT:
                 target = tokens.get_next()
 
                 stmt.referenced_syms.add(target)
                 stmt.selected_syms.add(target)
 
-                if tokens.check(T_IF):
-                    new_selects.append((target,
-                                        self._parse_expr(tokens, stmt, line,
-                                                         filename, linenr)))
-                else:
-                    new_selects.append((target, None))
+                new_selects.append(
+                    (target,
+                     self._parse_expr(tokens, stmt, line, filename, linenr)
+                     if tokens.check(T_IF) else None))
+
+            elif t0 == T_IMPLY:
+                target = tokens.get_next()
+
+                stmt.referenced_syms.add(target)
+                stmt.implied_syms.add(target)
+
+                new_implies.append(
+                    (target,
+                     self._parse_expr(tokens, stmt, line, filename, linenr)
+                     if tokens.check(T_IF) else None))
 
             elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING):
                 stmt.type = TOKEN_TO_TYPE[t0]
@@ -939,12 +954,10 @@ class Config(object):
                 stmt.referenced_syms.add(low)
                 stmt.referenced_syms.add(high)
 
-                if tokens.check(T_IF):
-                    stmt.ranges.append((low, high,
-                                        self._parse_expr(tokens, stmt, line,
-                                                         filename, linenr)))
-                else:
-                    stmt.ranges.append((low, high, None))
+                stmt.ranges.append(
+                    (low, high,
+                     self._parse_expr(tokens, stmt, line, filename, linenr)
+                     if tokens.check(T_IF) else None))
 
             elif t0 == T_DEF_TRISTATE:
                 stmt.type = TRISTATE
@@ -1051,21 +1064,20 @@ class Config(object):
             # Symbol or Choice
 
             # See comment for 'menu_dep'
-            stmt.menu_dep = depends_on_expr
+            stmt.menu_dep = _make_and(deps, depends_on_expr)
 
             # Propagate dependencies to prompts
 
             if new_prompt is not None:
-                # Propagate 'visible if' dependencies from enclosing menus
                 prompt, cond_expr = new_prompt
-                cond_expr = _make_and(cond_expr, visible_if_deps)
-                # Propagate 'depends on' dependencies
-                new_prompt = (prompt, _make_and(cond_expr, depends_on_expr))
+                # Propagate 'visible if' dependencies from menus and local
+                # 'depends on' dependencies
+                cond_expr = _make_and(_make_and(cond_expr, visible_if_deps),
+                                      depends_on_expr)
                 # Save original
-                stmt.orig_prompts.append(new_prompt)
+                stmt.orig_prompts.append((prompt, cond_expr))
                 # Finalize with dependencies from enclosing menus and ifs
-                stmt.prompts.append((new_prompt[0],
-                                     _make_and(new_prompt[1], deps)))
+                stmt.prompts.append((prompt, _make_and(cond_expr, deps)))
 
             # Propagate dependencies to defaults
 
@@ -1078,20 +1090,27 @@ class Config(object):
             stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
                                    for val_expr, cond_expr in new_def_exprs])
 
-            # Propagate dependencies to selects
+            # Propagate dependencies to selects and implies
 
-            # Only symbols can select
+            # Only symbols can select and imply
             if isinstance(stmt, Symbol):
                 # Propagate 'depends on' dependencies
                 new_selects = [(target, _make_and(cond_expr, depends_on_expr))
                                for target, cond_expr in new_selects]
+                new_implies = [(target, _make_and(cond_expr, depends_on_expr))
+                               for target, cond_expr in new_implies]
                 # Save original
                 stmt.orig_selects.extend(new_selects)
+                stmt.orig_implies.extend(new_implies)
                 # Finalize with dependencies from enclosing menus and ifs
                 for target, cond in new_selects:
-                    target.rev_dep = _make_or(target.rev_dep,
-                                              _make_and(stmt,
-                                                        _make_and(cond, deps)))
+                    target.rev_dep = \
+                        _make_or(target.rev_dep,
+                                 _make_and(stmt, _make_and(cond, deps)))
+                for target, cond in new_implies:
+                    target.weak_rev_dep = \
+                        _make_or(target.weak_rev_dep,
+                                 _make_and(stmt, _make_and(cond, deps)))
 
     def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None,
                     transform_m=True):
@@ -1483,7 +1502,8 @@ class Config(object):
 
         # The directly dependent symbols of a symbol are:
         #  - Any symbols whose prompts, default values, rev_dep (select
-        #    condition), or ranges depend on the symbol
+        #    condition), weak_rev_dep (imply condition) or ranges depend on the
+        #    symbol
         #  - Any symbols that belong to the same choice statement as the symbol
         #    (these won't be included in 'dep' as that makes the dependency
         #    graph unwieldy, but Symbol._get_dependent() will include them)
@@ -1497,6 +1517,7 @@ class Config(object):
                 add_expr_deps(e, sym)
 
             add_expr_deps(sym.rev_dep, sym)
+            add_expr_deps(sym.weak_rev_dep, sym)
 
             for l, u, e in sym.ranges:
                 add_expr_deps(l, sym)
@@ -1625,20 +1646,16 @@ class Config(object):
         else:
             prompts_str_rows = []
             for prompt, cond_expr in sc.orig_prompts:
-                if cond_expr is None:
-                    prompts_str_rows.append(' "{0}"'.format(prompt))
-                else:
-                    prompts_str_rows.append(
-                      ' "{0}" if {1}'.format(prompt,
-                                             self._expr_val_str(cond_expr)))
+                prompts_str_rows.append(
+                    ' "{0}"'.format(prompt) if cond_expr is None else
+                    ' "{0}" if {1}'.format(prompt,
+                                           self._expr_val_str(cond_expr)))
             prompts_str = "\n".join(prompts_str_rows)
 
         # Build locations string
-        if not sc.def_locations:
-            locations_str = "(no locations)"
-        else:
-            locations_str = " ".join(["{0}:{1}".format(filename, linenr) for
-                                      (filename, linenr) in sc.def_locations])
+        locations_str = "(no locations)" if not sc.def_locations else \
+                        " ".join(["{0}:{1}".format(filename, linenr) for
+                                  filename, linenr in sc.def_locations])
 
         # Build additional-dependencies-from-menus-and-ifs string
         additional_deps_str = " " + \
@@ -1657,13 +1674,11 @@ class Config(object):
                 else:
                     ranges_str_rows = []
                     for l, u, cond_expr in sc.ranges:
-                        if cond_expr is None:
-                            ranges_str_rows.append(" [{0}, {1}]".format(s(l),
-                                                                        s(u)))
-                        else:
-                            ranges_str_rows.append(" [{0}, {1}] if {2}"
-                              .format(s(l), s(u),
-                                      self._expr_val_str(cond_expr)))
+                        ranges_str_rows.append(
+                            " [{0}, {1}]".format(s(l), s(u))
+                            if cond_expr is None else
+                            " [{0}, {1}] if {2}"
+                            .format(s(l), s(u), self._expr_val_str(cond_expr)))
                     ranges_str = "\n".join(ranges_str_rows)
 
             # Build default values string
@@ -1685,14 +1700,24 @@ class Config(object):
             else:
                 selects_str_rows = []
                 for target, cond_expr in sc.orig_selects:
-                    if cond_expr is None:
-                        selects_str_rows.append(" {0}".format(target.name))
-                    else:
-                        selects_str_rows.append(
-                          " {0} if {1}".format(target.name,
-                                               self._expr_val_str(cond_expr)))
+                    selects_str_rows.append(
+                        " {0}".format(target.name) if cond_expr is None else
+                        " {0} if {1}".format(target.name,
+                                             self._expr_val_str(cond_expr)))
                 selects_str = "\n".join(selects_str_rows)
 
+            # Build implies string
+            if not sc.orig_implies:
+                implies_str = " (no implies)"
+            else:
+                implies_str_rows = []
+                for target, cond_expr in sc.orig_implies:
+                    implies_str_rows.append(
+                        " {0}".format(target.name) if cond_expr is None else
+                        " {0} if {1}".format(target.name,
+                                             self._expr_val_str(cond_expr)))
+                implies_str = "\n".join(implies_str_rows)
+
             res = _lines("Symbol " +
                            ("(no name)" if sc.name is None else sc.name),
                          "Type           : " + TYPENAME[sc.type],
@@ -1711,9 +1736,16 @@ class Config(object):
                           defaults_str,
                           "Selects:",
                           selects_str,
+                          "Implies:",
+                          implies_str,
                           "Reverse (select-related) dependencies:",
-                          " (no reverse dependencies)" if sc.rev_dep == "n"
-                            else " " + self._expr_val_str(sc.rev_dep),
+                          " (no reverse dependencies)"
+                          if sc.rev_dep == "n"
+                          else " " + self._expr_val_str(sc.rev_dep),
+                          "Weak reverse (imply-related) dependencies:",
+                          " (no weak reverse dependencies)"
+                          if sc.weak_rev_dep == "n"
+                          else " " + self._expr_val_str(sc.weak_rev_dep),
                           "Additional dependencies from enclosing menus "
                             "and ifs:",
                           additional_deps_str,
@@ -1735,11 +1767,10 @@ class Config(object):
         else:
             defaults_str_rows = []
             for sym, cond_expr in sc.orig_def_exprs:
-                if cond_expr is None:
-                    defaults_str_rows.append(" {0}".format(sym.name))
-                else:
-                    defaults_str_rows.append(" {0} if {1}".format(sym.name,
-                                                self._expr_val_str(cond_expr)))
+                defaults_str_rows.append(
+                    " {0}".format(sym.name) if cond_expr is None else
+                    " {0} if {1}".format(sym.name,
+                                         self._expr_val_str(cond_expr)))
             defaults_str = "\n".join(defaults_str_rows)
 
         # Build contained symbols string
@@ -1919,26 +1950,25 @@ class Symbol(Item):
                     self.write_to_conf = (mode != "n")
 
                     if mode == "y":
-                        if choice.get_selection() is self:
-                            new_val = "y"
-                        else:
-                            new_val = "n"
+                        new_val = "y" if choice.get_selection() is self \
+                                  else "n"
                     elif mode == "m":
                         if self.user_val == "m" or self.user_val == "y":
                             new_val = "m"
 
             else:
                 # If the symbol is visible and has a user value, use that.
-                # Otherwise, look at defaults.
-                use_defaults = True
+                # Otherwise, look at defaults and weak reverse dependencies
+                # (implies).
+                use_defaults_and_weak_rev_deps = True
 
                 if vis != "n":
                     self.write_to_conf = True
                     if self.user_val is not None:
                         new_val = self.config._eval_min(self.user_val, vis)
-                        use_defaults = False
+                        use_defaults_and_weak_rev_deps = False
 
-                if use_defaults:
+                if use_defaults_and_weak_rev_deps:
                     for val_expr, cond_expr in self.def_exprs:
                         cond_eval = self.config._eval_expr(cond_expr)
                         if cond_eval != "n":
@@ -1947,14 +1977,25 @@ class Symbol(Item):
                                                             cond_eval)
                             break
 
+                    weak_rev_dep_val = \
+                        self.config._eval_expr(self.weak_rev_dep)
+                    if weak_rev_dep_val != "n":
+                        self.write_to_conf = True
+                        new_val = self.config._eval_max(new_val,
+                                                        weak_rev_dep_val)
+
                 # Reverse (select-related) dependencies take precedence
                 rev_dep_val = self.config._eval_expr(self.rev_dep)
                 if rev_dep_val != "n":
                     self.write_to_conf = True
                     new_val = self.config._eval_max(new_val, rev_dep_val)
 
-            # Promote "m" to "y" for booleans
-            if new_val == "m" and self.type == BOOL:
+            # We need to promote "m" to "y" in two circumstances:
+            #  1) If our type is boolean
+            #  2) If our weak_rev_dep (from IMPLY) is "y"
+            if new_val == "m" and \
+               (self.type == BOOL or
+                self.config._eval_expr(self.weak_rev_dep) == "y"):
                 new_val = "y"
 
         elif self.type == INT or self.type == HEX:
@@ -2189,6 +2230,13 @@ class Symbol(Item):
         get_referenced_symbols()."""
         return self.selected_syms
 
+    def get_implied_symbols(self):
+        """Returns the set() of all symbols X for which this symbol has an
+        'imply X' or 'imply X if Y' (regardless of whether Y is satisfied or
+        not). This is a subset of the symbols returned by
+        get_referenced_symbols()."""
+        return self.implied_syms
+
     def set_user_value(self, v):
         """Sets the user value of the symbol.
 
@@ -2304,16 +2352,18 @@ class Symbol(Item):
         self.ranges = [] # 'range' properties (for int and hex)
         self.help = None # Help text
         self.rev_dep = "n" # Reverse (select-related) dependencies
+        self.weak_rev_dep = "n" # Weak reverse (imply-related) dependencies
         self.config = None
         self.parent = None
 
         self.user_val = None # Value set by user
 
-        # The prompt, default value and select conditions without any
+        # The prompt, default value, select, and imply conditions without any
         # dependencies from menus and ifs propagated to them
         self.orig_prompts = []
         self.orig_def_exprs = []
         self.orig_selects = []
+        self.orig_implies = []
 
         # Dependencies inherited from containing menus and ifs
         self.deps_from_containing = None
@@ -2323,13 +2373,15 @@ class Symbol(Item):
         # The set of symbols selected by this symbol (see
         # get_selected_symbols())
         self.selected_syms = set()
+        # The set of symbols implied by this symbol (see get_implied_symbols())
+        self.implied_syms = set()
         # Like 'referenced_syms', but includes symbols from
         # dependencies inherited from enclosing menus and ifs
         self.all_referenced_syms = set()
 
-        # This records only dependencies specified with 'depends on'. Needed
-        # when determining actual choice items (hrrrr...). See also
-        # Choice._determine_actual_symbols().
+        # This records only dependencies from enclosing ifs and menus together
+        # with local 'depends on' dependencies. Needed when determining actual
+        # choice items (hrrrr...). See Choice._determine_actual_symbols().
         self.menu_dep = None
 
         # See Symbol.get_ref/def_locations().
@@ -2470,18 +2522,17 @@ class Symbol(Item):
             return
 
         if self.type == BOOL or self.type == TRISTATE:
-            if val == "y" or val == "m":
-                append_fn("CONFIG_{0}={1}".format(self.name, val))
-            else:
-                append_fn("# CONFIG_{0} is not set".format(self.name))
+            append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val)
+                      if val == "y" or val == "m" else
+                      "# {0}{1} is not set".format(self.config.config_prefix, self.name))
 
         elif self.type == INT or self.type == HEX:
-            append_fn("CONFIG_{0}={1}".format(self.name, val))
+            append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val))
 
         elif self.type == STRING:
             # Escape \ and "
-            append_fn('CONFIG_{0}="{1}"'
-                      .format(self.name,
+            append_fn('{0}{1}="{2}"'
+                      .format(self.config.config_prefix, self.name,
                               val.replace("\\", "\\\\").replace('"', '\\"')))
 
         else:
@@ -2635,7 +2686,7 @@ class Menu(Item):
         self.title = None
         self.dep_expr = None
         self.visible_if_expr = None
-        self.block = None
+        self.block = [] # List of contained items
         self.config = None
         self.parent = None
 
@@ -2852,7 +2903,7 @@ class Choice(Item):
         self.prompts = []
         self.def_exprs = [] # 'default' properties
         self.help = None # Help text
-        self.block = None # List of contained items
+        self.block = [] # List of contained items
         self.config = None
         self.parent = None
 
@@ -3177,7 +3228,13 @@ def _get_visibility(sc):
             vis = sc.config._eval_max(vis, cond_expr)
 
         if isinstance(sc, Symbol) and sc.is_choice_sym:
-            vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
+            if sc.type == TRISTATE and vis == "m" and \
+               sc.parent.get_mode() == "y":
+                # Choice symbols with visibility "m" are not visible if the
+                # choice has mode "y"
+                vis = "n"
+            else:
+                vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
 
         # Promote "m" to "y" if we're dealing with a non-tristate
         if vis == "m" and sc.type != TRISTATE:
@@ -3434,7 +3491,7 @@ _get_keyword = \
    "prompt": T_PROMPT, "default": T_DEFAULT, "bool": T_BOOL, "boolean": T_BOOL,
    "tristate": T_TRISTATE, "int": T_INT, "hex": T_HEX, "def_bool": T_DEF_BOOL,
    "def_tristate": T_DEF_TRISTATE, "string": T_STRING, "select": T_SELECT,
-   "imply": T_IMPLY, "range": T_RANGE, "option": T_OPTION,
+   "imply" : T_IMPLY, "range": T_RANGE, "option": T_OPTION,
    "allnoconfig_y": T_ALLNOCONFIG_Y, "env": T_ENV,
    "defconfig_list": T_DEFCONFIG_LIST, "modules": T_MODULES,
    "visible": T_VISIBLE}.get
@@ -3455,10 +3512,6 @@ _initial_token_re_match = re.compile(r"[^\w]*(\w+)\s*").match
 # trailing whitespace as an optimization.
 _id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").match
 
-# Regular expressions for parsing .config files
-_set_re_match = re.compile(r"CONFIG_(\w+)=(.*)").match
-_unset_re_match = re.compile(r"# CONFIG_(\w+) is not set").match
-
 # Regular expression for finding $-references to symbols in strings
 _sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
 
index 6f549a51c16d0c2d81c3effbd8f62f8d255f45a5..e3116461bad0ec577b5081ff332077c5babdefe6 100755 (executable)
@@ -1472,7 +1472,7 @@ def find_kconfig_rules(kconf, config, imply_config):
     """
     sym = kconf.get_symbol(imply_config)
     if sym:
-        for sel in sym.get_selected_symbols():
+        for sel in sym.get_selected_symbols() | sym.get_implied_symbols():
             if sel.get_name() == config:
                 return sym
     return None
index 04e8272fd5b63b870186bd73a31e4256ee38352f..1a24e165894c45435daef9f4404b9ea7280b843f 100644 (file)
@@ -73,6 +73,7 @@ struct spl_info {
 
 static struct spl_info spl_infos[] = {
        { "rk3036", "RK30", 0x1000, false, false },
+       { "rk3128", "RK31", 0x1800, false, false },
        { "rk3188", "RK31", 0x8000 - 0x800, true, false },
        { "rk322x", "RK32", 0x8000 - 0x1000, false, false },
        { "rk3288", "RK32", 0x8000, false, false },