diff options
176 files changed, 9999 insertions, 888 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 04acf2b89d..b167b028ec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -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 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index bb64b9c160..d6d9558c69 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -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 index 0000000000..24a67dbd1e --- /dev/null +++ b/arch/arm/dts/am3517-evm-u-boot.dtsi @@ -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 index 0000000000..0e4a125f78 --- /dev/null +++ b/arch/arm/dts/am3517-evm.dts @@ -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 index 0000000000..219005210d --- /dev/null +++ b/arch/arm/dts/am3517-u-boot.dtsi @@ -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 index 0000000000..00da3f2c40 --- /dev/null +++ b/arch/arm/dts/am3517.dtsi @@ -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 index 0000000000..00dd1f091b --- /dev/null +++ b/arch/arm/dts/am35xx-clocks.dtsi @@ -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 index 0000000000..5cc5a81f6f --- /dev/null +++ b/arch/arm/dts/da850-evm-u-boot.dtsi @@ -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 index 0000000000..67e72bc72e --- /dev/null +++ b/arch/arm/dts/da850-evm.dts @@ -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 index 0000000000..02e2f8f258 --- /dev/null +++ b/arch/arm/dts/da850.dtsi @@ -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"; + }; +}; diff --git a/arch/arm/dts/omap3.dtsi b/arch/arm/dts/omap3.dtsi index e6f9c9a6dd..56c94729bb 100644 --- a/arch/arm/dts/omap3.dtsi +++ b/arch/arm/dts/omap3.dtsi @@ -716,14 +716,12 @@ 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>; }; }; @@ -834,7 +832,6 @@ reg-names = "tx", "rx"; - interrupt-parent = <&intc>; interrupts = <67>, <68>; }; @@ -847,7 +844,6 @@ reg-names = "tx", "rx"; - interrupt-parent = <&intc>; interrupts = <69>, <70>; }; diff --git a/arch/arm/dts/omap5-u-boot.dtsi b/arch/arm/dts/omap5-u-boot.dtsi index 2eeed6f4a0..fdaa69297c 100644 --- a/arch/arm/dts/omap5-u-boot.dtsi +++ b/arch/arm/dts/omap5-u-boot.dtsi @@ -60,10 +60,30 @@ }; }; +&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; }; diff --git a/arch/arm/dts/rk3229-evb.dts b/arch/arm/dts/rk3229-evb.dts index 64f1c2d7da..ae0b0a4b8e 100644 --- a/arch/arm/dts/rk3229-evb.dts +++ b/arch/arm/dts/rk3229-evb.dts @@ -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 diff --git a/arch/arm/dts/rk3288-popmetal.dtsi b/arch/arm/dts/rk3288-popmetal.dtsi index dd6ce8b69e..63785eb55e 100644 --- a/arch/arm/dts/rk3288-popmetal.dtsi +++ b/arch/arm/dts/rk3288-popmetal.dtsi @@ -491,6 +491,10 @@ }; }; +&saradc { + status = "okay"; +}; + &tsadc { rockchip,hw-tshut-mode = <0>; rockchip,hw-tshut-polarity = <0>; diff --git a/arch/arm/dts/rk3328-evb.dts b/arch/arm/dts/rk3328-evb.dts index 8a14c653e4..3dd9d81961 100644 --- a/arch/arm/dts/rk3328-evb.dts +++ b/arch/arm/dts/rk3328-evb.dts @@ -42,6 +42,10 @@ }; }; +&saradc { + status = "okay"; +}; + &uart2 { status = "okay"; }; @@ -87,3 +91,121 @@ 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 */ + }; + }; +}; + diff --git a/arch/arm/dts/rk3368-px5-evb.dts b/arch/arm/dts/rk3368-px5-evb.dts index c7478f7ddb..e9c5ebad47 100644 --- a/arch/arm/dts/rk3368-px5-evb.dts +++ b/arch/arm/dts/rk3368-px5-evb.dts @@ -296,6 +296,10 @@ }; }; +&saradc { + status = "okay"; +}; + &tsadc { status = "okay"; rockchip,hw-tshut-mode = <0>; /* CRU */ diff --git a/arch/arm/dts/rk3368-sheep.dts b/arch/arm/dts/rk3368-sheep.dts index 7c190f7456..27befadd67 100644 --- a/arch/arm/dts/rk3368-sheep.dts +++ b/arch/arm/dts/rk3368-sheep.dts @@ -260,6 +260,10 @@ }; }; +&saradc { + status = "okay"; +}; + &tsadc { status = "okay"; rockchip,hw-tshut-mode = <0>; /* CRU */ diff --git a/arch/arm/dts/rk3399-evb.dts b/arch/arm/dts/rk3399-evb.dts index be0c6d98bd..0e5d8d79a1 100644 --- a/arch/arm/dts/rk3399-evb.dts +++ b/arch/arm/dts/rk3399-evb.dts @@ -149,6 +149,10 @@ status = "okay"; }; +&saradc { + status = "okay"; +}; + &sdmmc { bus-width = <4>; status = "okay"; diff --git a/arch/arm/dts/rk3399-puma.dtsi b/arch/arm/dts/rk3399-puma.dtsi index a04878e223..65ab380139 100644 --- a/arch/arm/dts/rk3399-puma.dtsi +++ b/arch/arm/dts/rk3399-puma.dtsi @@ -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 { @@ -100,6 +101,24 @@ 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"; @@ -458,7 +477,7 @@ }; &pcie_phy { - status = "okay"; + status = "okay"; }; &pmu_io_domains { @@ -485,7 +504,7 @@ }; &sdmmc { - u-boot,dm-pre-reloc; + u-boot,dm-pre-reloc; clock-frequency = <150000000>; clock-freq-min-max = <100000 150000000>; supports-sd; @@ -532,10 +551,15 @@ 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 = @@ -575,7 +599,7 @@ 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>; }; }; }; @@ -651,4 +675,3 @@ &spi5 { status = "okay"; }; - diff --git a/arch/arm/dts/rv1108-evb.dts b/arch/arm/dts/rv1108-evb.dts index 2b221b6d61..8e857b2c89 100644 --- a/arch/arm/dts/rv1108-evb.dts +++ b/arch/arm/dts/rv1108-evb.dts @@ -39,6 +39,10 @@ snps,reset-gpio = <&gpio1 RK_PC1 GPIO_ACTIVE_LOW>; }; +&saradc { + status = "okay"; +}; + &sfc { status = "okay"; flash@0 { diff --git a/arch/arm/dts/rv1108.dtsi b/arch/arm/dts/rv1108.dtsi index 3153dfe658..31b4d93b07 100644 --- a/arch/arm/dts/rv1108.dtsi +++ b/arch/arm/dts/rv1108.dtsi @@ -126,6 +126,17 @@ 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 index 0000000000..4c326e591e --- /dev/null +++ b/arch/arm/dts/tps6507x.dtsi @@ -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"; + }; + + }; +}; diff --git a/arch/arm/include/asm/arch-rockchip/bootrom.h b/arch/arm/include/asm/arch-rockchip/bootrom.h index 92eb8783a3..169cc5e50b 100644 --- a/arch/arm/include/asm/arch-rockchip/bootrom.h +++ b/arch/arm/include/asm/arch-rockchip/bootrom.h @@ -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 diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3368.h b/arch/arm/include/asm/arch-rockchip/cru_rk3368.h index 2b1197fd46..5f6a5fbe4c 100644 --- a/arch/arm/include/asm/arch-rockchip/cru_rk3368.h +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3368.h @@ -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), diff --git a/arch/arm/include/asm/arch-rockchip/cru_rv1108.h b/arch/arm/include/asm/arch-rockchip/cru_rv1108.h index 2a1ae692be..ad2dc96467 100644 --- a/arch/arm/include/asm/arch-rockchip/cru_rv1108.h +++ b/arch/arm/include/asm/arch-rockchip/cru_rv1108.h @@ -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, diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3036.h b/arch/arm/include/asm/arch-rockchip/grf_rk3036.h index 7625f249bd..d995b7db14 100644 --- a/arch/arm/include/asm/arch-rockchip/grf_rk3036.h +++ b/arch/arm/include/asm/arch-rockchip/grf_rk3036.h @@ -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 index 0000000000..b40da409d4 --- /dev/null +++ b/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h @@ -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 */ diff --git a/arch/arm/include/asm/arch-rockchip/sys_proto.h b/arch/arm/include/asm/arch-rockchip/sys_proto.h index 35423e1ba0..e428d59336 100644 --- a/arch/arm/include/asm/arch-rockchip/sys_proto.h +++ b/arch/arm/include/asm/arch-rockchip/sys_proto.h @@ -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 */ diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h index a20702e612..efc515eb33 100644 --- a/arch/arm/include/asm/armv7.h +++ b/arch/arm/include/asm/armv7.h @@ -61,6 +61,27 @@ #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 diff --git a/arch/arm/mach-omap2/omap3/Kconfig b/arch/arm/mach-omap2/omap3/Kconfig index 11f5f058b9..4dbf9a27da 100644 --- a/arch/arm/mach-omap2/omap3/Kconfig +++ b/arch/arm/mach-omap2/omap3/Kconfig @@ -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" diff --git a/arch/arm/mach-omap2/sec-common.c b/arch/arm/mach-omap2/sec-common.c index 52e1785b4a..2630e7d316 100644 --- a/arch/arm/mach-omap2/sec-common.c +++ b/arch/arm/mach-omap2/sec-common.c @@ -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 */ diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index 79e9704a2c..daafc8de6a 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -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 diff --git a/arch/arm/mach-rockchip/rk3188/Makefile b/arch/arm/mach-rockchip/rk3188/Makefile index 2dc9511de7..7fa010405b 100644 --- a/arch/arm/mach-rockchip/rk3188/Makefile +++ b/arch/arm/mach-rockchip/rk3188/Makefile @@ -6,6 +6,5 @@ ifndef CONFIG_TPL_BUILD obj-y += clk_rk3188.o -obj-y += sdram_rk3188.o obj-y += syscon_rk3188.o endif diff --git a/arch/arm/mach-rockchip/rk322x-board.c b/arch/arm/mach-rockchip/rk322x-board.c index dcd8cf805f..d44311457a 100644 --- a/arch/arm/mach-rockchip/rk322x-board.c +++ b/arch/arm/mach-rockchip/rk322x-board.c @@ -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: diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c index 6b7bf85d8d..7b7fd5a6f1 100644 --- a/arch/arm/mach-rockchip/rk3288-board-spl.c +++ b/arch/arm/mach-rockchip/rk3288-board-spl.c @@ -19,7 +19,10 @@ #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 index 0000000000..3d08b5b6d8 --- /dev/null +++ b/arch/arm/mach-rockchip/rk3288-board-tpl.c @@ -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"); +} diff --git a/arch/arm/mach-rockchip/rk3288/Kconfig b/arch/arm/mach-rockchip/rk3288/Kconfig index 4ad2940069..6beb26fd7a 100644 --- a/arch/arm/mach-rockchip/rk3288/Kconfig +++ b/arch/arm/mach-rockchip/rk3288/Kconfig @@ -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 diff --git a/arch/arm/mach-rockchip/rk3288/Makefile b/arch/arm/mach-rockchip/rk3288/Makefile index b5b28efbe8..a0033a0d84 100644 --- a/arch/arm/mach-rockchip/rk3288/Makefile +++ b/arch/arm/mach-rockchip/rk3288/Makefile @@ -6,5 +6,4 @@ obj-y += clk_rk3288.o obj-y += rk3288.o -obj-y += sdram_rk3288.o obj-y += syscon_rk3288.o diff --git a/arch/arm/mach-rockchip/rk3328/Makefile b/arch/arm/mach-rockchip/rk3328/Makefile index 72873e29e6..bbab036a12 100644 --- a/arch/arm/mach-rockchip/rk3328/Makefile +++ b/arch/arm/mach-rockchip/rk3328/Makefile @@ -6,5 +6,4 @@ obj-y += clk_rk3328.o obj-y += rk3328.o -obj-y += sdram_rk3328.o obj-y += syscon_rk3328.o diff --git a/arch/arm/mach-rockchip/rk3399-board-spl.c b/arch/arm/mach-rockchip/rk3399-board-spl.c index 3406156447..9c20f56dc9 100644 --- a/arch/arm/mach-rockchip/rk3399-board-spl.c +++ b/arch/arm/mach-rockchip/rk3399-board-spl.c @@ -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> @@ -19,9 +21,43 @@ 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) { diff --git a/arch/arm/mach-rockchip/rk3399/Makefile b/arch/arm/mach-rockchip/rk3399/Makefile index 793ce31c12..98ebeac340 100644 --- a/arch/arm/mach-rockchip/rk3399/Makefile +++ b/arch/arm/mach-rockchip/rk3399/Makefile @@ -6,5 +6,4 @@ obj-y += clk_rk3399.o obj-y += rk3399.o -obj-y += sdram_rk3399.o obj-y += syscon_rk3399.o diff --git a/arch/arm/mach-rockchip/spl-boot-order.c b/arch/arm/mach-rockchip/spl-boot-order.c index 4f78c72720..843998dfdc 100644 --- a/arch/arm/mach-rockchip/spl-boot-order.c +++ b/arch/arm/mach-rockchip/spl-boot-order.c @@ -10,6 +10,25 @@ #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; diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h index e8ee961526..25ef9a46c6 100644 --- a/arch/nds32/include/asm/io.h +++ b/arch/nds32/include/asm/io.h @@ -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; diff --git a/board/amarula/vyasa-rk3288/vyasa-rk3288.c b/board/amarula/vyasa-rk3288/vyasa-rk3288.c index ceee42c16e..7985671fbd 100644 --- a/board/amarula/vyasa-rk3288/vyasa-rk3288.c +++ b/board/amarula/vyasa-rk3288/vyasa-rk3288.c @@ -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 diff --git a/board/davinci/da8xxevm/Kconfig b/board/davinci/da8xxevm/Kconfig index bb1188b4ea..e0df97ca0e 100644 --- a/board/davinci/da8xxevm/Kconfig +++ b/board/davinci/da8xxevm/Kconfig @@ -33,6 +33,8 @@ config MAC_ADDR_IN_EEPROM endif +source "board/ti/common/Kconfig" + endif if TARGET_OMAPL138_LCDK diff --git a/board/davinci/da8xxevm/da850evm.c b/board/davinci/da8xxevm/da850evm.c index 516d86df50..83c9f2940f 100644 --- a/board/davinci/da8xxevm/da850evm.c +++ b/board/davinci/da8xxevm/da850evm.c @@ -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 diff --git a/board/logicpd/am3517evm/am3517evm.c b/board/logicpd/am3517evm/am3517evm.c index c18a5a3140..29f136a530 100644 --- a/board/logicpd/am3517evm/am3517evm.c +++ b/board/logicpd/am3517evm/am3517evm.c @@ -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; } diff --git a/board/rockchip/evb_rk3399/evb-rk3399.c b/board/rockchip/evb_rk3399/evb-rk3399.c index d50c59db8d..502dec325f 100644 --- a/board/rockchip/evb_rk3399/evb-rk3399.c +++ b/board/rockchip/evb_rk3399/evb-rk3399.c @@ -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(); +} diff --git a/board/theobroma-systems/lion_rk3368/fit_spl_atf.its b/board/theobroma-systems/lion_rk3368/fit_spl_atf.its index 405750f351..60daddcc44 100644 --- a/board/theobroma-systems/lion_rk3368/fit_spl_atf.its +++ b/board/theobroma-systems/lion_rk3368/fit_spl_atf.its @@ -27,8 +27,8 @@ type = "firmware"; arch = "arm64"; compression = "none"; - load = <0x00010000>; - entry = <0x00010000>; + load = <0x00100000>; + entry = <0x00100000>; }; fdt { diff --git a/board/theobroma-systems/puma_rk3399/puma-rk3399.c b/board/theobroma-systems/puma_rk3399/puma-rk3399.c index 45d56cd99e..2b4988e2d2 100644 --- a/board/theobroma-systems/puma_rk3399/puma-rk3399.c +++ b/board/theobroma-systems/puma_rk3399/puma-rk3399.c @@ -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", ®ulator); + 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", ®ulator); - 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) diff --git a/cmd/Kconfig b/cmd/Kconfig index d6d130edfa..3ef9b16b08 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -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 diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 3196d86040..b7087e3da8 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -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); } diff --git a/common/spl/Kconfig b/common/spl/Kconfig index b05ec21ed6..0bd8370337 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -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. diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index b2cccc6c6e..b57e0b04e4 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -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; diff --git a/configs/am335x_baltos_defconfig b/configs/am335x_baltos_defconfig index eb8338f0f1..2842694dbc 100644 --- a/configs/am335x_baltos_defconfig +++ b/configs/am335x_baltos_defconfig @@ -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 diff --git a/configs/am335x_boneblack_defconfig b/configs/am335x_boneblack_defconfig index b8526fc15e..2fc25fbaab 100644 --- a/configs/am335x_boneblack_defconfig +++ b/configs/am335x_boneblack_defconfig @@ -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 diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig index 0a239bb733..e8bcb6d0c8 100644 --- a/configs/am335x_boneblack_vboot_defconfig +++ b/configs/am335x_boneblack_vboot_defconfig @@ -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 diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig index 00c1af4344..b6a7cf0e5c 100644 --- a/configs/am335x_evm_defconfig +++ b/configs/am335x_evm_defconfig @@ -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 diff --git a/configs/am335x_evm_nor_defconfig b/configs/am335x_evm_nor_defconfig index 9f08edff4c..e2fc822c2f 100644 --- a/configs/am335x_evm_nor_defconfig +++ b/configs/am335x_evm_nor_defconfig @@ -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 diff --git a/configs/am335x_evm_spiboot_defconfig b/configs/am335x_evm_spiboot_defconfig index 501fb2b90f..a53e5aee83 100644 --- a/configs/am335x_evm_spiboot_defconfig +++ b/configs/am335x_evm_spiboot_defconfig @@ -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 diff --git a/configs/am335x_evm_usbspl_defconfig b/configs/am335x_evm_usbspl_defconfig index 7c351382d9..7b003ee777 100644 --- a/configs/am335x_evm_usbspl_defconfig +++ b/configs/am335x_evm_usbspl_defconfig @@ -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 diff --git a/configs/am335x_hs_evm_defconfig b/configs/am335x_hs_evm_defconfig index acdd56b435..af5233c5fc 100644 --- a/configs/am335x_hs_evm_defconfig +++ b/configs/am335x_hs_evm_defconfig @@ -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 index 0000000000..1c453fb23a --- /dev/null +++ b/configs/am335x_hs_evm_uart_defconfig @@ -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 diff --git a/configs/am335x_igep003x_defconfig b/configs/am335x_igep003x_defconfig index 1b03c334b4..f344a7367d 100644 --- a/configs/am335x_igep003x_defconfig +++ b/configs/am335x_igep003x_defconfig @@ -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 diff --git a/configs/am335x_shc_defconfig b/configs/am335x_shc_defconfig index c63e388ff5..0b29290cf5 100644 --- a/configs/am335x_shc_defconfig +++ b/configs/am335x_shc_defconfig @@ -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 diff --git a/configs/am335x_shc_ict_defconfig b/configs/am335x_shc_ict_defconfig index 1bcf683e35..73e0d2857f 100644 --- a/configs/am335x_shc_ict_defconfig +++ b/configs/am335x_shc_ict_defconfig @@ -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 diff --git a/configs/am335x_shc_netboot_defconfig b/configs/am335x_shc_netboot_defconfig index 9528a8cd5c..c4f2f55d05 100644 --- a/configs/am335x_shc_netboot_defconfig +++ b/configs/am335x_shc_netboot_defconfig @@ -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 diff --git a/configs/am335x_shc_prompt_defconfig b/configs/am335x_shc_prompt_defconfig index 8519282ecf..4eac21b4eb 100644 --- a/configs/am335x_shc_prompt_defconfig +++ b/configs/am335x_shc_prompt_defconfig @@ -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 diff --git a/configs/am335x_shc_sdboot_defconfig b/configs/am335x_shc_sdboot_defconfig index b00d6f6b22..e3a37db04a 100644 --- a/configs/am335x_shc_sdboot_defconfig +++ b/configs/am335x_shc_sdboot_defconfig @@ -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 diff --git a/configs/am335x_shc_sdboot_prompt_defconfig b/configs/am335x_shc_sdboot_prompt_defconfig index b00d6f6b22..e3a37db04a 100644 --- a/configs/am335x_shc_sdboot_prompt_defconfig +++ b/configs/am335x_shc_sdboot_prompt_defconfig @@ -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 diff --git a/configs/am335x_sl50_defconfig b/configs/am335x_sl50_defconfig index 3fa5d5e5cc..e9ca0d640f 100644 --- a/configs/am335x_sl50_defconfig +++ b/configs/am335x_sl50_defconfig @@ -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 diff --git a/configs/am3517_evm_defconfig b/configs/am3517_evm_defconfig index 920c61c391..8ab018656d 100644 --- a/configs/am3517_evm_defconfig +++ b/configs/am3517_evm_defconfig @@ -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 diff --git a/configs/am43xx_evm_defconfig b/configs/am43xx_evm_defconfig index 15c25d39f1..352ae16a9e 100644 --- a/configs/am43xx_evm_defconfig +++ b/configs/am43xx_evm_defconfig @@ -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 diff --git a/configs/am43xx_evm_usbhost_boot_defconfig b/configs/am43xx_evm_usbhost_boot_defconfig index 0bed335722..1a4856ca9e 100644 --- a/configs/am43xx_evm_usbhost_boot_defconfig +++ b/configs/am43xx_evm_usbhost_boot_defconfig @@ -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 diff --git a/configs/am43xx_hs_evm_defconfig b/configs/am43xx_hs_evm_defconfig index a4d23e10b6..9b2b1d7196 100644 --- a/configs/am43xx_hs_evm_defconfig +++ b/configs/am43xx_hs_evm_defconfig @@ -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 diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig index 0e4679abed..0c9daed5f5 100644 --- a/configs/am57xx_evm_defconfig +++ b/configs/am57xx_evm_defconfig @@ -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 diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig index e7638b88c2..b527e18463 100644 --- a/configs/am57xx_hs_evm_defconfig +++ b/configs/am57xx_hs_evm_defconfig @@ -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 diff --git a/configs/chiliboard_defconfig b/configs/chiliboard_defconfig index ea729b0155..d0f6f5fa11 100644 --- a/configs/chiliboard_defconfig +++ b/configs/chiliboard_defconfig @@ -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 diff --git a/configs/da850_am18xxevm_defconfig b/configs/da850_am18xxevm_defconfig index 27370e7c0c..0c60fef098 100644 --- a/configs/da850_am18xxevm_defconfig +++ b/configs/da850_am18xxevm_defconfig @@ -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 diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig index bfa5ea1c4b..d6eb4a5ba2 100644 --- a/configs/da850evm_defconfig +++ b/configs/da850evm_defconfig @@ -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 diff --git a/configs/da850evm_direct_nor_defconfig b/configs/da850evm_direct_nor_defconfig index 24ab89224d..3c8e7ad15a 100644 --- a/configs/da850evm_direct_nor_defconfig +++ b/configs/da850evm_direct_nor_defconfig @@ -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 diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig index 53903bf730..215fc61dc6 100644 --- a/configs/dra7xx_evm_defconfig +++ b/configs/dra7xx_evm_defconfig @@ -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 diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig index 06d8834119..c88229cead 100644 --- a/configs/dra7xx_hs_evm_defconfig +++ b/configs/dra7xx_hs_evm_defconfig @@ -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 diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig index 7bec001786..6d0f3af7a3 100644 --- a/configs/evb-rk3328_defconfig +++ b/configs/evb-rk3328_defconfig @@ -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 diff --git a/configs/lion-rk3368_defconfig b/configs/lion-rk3368_defconfig index c7ee7b3f97..985fb1ce98 100644 --- a/configs/lion-rk3368_defconfig +++ b/configs/lion-rk3368_defconfig @@ -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 diff --git a/configs/omap3_evm_defconfig b/configs/omap3_evm_defconfig index 962ffa0729..bae67de718 100644 --- a/configs/omap3_evm_defconfig +++ b/configs/omap3_evm_defconfig @@ -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 # " diff --git a/configs/omap3_logic_defconfig b/configs/omap3_logic_defconfig index b8f25883d8..adffcd981c 100644 --- a/configs/omap3_logic_defconfig +++ b/configs/omap3_logic_defconfig @@ -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 diff --git a/configs/omap3_overo_defconfig b/configs/omap3_overo_defconfig index 5d1cbe993a..4043c42e4b 100644 --- a/configs/omap3_overo_defconfig +++ b/configs/omap3_overo_defconfig @@ -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 diff --git a/configs/puma-rk3399_defconfig b/configs/puma-rk3399_defconfig index 2ab2516c01..62a8d7c859 100644 --- a/configs/puma-rk3399_defconfig +++ b/configs/puma-rk3399_defconfig @@ -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 diff --git a/configs/ti816x_evm_defconfig b/configs/ti816x_evm_defconfig index 4341d8d01f..d269e3641a 100644 --- a/configs/ti816x_evm_defconfig +++ b/configs/ti816x_evm_defconfig @@ -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 diff --git a/configs/vyasa-rk3288_defconfig b/configs/vyasa-rk3288_defconfig index 7db7b0b6f9..7bd6068e0c 100644 --- a/configs/vyasa-rk3288_defconfig +++ b/configs/vyasa-rk3288_defconfig @@ -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 diff --git a/disk/part_dos.c b/disk/part_dos.c index 7ede15ec26..1a36be0446 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -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; } diff --git a/disk/part_efi.c b/disk/part_efi.c index 2973d52f6a..208bb14ee8 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -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) { diff --git a/doc/README.rockchip b/doc/README.rockchip index 12fec38139..4b7be0b715 100644 --- a/doc/README.rockchip +++ b/doc/README.rockchip @@ -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 ================================= diff --git a/doc/device-tree-bindings/chosen.txt b/doc/device-tree-bindings/chosen.txt index 5625d210e8..c96b8f7109 100644 --- a/doc/device-tree-bindings/chosen.txt +++ b/doc/device-tree-bindings/chosen.txt @@ -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"; }; }; diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index e5335f7234..8094420548 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -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 diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile index cebf26de07..4b5aa693ec 100644 --- a/drivers/adc/Makefile +++ b/drivers/adc/Makefile @@ -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 index 0000000000..0e6271d097 --- /dev/null +++ b/drivers/adc/rockchip-saradc.c @@ -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), +}; diff --git a/drivers/clk/clk_stm32f7.c b/drivers/clk/clk_stm32f7.c index 255a583c95..68d6ba0461 100644 --- a/drivers/clk/clk_stm32f7.c +++ b/drivers/clk/clk_stm32f7.c @@ -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, }; diff --git a/drivers/clk/rockchip/clk_rk322x.c b/drivers/clk/rockchip/clk_rk322x.c index d7f6a3c313..e87267d239 100644 --- a/drivers/clk/rockchip/clk_rk322x.c +++ b/drivers/clk/rockchip/clk_rk322x.c @@ -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; } diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c index 478195b10b..a133810bf6 100644 --- a/drivers/clk/rockchip/clk_rk3288.c +++ b/drivers/clk/rockchip/clk_rk3288.c @@ -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; } diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c index c3a6650de0..540d9104c3 100644 --- a/drivers/clk/rockchip/clk_rk3328.c +++ b/drivers/clk/rockchip/clk_rk3328.c @@ -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; } diff --git a/drivers/clk/rockchip/clk_rk3368.c b/drivers/clk/rockchip/clk_rk3368.c index e2747816b9..3a12be7728 100644 --- a/drivers/clk/rockchip/clk_rk3368.c +++ b/drivers/clk/rockchip/clk_rk3368.c @@ -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; } diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c index 9d963be552..50faf5d193 100644 --- a/drivers/clk/rockchip/clk_rk3399.c +++ b/drivers/clk/rockchip/clk_rk3399.c @@ -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; } diff --git a/drivers/clk/rockchip/clk_rv1108.c b/drivers/clk/rockchip/clk_rv1108.c index cf966bbdc3..86e73e414c 100644 --- a/drivers/clk/rockchip/clk_rv1108.c +++ b/drivers/clk/rockchip/clk_rv1108.c @@ -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; } diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c index 840b3f6046..332280c220 100644 --- a/drivers/i2c/rk_i2c.c +++ b/drivers/i2c/rk_i2c.c @@ -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" }, { } }; diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index fa24c52351..24b4eadd2a 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -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 diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index a6becb2309..d505f37f01 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -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 diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c index f83c1d7241..72d1c646a2 100644 --- a/drivers/mmc/sdhci-cadence.c +++ b/drivers/mmc/sdhci-cadence.c @@ -23,6 +23,18 @@ #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 index 0000000000..0e1f40b569 --- /dev/null +++ b/drivers/mmc/stm32_sdmmc2.c @@ -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), +}; diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 0786ad0d5f..0d1203cb76 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -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"); diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3368.c b/drivers/pinctrl/rockchip/pinctrl_rk3368.c index b1f5704164..25249e377a 100644 --- a/drivers/pinctrl/rockchip/pinctrl_rk3368.c +++ b/drivers/pinctrl/rockchip/pinctrl_rk3368.c @@ -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); diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 2cfade1cb2..8892fa14e0 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -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 diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile index b09d03c2c9..45b5fe7247 100644 --- a/drivers/ram/rockchip/Makefile +++ b/drivers/ram/rockchip/Makefile @@ -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 diff --git a/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c b/drivers/ram/rockchip/sdram_rk3188.c index 9d8b225dfa..365d00ef54 100644 --- a/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c +++ b/drivers/ram/rockchip/sdram_rk3188.c @@ -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 index 0000000000..cc3138b21d --- /dev/null +++ b/drivers/ram/rockchip/sdram_rk322x.c @@ -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 *)¶ms->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 *)¶ms->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 *)¶ms->base, + sizeof(params->base) / sizeof(u32)); + if (ret) { + printf("%s: Cannot read rockchip,sdram-params\n", __func__); + return -EINVAL; + } + ret = regmap_init_mem(dev, ¶ms->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 +}; + diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/drivers/ram/rockchip/sdram_rk3288.c index 95efb117fc..95efb117fc 100644 --- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c +++ b/drivers/ram/rockchip/sdram_rk3288.c diff --git a/arch/arm/mach-rockchip/rk3328/sdram_rk3328.c b/drivers/ram/rockchip/sdram_rk3328.c index 9637a35e23..9637a35e23 100644 --- a/arch/arm/mach-rockchip/rk3328/sdram_rk3328.c +++ b/drivers/ram/rockchip/sdram_rk3328.c diff --git a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c index 5ed4b03837..5ed4b03837 100644 --- a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c +++ b/drivers/ram/rockchip/sdram_rk3399.c diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 291ef9576a..eda252d0b3 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -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" }, { } }; diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index daf021b647..b6535705a5 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -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[]; diff --git a/include/blk.h b/include/blk.h index 1965812a9d..41b4d7efa8 100644 --- a/include/blk.h +++ b/include/blk.h @@ -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" @@ -41,6 +43,17 @@ enum if_type { #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 diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index 9ed6b9892c..e0d0034ed3 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -112,6 +112,11 @@ #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 " \ diff --git a/include/configs/am3517_evm.h b/include/configs/am3517_evm.h index 708a98f827..adb33a9e3e 100644 --- a/include/configs/am3517_evm.h +++ b/include/configs/am3517_evm.h @@ -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 @@ -33,16 +34,6 @@ /* 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 @@ -250,8 +240,6 @@ #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 diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h index b84f6e3480..7ee69b0c78 100644 --- a/include/configs/am43xx_evm.h +++ b/include/configs/am43xx_evm.h @@ -326,4 +326,9 @@ #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 */ diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h index 0c70c53050..bf555ccdc2 100644 --- a/include/configs/am57xx_evm.h +++ b/include/configs/am57xx_evm.h @@ -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};" \ diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h index c05c64cad7..821b1fe534 100644 --- a/include/configs/da850evm.h +++ b/include/configs/da850evm.h @@ -21,6 +21,16 @@ #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 */ #define CONFIG_MACH_DAVINCI_DA850_EVM @@ -130,18 +140,23 @@ /* * 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 @@ -152,11 +167,10 @@ /* * 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 @@ -234,6 +248,17 @@ #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 /* @@ -257,7 +282,29 @@ #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 diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h index 6c0fc35d3a..1555fc1b50 100644 --- a/include/configs/dra7xx_evm.h +++ b/include/configs/dra7xx_evm.h @@ -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};" \ diff --git a/include/configs/evb_rk3399.h b/include/configs/evb_rk3399.h index 015f25a774..66ead6c117 100644 --- a/include/configs/evb_rk3399.h +++ b/include/configs/evb_rk3399.h @@ -10,12 +10,6 @@ #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) diff --git a/include/configs/k2g_evm.h b/include/configs/k2g_evm.h index 1950740405..df81c09d86 100644 --- a/include/configs/k2g_evm.h +++ b/include/configs/k2g_evm.h @@ -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" \ diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h index e9e3c4013c..34f255847a 100644 --- a/include/configs/rk3288_common.h +++ b/include/configs/rk3288_common.h @@ -32,7 +32,11 @@ #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 diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h index 2b2b85d085..53046a2110 100644 --- a/include/configs/ti_armv7_keystone2.h +++ b/include/configs/ti_armv7_keystone2.h @@ -270,7 +270,7 @@ "${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" \ diff --git a/include/configs/vyasa-rk3288.h b/include/configs/vyasa-rk3288.h index 9d6c80f549..8774e42430 100644 --- a/include/configs/vyasa-rk3288.h +++ b/include/configs/vyasa-rk3288.h @@ -20,4 +20,21 @@ #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 diff --git a/include/dt-bindings/clock/rv1108-cru.h b/include/dt-bindings/clock/rv1108-cru.h index d2ad3bb52d..7defc6b282 100644 --- a/include/dt-bindings/clock/rv1108-cru.h +++ b/include/dt-bindings/clock/rv1108-cru.h @@ -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 diff --git a/include/efi.h b/include/efi.h index 02b78b31b1..dc8edc8743 100644 --- a/include/efi.h +++ b/include/efi.h @@ -28,6 +28,10 @@ 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 * diff --git a/include/efi_api.h b/include/efi_api.h index ec1b321e8e..c3b9032a48 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -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 diff --git a/include/efi_loader.h b/include/efi_loader.h index 1179234f68..2f081f8996 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -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 index 0000000000..76304a2b2a --- /dev/null +++ b/include/efi_selftest.h @@ -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 */ diff --git a/include/environment/ti/boot.h b/include/environment/ti/boot.h index 5b1b97bafe..799d9840aa 100644 --- a/include/environment/ti/boot.h +++ b/include/environment/ti/boot.h @@ -29,7 +29,14 @@ "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 @@ -93,10 +99,7 @@ "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; " \ "" diff --git a/include/part.h b/include/part.h index 86117a7ce5..b2e820ef8a 100644 --- a/include/part.h +++ b/include/part.h @@ -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 diff --git a/include/part_efi.h b/include/part_efi.h index 317c044795..31e6bc6e14 100644 --- a/include/part_efi.h +++ b/include/part_efi.h @@ -58,10 +58,6 @@ /* 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 */ diff --git a/include/pe.h b/include/pe.h index deb35a0ea4..4ef3e92efa 100644 --- a/include/pe.h +++ b/include/pe.h @@ -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; diff --git a/lib/Makefile b/lib/Makefile index faf4538fb5..8e1c9d1bb7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -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/ diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 30bf343a36..ddb978f650 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -10,12 +10,14 @@ 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 index 0000000000..857d88a879 --- /dev/null +++ b/lib/efi_loader/efi_bootmgr.c @@ -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; +} diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 43f32385fa..9e741c3cf3 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -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: diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 3fc82b8726..fd5398d61d 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -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 index 0000000000..5d5c3b3464 --- /dev/null +++ b/lib/efi_loader/efi_device_path.c @@ -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; +} diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 4b2f43f0c8..1a5ef3919b 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -15,81 +15,199 @@ 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) { diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index ed06485e33..eb9ce772d1 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -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 index 0000000000..52a4e7438e --- /dev/null +++ b/lib/efi_loader/efi_file.c @@ -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; +} diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index f961407f50..af29cc4f04 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -15,8 +15,12 @@ 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 = §ions[i]; diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 9e079f1fa3..d47759e08e 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -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; diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 0b949d86e8..91f1e4a69e 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -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; } diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index ad7f3754bd..8104e08c46 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -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 index 0000000000..6c177da3a6 --- /dev/null +++ b/lib/efi_loader/efi_variable.c @@ -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 index 0000000000..3b5f3a1230 --- /dev/null +++ b/lib/efi_selftest/Kconfig @@ -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 index 0000000000..30f1960933 --- /dev/null +++ b/lib/efi_selftest/Makefile @@ -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 index 0000000000..efec832e98 --- /dev/null +++ b/lib/efi_selftest/efi_selftest.c @@ -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 index 0000000000..7b5b724a61 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_console.c @@ -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 index 0000000000..c4f66952b9 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_events.c @@ -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 index 0000000000..60271e6180 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_exitbootservices.c @@ -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 index 0000000000..90ace0f51e --- /dev/null +++ b/lib/efi_selftest/efi_selftest_tpl.c @@ -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, +}; diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 2a7ed70cf2..861a3dc3f1 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -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 index 0000000000..400ef35169 --- /dev/null +++ b/scripts/spelling.txt @@ -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 diff --git a/test/py/README.md b/test/py/README.md index 829c7efbb2..ea4b66a41c 100644 --- a/test/py/README.md +++ b/test/py/README.md @@ -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: diff --git a/test/py/conftest.py b/test/py/conftest.py index 65e1d75626..6e66a48c15 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -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. diff --git a/test/py/multiplexed_log.py b/test/py/multiplexed_log.py index bf926c3e77..5bc1bc49d4 100644 --- a/test/py/multiplexed_log.py +++ b/test/py/multiplexed_log.py @@ -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): diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py index fba67d585b..8f6877c5c2 100644 --- a/test/py/tests/test_dfu.py +++ b/test/py/tests/test_dfu.py @@ -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 index 0000000000..76e282a6c7 --- /dev/null +++ b/test/py/tests/test_efi_selftest.py @@ -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(); diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index 7e6b96dae4..4b32bb18b8 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -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 diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py index e2bbd08e6d..ec25fbbc5a 100644 --- a/test/py/tests/test_gpt.py +++ b/test/py/tests/test_gpt.py @@ -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.""" diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py index 6e62820743..c4da79d114 100644 --- a/test/py/tests/test_vboot.py +++ b/test/py/tests/test_vboot.py @@ -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'. diff --git a/tools/buildman/kconfiglib.py b/tools/buildman/kconfiglib.py index 352ad438ee..68b470a3a7 100644 --- a/tools/buildman/kconfiglib.py +++ b/tools/buildman/kconfiglib.py @@ -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 diff --git a/tools/moveconfig.py b/tools/moveconfig.py index 6f549a51c1..e3116461ba 100755 --- a/tools/moveconfig.py +++ b/tools/moveconfig.py @@ -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 diff --git a/tools/rkcommon.c b/tools/rkcommon.c index 04e8272fd5..1a24e16589 100644 --- a/tools/rkcommon.c +++ b/tools/rkcommon.c @@ -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 }, |