diff options
308 files changed, 11285 insertions, 4023 deletions
@@ -42,6 +42,7 @@ Durga Challa <durga.challa@amd.com> <vnsl.durga.challa@xilinx.com> Eugen Hristev <eugen.hristev@linaro.org> <eugen.hristev@microchip.com> Eugen Hristev <eugen.hristev@linaro.org> <eugen.hristev@collabora.com> Fabio Estevam <fabio.estevam@nxp.com> +Greg Malysa <malysagreg@gmail.com> <greg.malysa@timesys.com> Harini Katakam <harini.katakam@amd.com> <harini.katakam@xilinx.com> Harsha <harsha.harsha@amd.com> <harsha.harsha@xilinx.com> Heiko Stuebner <heiko.stuebner@cherry.de> <heiko.stuebner@theobroma-systems.com> @@ -123,6 +124,7 @@ Srinivas Neeli <srinivas.neeli@amd.com> <srinivas.neeli@xilinx.com> Stefan Roese <sr@denx.de> <stroese> Stefano Babic <sbabic@denx.de> Stefano Stabellini <stefano.stabellini@amd.com> <stefano.stabellini@xilinx.com> +Sumit Garg <sumit.garg@kernel.org> <sumit.garg@linaro.org> Tom Rini <trini@konsulko.com> <trini@ti.com> Tomas Thoresen <tomas.thoresen@amd.com> <tomast@xilinx.com> TsiChung Liew <Tsi-Chung.Liew@freescale.com> diff --git a/MAINTAINERS b/MAINTAINERS index 687262b355d..e2339ecd2d0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -617,7 +617,7 @@ F: arch/arm/dts/am335x-sancloud* ARM SC5XX M: Nathan Barrett-Morrison <nathan.morrison@timesys.com> -M: Greg Malysa <greg.malysa@timesys.com> +M: Greg Malysa <malysagreg@gmail.com> M: Ian Roberts <ian.roberts@timesys.com> M: Vasileios Bimpikas <vasileios.bimpikas@analog.com> M: Utsav Agarwal <utsav.agarwal@analog.com> @@ -631,17 +631,30 @@ F: arch/arm/mach-sc5xx/ F: board/adi/ F: doc/device-tree-bindings/arm/adi/adi,sc5xx.yaml F: doc/device-tree-bindings/clock/adi,sc5xx-clocks.yaml +F: doc/device-tree-bindings/pinctrl/adi,adsp-pinctrl.yaml F: doc/device-tree-bindings/timer/adi,sc5xx-gptimer.yaml F: drivers/clk/adi/ +F: drivers/dma/adi_dma.c +F: drivers/gpio/adp5588_gpio.c +F: drivers/gpio/gpio-adi-adsp.c +F: drivers/i2c/adi_i2c.c +F: drivers/mmc/adi_sdhci.c +F: drivers/net/dwc_eth_qos_adi.c +F: drivers/pinctrl/pinctrl-adi-adsp.c +F: drivers/remoteproc/adi_sc5xx_rproc.c F: drivers/serial/serial_adi_uart4.c +F: drivers/spi/adi_spi3.c F: drivers/timer/adi_sc5xx_timer.c +F: drivers/usb/musb-new/sc5xx.c +F: drivers/watchdog/adi_wdt.c F: include/configs/sc5* +F: include/dt-bindings/pinctrl/adi-adsp.h F: include/env/adi/ ARM SNAPDRAGON M: Caleb Connolly <caleb.connolly@linaro.org> M: Neil Armstrong <neil.armstrong@linaro.org> -R: Sumit Garg <sumit.garg@linaro.org> +R: Sumit Garg <sumit.garg@kernel.org> L: u-boot-qcom@groups.io S: Maintained T: git https://source.denx.de/u-boot/custodians/u-boot-snapdragon.git @@ -1045,9 +1058,10 @@ F: common/cyclic.c F: include/cyclic.h DEVICETREE REBASING SUBTREE -M: Sumit Garg <sumit.garg@linaro.org> +M: Sumit Garg <sumit.garg@kernel.org> S: Maintained F: dts/upstream/ +N: OF_UPSTREAM DFU M: Lukasz Majewski <lukma@denx.de> @@ -1453,7 +1467,7 @@ S: Maintained F: tools/patman/ PCIe DWC IMX -M: Sumit Garg <sumit.garg@linaro.org> +M: Sumit Garg <sumit.garg@kernel.org> S: Maintained F: drivers/pci/pcie_dw_imx.c F: drivers/phy/phy-imx8m-pcie.c @@ -3,7 +3,7 @@ VERSION = 2025 PATCHLEVEL = 04 SUBLEVEL = -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = # *DOCUMENTATION* @@ -829,7 +829,7 @@ KBUILD_HOSTCFLAGS += $(if $(CONFIG_TOOLS_DEBUG),-g) UBOOTINCLUDE := \ -Iinclude \ $(if $(KBUILD_SRC), -I$(srctree)/include) \ - $(if $(CONFIG_MBEDTLS_LIB), \ + $(if $(CONFIG_$(XPL_)MBEDTLS_LIB), \ "-DMBEDTLS_CONFIG_FILE=\"mbedtls_def_config.h\"" \ -I$(srctree)/lib/mbedtls \ -I$(srctree)/lib/mbedtls/port \ @@ -878,7 +878,6 @@ libs-y += drivers/usb/dwc3/ libs-y += drivers/usb/common/ libs-y += drivers/usb/emul/ libs-y += drivers/usb/eth/ -libs-$(CONFIG_USB_DEVICE) += drivers/usb/gadget/ libs-$(CONFIG_USB_GADGET) += drivers/usb/gadget/ libs-$(CONFIG_USB_GADGET) += drivers/usb/gadget/udc/ libs-y += drivers/usb/host/ @@ -1864,6 +1863,7 @@ quiet_cmd_gen_envp = ENVP $@ $(CPP) -P $(cpp_flags) -x assembler-with-cpp -undef \ -D__ASSEMBLY__ \ -D__UBOOT_CONFIG__ \ + -DDEFAULT_DEVICE_TREE=$(subst ",,$(CONFIG_DEFAULT_DEVICE_TREE)) \ -I . -I include -I $(srctree)/include \ -include linux/kconfig.h -include include/config.h \ -I$(srctree)/arch/$(ARCH)/include \ diff --git a/arch/arm/cpu/armv7/exception_level.c b/arch/arm/cpu/armv7/exception_level.c index 7baade61b07..a55c158ce51 100644 --- a/arch/arm/cpu/armv7/exception_level.c +++ b/arch/arm/cpu/armv7/exception_level.c @@ -11,9 +11,9 @@ #include <bootm.h> #include <cpu_func.h> #include <log.h> +#include <setjmp.h> #include <asm/armv7.h> #include <asm/secure.h> -#include <asm/setjmp.h> /** * entry_non_secure() - entry point when switching to non-secure mode @@ -24,7 +24,7 @@ * * @non_secure_jmp: jump buffer for restoring stack and registers */ -static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) +static void entry_non_secure(jmp_buf non_secure_jmp) { dcache_enable(); debug("Reached non-secure mode\n"); @@ -42,10 +42,10 @@ static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) void switch_to_non_secure_mode(void) { static bool is_nonsec; - struct jmp_buf_data non_secure_jmp; + jmp_buf non_secure_jmp; if (armv7_boot_nonsec() && !is_nonsec) { - if (setjmp(&non_secure_jmp)) + if (setjmp(non_secure_jmp)) return; dcache_disable(); /* flush cache before switch to HYP */ armv7_init_nonsec(); diff --git a/arch/arm/cpu/armv8/exception_level.c b/arch/arm/cpu/armv8/exception_level.c index 85c78f55789..746737861e7 100644 --- a/arch/arm/cpu/armv8/exception_level.c +++ b/arch/arm/cpu/armv8/exception_level.c @@ -11,8 +11,8 @@ #include <bootm.h> #include <cpu_func.h> #include <log.h> +#include <setjmp.h> #include <asm/cache.h> -#include <asm/setjmp.h> /** * entry_non_secure() - entry point when switching to non-secure mode @@ -23,7 +23,7 @@ * * @non_secure_jmp: jump buffer for restoring stack and registers */ -static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) +static void entry_non_secure(jmp_buf non_secure_jmp) { dcache_enable(); debug("Reached non-secure mode\n"); @@ -42,11 +42,11 @@ static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) */ void switch_to_non_secure_mode(void) { - struct jmp_buf_data non_secure_jmp; + jmp_buf non_secure_jmp; /* On AArch64 we need to make sure we call our payload in < EL3 */ if (current_el() == 3) { - if (setjmp(&non_secure_jmp)) + if (setjmp(non_secure_jmp)) return; dcache_disable(); /* flush cache before switch to EL2 */ diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 85a03b512b6..73231824526 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -121,6 +121,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += \ tegra124-nyan-big.dtb \ tegra124-cei-tk1-som.dtb \ tegra124-venice2.dtb \ + tegra124-xiaomi-mocha.dtb \ tegra186-p2771-0000-000.dtb \ tegra186-p2771-0000-500.dtb \ tegra210-p2371-0000.dtb \ diff --git a/arch/arm/dts/k3-am62-lp4-50-800-800.dtsi b/arch/arm/dts/k3-am62-lp4-50-800-800.dtsi index c255ae6530f..ee9e213be84 100644 --- a/arch/arm/dts/k3-am62-lp4-50-800-800.dtsi +++ b/arch/arm/dts/k3-am62-lp4-50-800-800.dtsi @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* * This file was generated with the - * AM62x SysConfig DDR Subsystem Register Configuration Tool v0.09.07 - * Wed Mar 01 2023 17:52:11 GMT-0600 (Central Standard Time) + * AM623/AM625 SysConfig DDR Configuration Tool for AM64x, AM625, AM623, AM62Ax, AM62Px v0.10.02 + * Tue Sep 17 2024 13:07:19 GMT+0530 (India Standard Time) * DDR Type: LPDDR4 * F0 = 50MHz F1 = NA F2 = 800MHz * Density (per channel): 16Gb @@ -13,6 +13,8 @@ #define DDRSS_PLL_FHS_CNT 3 #define DDRSS_PLL_FREQUENCY_1 400000000 #define DDRSS_PLL_FREQUENCY_2 400000000 +#define DDRSS_SDRAM_IDX 15 +#define DDRSS_REGION_IDX 16 #define DDRSS_CTL_0_DATA 0x00000B00 #define DDRSS_CTL_1_DATA 0x00000000 @@ -847,7 +849,7 @@ #define DDRSS_PHY_62_DATA 0x00000000 #define DDRSS_PHY_63_DATA 0x00000000 #define DDRSS_PHY_64_DATA 0x00000000 -#define DDRSS_PHY_65_DATA 0x00000004 +#define DDRSS_PHY_65_DATA 0x00000104 #define DDRSS_PHY_66_DATA 0x00000000 #define DDRSS_PHY_67_DATA 0x00000000 #define DDRSS_PHY_68_DATA 0x00000000 @@ -869,7 +871,7 @@ #define DDRSS_PHY_84_DATA 0x00100010 #define DDRSS_PHY_85_DATA 0x00100010 #define DDRSS_PHY_86_DATA 0x00100010 -#define DDRSS_PHY_87_DATA 0x02020010 +#define DDRSS_PHY_87_DATA 0x02000010 #define DDRSS_PHY_88_DATA 0x51516041 #define DDRSS_PHY_89_DATA 0x31C06000 #define DDRSS_PHY_90_DATA 0x07AB0340 @@ -1103,7 +1105,7 @@ #define DDRSS_PHY_318_DATA 0x00000000 #define DDRSS_PHY_319_DATA 0x00000000 #define DDRSS_PHY_320_DATA 0x00000000 -#define DDRSS_PHY_321_DATA 0x00000004 +#define DDRSS_PHY_321_DATA 0x00000104 #define DDRSS_PHY_322_DATA 0x00000000 #define DDRSS_PHY_323_DATA 0x00000000 #define DDRSS_PHY_324_DATA 0x00000000 @@ -1125,7 +1127,7 @@ #define DDRSS_PHY_340_DATA 0x00100010 #define DDRSS_PHY_341_DATA 0x00100010 #define DDRSS_PHY_342_DATA 0x00100010 -#define DDRSS_PHY_343_DATA 0x02020010 +#define DDRSS_PHY_343_DATA 0x02000010 #define DDRSS_PHY_344_DATA 0x51516041 #define DDRSS_PHY_345_DATA 0x31C06000 #define DDRSS_PHY_346_DATA 0x07AB0340 @@ -2181,7 +2183,7 @@ #define DDRSS_PHY_1396_DATA 0x0089FF00 #define DDRSS_PHY_1397_DATA 0x000C3F11 #define DDRSS_PHY_1398_DATA 0x01990000 -#define DDRSS_PHY_1399_DATA 0x000C3F11 +#define DDRSS_PHY_1399_DATA 0x000C3F91 #define DDRSS_PHY_1400_DATA 0x01990000 #define DDRSS_PHY_1401_DATA 0x3F0DFF11 #define DDRSS_PHY_1402_DATA 0x01990000 diff --git a/arch/arm/dts/k3-am625-phycore-som-binman.dtsi b/arch/arm/dts/k3-am625-phycore-som-binman.dtsi index 31456d23167..4a65427e877 100644 --- a/arch/arm/dts/k3-am625-phycore-som-binman.dtsi +++ b/arch/arm/dts/k3-am625-phycore-som-binman.dtsi @@ -321,8 +321,11 @@ compression = "none"; load = <0x8F000000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_rtc_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_rtc_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-rtc.dtbo"; }; }; @@ -333,8 +336,11 @@ compression = "none"; load = <0x8F001000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_spi_not_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_spi_not_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-spi-nor.dtbo"; }; }; @@ -345,8 +351,11 @@ compression = "none"; load = <0x8F002000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_eth_phy_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_eth_phy_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-eth-phy.dtbo"; }; }; @@ -357,8 +366,11 @@ compression = "none"; load = <0x8F003000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_qspi_nor_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_qspi_nor_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-qspi-nor.dtbo"; }; }; diff --git a/arch/arm/dts/k3-am62a-ddr-1866mhz-32bit.dtsi b/arch/arm/dts/k3-am62a-ddr-1866mhz-32bit.dtsi index 9f50d7eae69..35202651221 100644 --- a/arch/arm/dts/k3-am62a-ddr-1866mhz-32bit.dtsi +++ b/arch/arm/dts/k3-am62a-ddr-1866mhz-32bit.dtsi @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* * This file was generated with the - * AM62A SysConfig DDR Subsystem Register Configuration Tool v0.09.01 - * Wed Aug 10 2022 17:34:54 GMT-0500 (Central Daylight Time) + * AM62Ax SysConfig DDR Configuration Tool for AM64x, AM625, AM623, AM62Ax, AM62Px v0.10.02 + * Tue Sep 17 2024 10:55:17 GMT+0530 (India Standard Time) * DDR Type: LPDDR4 * F0 = 50MHz F1 = NA F2 = 1866MHz * Density (per channel): 8Gb @@ -12,6 +12,8 @@ #define DDRSS_PLL_FHS_CNT 5 #define DDRSS_PLL_FREQUENCY_1 933000000 #define DDRSS_PLL_FREQUENCY_2 933000000 +#define DDRSS_SDRAM_IDX 16 +#define DDRSS_REGION_IDX 17 #define DDRSS_CTL_0_DATA 0x00000B00 #define DDRSS_CTL_1_DATA 0x00000000 @@ -402,10 +404,10 @@ #define DDRSS_CTL_386_DATA 0x01090903 #define DDRSS_CTL_387_DATA 0x05020201 #define DDRSS_CTL_388_DATA 0x0E081B1B -#define DDRSS_CTL_389_DATA 0x0008030E -#define DDRSS_CTL_390_DATA 0x0B12030E -#define DDRSS_CTL_391_DATA 0x0B120314 -#define DDRSS_CTL_392_DATA 0x12120814 +#define DDRSS_CTL_389_DATA 0x0008040E +#define DDRSS_CTL_390_DATA 0x0B120406 +#define DDRSS_CTL_391_DATA 0x0B120406 +#define DDRSS_CTL_392_DATA 0x12120806 #define DDRSS_CTL_393_DATA 0x01000000 #define DDRSS_CTL_394_DATA 0x07030701 #define DDRSS_CTL_395_DATA 0x04000103 @@ -417,8 +419,8 @@ #define DDRSS_CTL_401_DATA 0x00000200 #define DDRSS_CTL_402_DATA 0x00000693 #define DDRSS_CTL_403_DATA 0x00000E9C -#define DDRSS_CTL_404_DATA 0x03050202 -#define DDRSS_CTL_405_DATA 0x37200201 +#define DDRSS_CTL_404_DATA 0x03000202 +#define DDRSS_CTL_405_DATA 0x37200404 #define DDRSS_CTL_406_DATA 0x000038C8 #define DDRSS_CTL_407_DATA 0x00000200 #define DDRSS_CTL_408_DATA 0x00000200 @@ -426,8 +428,8 @@ #define DDRSS_CTL_410_DATA 0x00000200 #define DDRSS_CTL_411_DATA 0x0000FF84 #define DDRSS_CTL_412_DATA 0x000237D0 -#define DDRSS_CTL_413_DATA 0x111F0402 -#define DDRSS_CTL_414_DATA 0x37200C0D +#define DDRSS_CTL_413_DATA 0x111A0402 +#define DDRSS_CTL_414_DATA 0x37200C09 #define DDRSS_CTL_415_DATA 0x000038C8 #define DDRSS_CTL_416_DATA 0x00000200 #define DDRSS_CTL_417_DATA 0x00000200 @@ -435,8 +437,8 @@ #define DDRSS_CTL_419_DATA 0x00000200 #define DDRSS_CTL_420_DATA 0x0000FF84 #define DDRSS_CTL_421_DATA 0x000237D0 -#define DDRSS_CTL_422_DATA 0x111F0402 -#define DDRSS_CTL_423_DATA 0x00200C0D +#define DDRSS_CTL_422_DATA 0x111A0402 +#define DDRSS_CTL_423_DATA 0x00200C09 #define DDRSS_CTL_424_DATA 0x00000000 #define DDRSS_CTL_425_DATA 0x02000A00 #define DDRSS_CTL_426_DATA 0x00050003 @@ -939,7 +941,7 @@ #define DDRSS_PHY_64_DATA 0x00000000 #define DDRSS_PHY_65_DATA 0x00000000 #define DDRSS_PHY_66_DATA 0x00000000 -#define DDRSS_PHY_67_DATA 0x00000004 +#define DDRSS_PHY_67_DATA 0x00000104 #define DDRSS_PHY_68_DATA 0x00000000 #define DDRSS_PHY_69_DATA 0x00000000 #define DDRSS_PHY_70_DATA 0x00000000 @@ -964,7 +966,7 @@ #define DDRSS_PHY_89_DATA 0x00100010 #define DDRSS_PHY_90_DATA 0x00100010 #define DDRSS_PHY_91_DATA 0x00100010 -#define DDRSS_PHY_92_DATA 0x02040010 +#define DDRSS_PHY_92_DATA 0x02000010 #define DDRSS_PHY_93_DATA 0x00000005 #define DDRSS_PHY_94_DATA 0x51516042 #define DDRSS_PHY_95_DATA 0x31C06000 @@ -1195,7 +1197,7 @@ #define DDRSS_PHY_320_DATA 0x00000000 #define DDRSS_PHY_321_DATA 0x00000000 #define DDRSS_PHY_322_DATA 0x00000000 -#define DDRSS_PHY_323_DATA 0x00000004 +#define DDRSS_PHY_323_DATA 0x00000104 #define DDRSS_PHY_324_DATA 0x00000000 #define DDRSS_PHY_325_DATA 0x00000000 #define DDRSS_PHY_326_DATA 0x00000000 @@ -1220,7 +1222,7 @@ #define DDRSS_PHY_345_DATA 0x00100010 #define DDRSS_PHY_346_DATA 0x00100010 #define DDRSS_PHY_347_DATA 0x00100010 -#define DDRSS_PHY_348_DATA 0x02040010 +#define DDRSS_PHY_348_DATA 0x02000010 #define DDRSS_PHY_349_DATA 0x00000005 #define DDRSS_PHY_350_DATA 0x51516042 #define DDRSS_PHY_351_DATA 0x31C06000 @@ -1451,7 +1453,7 @@ #define DDRSS_PHY_576_DATA 0x00000000 #define DDRSS_PHY_577_DATA 0x00000000 #define DDRSS_PHY_578_DATA 0x00000000 -#define DDRSS_PHY_579_DATA 0x00000004 +#define DDRSS_PHY_579_DATA 0x00000104 #define DDRSS_PHY_580_DATA 0x00000000 #define DDRSS_PHY_581_DATA 0x00000000 #define DDRSS_PHY_582_DATA 0x00000000 @@ -1476,7 +1478,7 @@ #define DDRSS_PHY_601_DATA 0x00100010 #define DDRSS_PHY_602_DATA 0x00100010 #define DDRSS_PHY_603_DATA 0x00100010 -#define DDRSS_PHY_604_DATA 0x02040010 +#define DDRSS_PHY_604_DATA 0x02000010 #define DDRSS_PHY_605_DATA 0x00000005 #define DDRSS_PHY_606_DATA 0x51516042 #define DDRSS_PHY_607_DATA 0x31C06000 @@ -1707,7 +1709,7 @@ #define DDRSS_PHY_832_DATA 0x00000000 #define DDRSS_PHY_833_DATA 0x00000000 #define DDRSS_PHY_834_DATA 0x00000000 -#define DDRSS_PHY_835_DATA 0x00000004 +#define DDRSS_PHY_835_DATA 0x00000104 #define DDRSS_PHY_836_DATA 0x00000000 #define DDRSS_PHY_837_DATA 0x00000000 #define DDRSS_PHY_838_DATA 0x00000000 @@ -1732,7 +1734,7 @@ #define DDRSS_PHY_857_DATA 0x00100010 #define DDRSS_PHY_858_DATA 0x00100010 #define DDRSS_PHY_859_DATA 0x00100010 -#define DDRSS_PHY_860_DATA 0x02040010 +#define DDRSS_PHY_860_DATA 0x02000010 #define DDRSS_PHY_861_DATA 0x00000005 #define DDRSS_PHY_862_DATA 0x51516042 #define DDRSS_PHY_863_DATA 0x31C06000 @@ -2699,7 +2701,7 @@ #define DDRSS_PHY_1824_DATA 0x0F0F0804 #define DDRSS_PHY_1825_DATA 0x00800120 #define DDRSS_PHY_1826_DATA 0x00041B42 -#define DDRSS_PHY_1827_DATA 0x00005201 +#define DDRSS_PHY_1827_DATA 0x00004201 #define DDRSS_PHY_1828_DATA 0x00000000 #define DDRSS_PHY_1829_DATA 0x00000000 #define DDRSS_PHY_1830_DATA 0x00000000 @@ -2760,7 +2762,7 @@ #define DDRSS_PHY_1885_DATA 0x00000002 #define DDRSS_PHY_1886_DATA 0x00000000 #define DDRSS_PHY_1887_DATA 0x00000000 -#define DDRSS_PHY_1888_DATA 0x00000AC4 +#define DDRSS_PHY_1888_DATA 0x0001F7C4 #define DDRSS_PHY_1889_DATA 0x04000004 #define DDRSS_PHY_1890_DATA 0x00000000 #define DDRSS_PHY_1891_DATA 0x00001142 @@ -2789,10 +2791,10 @@ #define DDRSS_PHY_1914_DATA 0x0089FF00 #define DDRSS_PHY_1915_DATA 0x000C3F11 #define DDRSS_PHY_1916_DATA 0x01990000 -#define DDRSS_PHY_1917_DATA 0x000C3F11 +#define DDRSS_PHY_1917_DATA 0x000C3F91 #define DDRSS_PHY_1918_DATA 0x01990000 #define DDRSS_PHY_1919_DATA 0x3F0DFF11 #define DDRSS_PHY_1920_DATA 0x00EF0000 #define DDRSS_PHY_1921_DATA 0x00018011 #define DDRSS_PHY_1922_DATA 0x0089FF00 -#define DDRSS_PHY_1923_DATA 0x20040004 +#define DDRSS_PHY_1923_DATA 0x20040006 diff --git a/arch/arm/dts/k3-am62p-ddr-lp4-50-1600.dtsi b/arch/arm/dts/k3-am62p-ddr-lp4-50-1600.dtsi index f6643520153..c7e33ba50b9 100644 --- a/arch/arm/dts/k3-am62p-ddr-lp4-50-1600.dtsi +++ b/arch/arm/dts/k3-am62p-ddr-lp4-50-1600.dtsi @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* * This file was generated with the - * AM62Px SysConfig DDR Subsystem Register Configuration Tool v0.10.02 - * Thu Jan 25 2024 10:43:46 GMT-0600 (Central Standard Time) + * AM62Px SysConfig DDR Configuration Tool for AM64x, AM625, AM623, AM62Ax, AM62Px v0.10.02 + * Tue Sep 17 2024 11:03:07 GMT+0530 (India Standard Time) * DDR Type: LPDDR4 * F0 = 50MHz F1 = NA F2 = 1600MHz * Density (per channel): 16Gb @@ -941,7 +941,7 @@ #define DDRSS_PHY_64_DATA 0x00000000 #define DDRSS_PHY_65_DATA 0x00000000 #define DDRSS_PHY_66_DATA 0x00000000 -#define DDRSS_PHY_67_DATA 0x00000004 +#define DDRSS_PHY_67_DATA 0x00000104 #define DDRSS_PHY_68_DATA 0x00000000 #define DDRSS_PHY_69_DATA 0x00000000 #define DDRSS_PHY_70_DATA 0x00000000 @@ -1197,7 +1197,7 @@ #define DDRSS_PHY_320_DATA 0x00000000 #define DDRSS_PHY_321_DATA 0x00000000 #define DDRSS_PHY_322_DATA 0x00000000 -#define DDRSS_PHY_323_DATA 0x00000004 +#define DDRSS_PHY_323_DATA 0x00000104 #define DDRSS_PHY_324_DATA 0x00000000 #define DDRSS_PHY_325_DATA 0x00000000 #define DDRSS_PHY_326_DATA 0x00000000 @@ -1453,7 +1453,7 @@ #define DDRSS_PHY_576_DATA 0x00000000 #define DDRSS_PHY_577_DATA 0x00000000 #define DDRSS_PHY_578_DATA 0x00000000 -#define DDRSS_PHY_579_DATA 0x00000004 +#define DDRSS_PHY_579_DATA 0x00000104 #define DDRSS_PHY_580_DATA 0x00000000 #define DDRSS_PHY_581_DATA 0x00000000 #define DDRSS_PHY_582_DATA 0x00000000 @@ -1709,7 +1709,7 @@ #define DDRSS_PHY_832_DATA 0x00000000 #define DDRSS_PHY_833_DATA 0x00000000 #define DDRSS_PHY_834_DATA 0x00000000 -#define DDRSS_PHY_835_DATA 0x00000004 +#define DDRSS_PHY_835_DATA 0x00000104 #define DDRSS_PHY_836_DATA 0x00000000 #define DDRSS_PHY_837_DATA 0x00000000 #define DDRSS_PHY_838_DATA 0x00000000 diff --git a/arch/arm/dts/k3-am62x-sk-ddr4-1600MTs.dtsi b/arch/arm/dts/k3-am62x-sk-ddr4-1600MTs.dtsi index d92e3ce048b..8def52b07f4 100644 --- a/arch/arm/dts/k3-am62x-sk-ddr4-1600MTs.dtsi +++ b/arch/arm/dts/k3-am62x-sk-ddr4-1600MTs.dtsi @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* * This file was generated with the - * AM62x SysConfig DDR Subsystem Register Configuration Tool v0.08.60 - * Wed Mar 16 2022 17:41:20 GMT-0500 (Central Daylight Time) + * AM623/AM625 SysConfig DDR Configuration Tool for AM64x, AM625, AM623, AM62Ax, AM62Px v0.10.02 + * Tue Sep 17 2024 11:00:17 GMT+0530 (India Standard Time) * DDR Type: DDR4 * Frequency = 800MHz (1600MTs) * Density: 16Gb @@ -12,6 +12,8 @@ #define DDRSS_PLL_FHS_CNT 6 #define DDRSS_PLL_FREQUENCY_1 400000000 #define DDRSS_PLL_FREQUENCY_2 400000000 +#define DDRSS_SDRAM_IDX 15 +#define DDRSS_REGION_IDX 17 #define DDRSS_CTL_0_DATA 0x00000A00 #define DDRSS_CTL_1_DATA 0x00000000 @@ -334,7 +336,7 @@ #define DDRSS_CTL_318_DATA 0x3FFF0000 #define DDRSS_CTL_319_DATA 0x000FFF00 #define DDRSS_CTL_320_DATA 0xFFFFFFFF -#define DDRSS_CTL_321_DATA 0x000FFF00 +#define DDRSS_CTL_321_DATA 0x00FFFF00 #define DDRSS_CTL_322_DATA 0x0A000000 #define DDRSS_CTL_323_DATA 0x0001FFFF #define DDRSS_CTL_324_DATA 0x01010101 @@ -901,7 +903,7 @@ #define DDRSS_PHY_117_DATA 0x00800080 #define DDRSS_PHY_118_DATA 0x00800080 #define DDRSS_PHY_119_DATA 0x01000080 -#define DDRSS_PHY_120_DATA 0x01A00000 +#define DDRSS_PHY_120_DATA 0x01000000 #define DDRSS_PHY_121_DATA 0x00000000 #define DDRSS_PHY_122_DATA 0x00000000 #define DDRSS_PHY_123_DATA 0x00080200 @@ -1157,7 +1159,7 @@ #define DDRSS_PHY_373_DATA 0x00800080 #define DDRSS_PHY_374_DATA 0x00800080 #define DDRSS_PHY_375_DATA 0x01000080 -#define DDRSS_PHY_376_DATA 0x01A00000 +#define DDRSS_PHY_376_DATA 0x01000000 #define DDRSS_PHY_377_DATA 0x00000000 #define DDRSS_PHY_378_DATA 0x00000000 #define DDRSS_PHY_379_DATA 0x00080200 @@ -2152,7 +2154,7 @@ #define DDRSS_PHY_1368_DATA 0x00000002 #define DDRSS_PHY_1369_DATA 0x00000100 #define DDRSS_PHY_1370_DATA 0x00000000 -#define DDRSS_PHY_1371_DATA 0x0001F7C0 +#define DDRSS_PHY_1371_DATA 0x0001F7C2 #define DDRSS_PHY_1372_DATA 0x00020002 #define DDRSS_PHY_1373_DATA 0x00000000 #define DDRSS_PHY_1374_DATA 0x00001142 diff --git a/arch/arm/dts/k3-am64-evm-ddr4-1600MTs.dtsi b/arch/arm/dts/k3-am64-evm-ddr4-1600MTs.dtsi index 491412119b1..1b5fabc3dd1 100644 --- a/arch/arm/dts/k3-am64-evm-ddr4-1600MTs.dtsi +++ b/arch/arm/dts/k3-am64-evm-ddr4-1600MTs.dtsi @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* * This file was generated with the - * AM64x SysConfig DDR Subsystem Register Configuration Tool v0.08.40 - * Wed Feb 02 2022 16:24:50 GMT-0600 (Central Standard Time) + * AM64x SysConfig DDR Configuration Tool for AM64x, AM625, AM623, AM62Ax, AM62Px v0.10.02 + * Tue Sep 17 2024 11:01:31 GMT+0530 (India Standard Time) * DDR Type: DDR4 * Frequency = 800MHz (1600MTs) * Density: 16Gb @@ -12,6 +12,8 @@ #define DDRSS_PLL_FHS_CNT 6 #define DDRSS_PLL_FREQUENCY_1 400000000 #define DDRSS_PLL_FREQUENCY_2 400000000 +#define DDRSS_SDRAM_IDX 15 +#define DDRSS_REGION_IDX 15 #define DDRSS_CTL_0_DATA 0x00000A00 #define DDRSS_CTL_1_DATA 0x00000000 @@ -178,7 +180,7 @@ #define DDRSS_CTL_162_DATA 0x0E0A0907 #define DDRSS_CTL_163_DATA 0x0A090000 #define DDRSS_CTL_164_DATA 0x0A090701 -#define DDRSS_CTL_165_DATA 0x0000000E +#define DDRSS_CTL_165_DATA 0x0000080E #define DDRSS_CTL_166_DATA 0x00040003 #define DDRSS_CTL_167_DATA 0x00000007 #define DDRSS_CTL_168_DATA 0x00000000 @@ -334,7 +336,7 @@ #define DDRSS_CTL_318_DATA 0x3FFF0000 #define DDRSS_CTL_319_DATA 0x000FFF00 #define DDRSS_CTL_320_DATA 0xFFFFFFFF -#define DDRSS_CTL_321_DATA 0x000FFF00 +#define DDRSS_CTL_321_DATA 0x00FFFF00 #define DDRSS_CTL_322_DATA 0x0A000000 #define DDRSS_CTL_323_DATA 0x0001FFFF #define DDRSS_CTL_324_DATA 0x01010101 @@ -901,7 +903,7 @@ #define DDRSS_PHY_117_DATA 0x00800080 #define DDRSS_PHY_118_DATA 0x00800080 #define DDRSS_PHY_119_DATA 0x01000080 -#define DDRSS_PHY_120_DATA 0x01A00000 +#define DDRSS_PHY_120_DATA 0x01000000 #define DDRSS_PHY_121_DATA 0x00000000 #define DDRSS_PHY_122_DATA 0x00000000 #define DDRSS_PHY_123_DATA 0x00080200 @@ -1157,7 +1159,7 @@ #define DDRSS_PHY_373_DATA 0x00800080 #define DDRSS_PHY_374_DATA 0x00800080 #define DDRSS_PHY_375_DATA 0x01000080 -#define DDRSS_PHY_376_DATA 0x01A00000 +#define DDRSS_PHY_376_DATA 0x01000000 #define DDRSS_PHY_377_DATA 0x00000000 #define DDRSS_PHY_378_DATA 0x00000000 #define DDRSS_PHY_379_DATA 0x00080200 @@ -2152,7 +2154,7 @@ #define DDRSS_PHY_1368_DATA 0x00000002 #define DDRSS_PHY_1369_DATA 0x00000100 #define DDRSS_PHY_1370_DATA 0x00000000 -#define DDRSS_PHY_1371_DATA 0x0001F7C0 +#define DDRSS_PHY_1371_DATA 0x0001F7C2 #define DDRSS_PHY_1372_DATA 0x00020002 #define DDRSS_PHY_1373_DATA 0x00000000 #define DDRSS_PHY_1374_DATA 0x00001142 diff --git a/arch/arm/dts/k3-am642-phycore-som-binman.dtsi b/arch/arm/dts/k3-am642-phycore-som-binman.dtsi index 3710564cd4a..5228eed19bf 100644 --- a/arch/arm/dts/k3-am642-phycore-som-binman.dtsi +++ b/arch/arm/dts/k3-am642-phycore-som-binman.dtsi @@ -363,8 +363,11 @@ compression = "none"; load = <0x8F000000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_rtc_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_rtc_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-rtc.dtbo"; }; }; @@ -375,8 +378,11 @@ compression = "none"; load = <0x8F001000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_spi_not_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_spi_not_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-spi-nor.dtbo"; }; }; @@ -387,8 +393,11 @@ compression = "none"; load = <0x8F002000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_eth_phy_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_eth_phy_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-eth-phy.dtbo"; }; }; @@ -399,8 +408,11 @@ compression = "none"; load = <0x8F003000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_qspi_nor_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_qspi_nor_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-qspi-nor.dtbo"; }; }; diff --git a/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi b/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi index b6d2c816acc..55337179f9f 100644 --- a/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi +++ b/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi @@ -14,6 +14,24 @@ spi0 = &ospi0; }; + sysinfo { + compatible = "siemens,sysinfo-iot2050"; + /* TI_SRAM_SCRATCH_BOARD_EEPROM_START */ + offset = <0x40280000>; + bootph-all; + + smbios { + system { + manufacturer = "SIEMENS AG"; + product = "SIMATIC IOT2050"; + }; + + baseboard { + manufacturer = "SIEMENS AG"; + }; + }; + }; + leds { bootph-all; status-led-red { diff --git a/arch/arm/dts/rk3308-rock-s0-u-boot.dtsi b/arch/arm/dts/rk3308-rock-s0-u-boot.dtsi index 84ca2ee0d5f..c8c56b17a15 100644 --- a/arch/arm/dts/rk3308-rock-s0-u-boot.dtsi +++ b/arch/arm/dts/rk3308-rock-s0-u-boot.dtsi @@ -7,6 +7,14 @@ bootph-some-ram; }; +&gpio4 { + bootph-pre-ram; +}; + +&sdmmc_2030 { + bootph-pre-ram; +}; + &uart0 { bootph-all; clock-frequency = <24000000>; @@ -16,6 +24,10 @@ bootph-all; }; +&vcc_sd { + bootph-pre-ram; +}; + &vdd_core { regulator-init-microvolt = <1015000>; }; diff --git a/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi index 69800cc368d..931499b084c 100644 --- a/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi +++ b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi @@ -36,3 +36,8 @@ }; }; }; + +&u2phy1_host { + phy-supply = <&vdd_5v>; + status = "okay"; +}; diff --git a/arch/arm/dts/stm32746g-eval-u-boot.dtsi b/arch/arm/dts/stm32746g-eval-u-boot.dtsi index 1c288acec99..32b5c7cea4b 100644 --- a/arch/arm/dts/stm32746g-eval-u-boot.dtsi +++ b/arch/arm/dts/stm32746g-eval-u-boot.dtsi @@ -22,16 +22,6 @@ mmc0 = &sdio1; spi0 = &qspi; }; - - button1 { - compatible = "st,button1"; - button-gpio = <&gpioc 13 0>; - }; - - led1 { - compatible = "st,led1"; - led-gpio = <&gpiof 10 0>; - }; }; &fmc { diff --git a/arch/arm/dts/stm32f746-disco-u-boot.dtsi b/arch/arm/dts/stm32f746-disco-u-boot.dtsi index 1b42d6cbbc1..38d797e49a0 100644 --- a/arch/arm/dts/stm32f746-disco-u-boot.dtsi +++ b/arch/arm/dts/stm32f746-disco-u-boot.dtsi @@ -22,16 +22,6 @@ mmc0 = &sdio1; spi0 = &qspi; }; - - button1 { - compatible = "st,button1"; - button-gpio = <&gpioi 11 0>; - }; - - led1 { - compatible = "st,led1"; - led-gpio = <&gpioi 1 0>; - }; }; <dc { diff --git a/arch/arm/dts/stm32f769-disco-u-boot.dtsi b/arch/arm/dts/stm32f769-disco-u-boot.dtsi index add55c96e21..7c99a6e61b6 100644 --- a/arch/arm/dts/stm32f769-disco-u-boot.dtsi +++ b/arch/arm/dts/stm32f769-disco-u-boot.dtsi @@ -23,16 +23,6 @@ spi0 = &qspi; }; - button1 { - compatible = "st,button1"; - button-gpio = <&gpioa 0 0>; - }; - - led1 { - compatible = "st,led1"; - led-gpio = <&gpioj 5 0>; - }; - panel: panel { compatible = "orisetech,otm8009a"; reset-gpios = <&gpioj 15 1>; diff --git a/arch/arm/dts/stm32mp13-pinctrl.dtsi b/arch/arm/dts/stm32mp13-pinctrl.dtsi index c01d39f03ea..52c2a9f24d7 100644 --- a/arch/arm/dts/stm32mp13-pinctrl.dtsi +++ b/arch/arm/dts/stm32mp13-pinctrl.dtsi @@ -215,6 +215,21 @@ }; }; + pwm1_ch3n_pins_a: pwm1-ch3n-0 { + pins { + pinmux = <STM32_PINMUX('E', 12, AF1)>; /* TIM1_CH3N */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm1_ch3n_sleep_pins_a: pwm1-ch3n-sleep-0 { + pins { + pinmux = <STM32_PINMUX('E', 12, ANALOG)>; /* TIM1_CH3N */ + }; + }; + pwm3_pins_a: pwm3-0 { pins { pinmux = <STM32_PINMUX('B', 1, AF2)>; /* TIM3_CH4 */ diff --git a/arch/arm/dts/stm32mp135f-dhcor-dhsbc-u-boot.dtsi b/arch/arm/dts/stm32mp135f-dhcor-dhsbc-u-boot.dtsi index d718aae16ca..eace94f5fa4 100644 --- a/arch/arm/dts/stm32mp135f-dhcor-dhsbc-u-boot.dtsi +++ b/arch/arm/dts/stm32mp135f-dhcor-dhsbc-u-boot.dtsi @@ -23,3 +23,25 @@ &usbphyc { bootph-all; }; + +&st33htph { + reset-gpios = <&gpioe 12 GPIO_ACTIVE_LOW>; +}; + +/* LDO2 is expansion connector 3V3 supply on STM32MP13xx DHCOR DHSBC rev.200 */ +&vdd_ldo2 { + bootph-all; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +}; + +/* LDO5 is carrier board 3V3 supply on STM32MP13xx DHCOR DHSBC rev.200 */ +&vdd_sd { + bootph-all; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +}; diff --git a/arch/arm/dts/stm32mp135f-dk.dts b/arch/arm/dts/stm32mp135f-dk.dts index eea740d097c..275823da3c6 100644 --- a/arch/arm/dts/stm32mp135f-dk.dts +++ b/arch/arm/dts/stm32mp135f-dk.dts @@ -9,6 +9,7 @@ #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input.h> #include <dt-bindings/leds/common.h> +#include <dt-bindings/pwm/pwm.h> #include <dt-bindings/regulator/st,stm32mp13-regulator.h> #include "stm32mp135.dtsi" #include "stm32mp13xf.dtsi" @@ -207,6 +208,19 @@ status = "disabled"; }; +&timers1 { + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; + pwm1: pwm { + pinctrl-0 = <&pwm1_ch3n_pins_a>; + pinctrl-1 = <&pwm1_ch3n_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + status = "okay"; + }; +}; + &timers3 { /delete-property/dmas; /delete-property/dma-names; diff --git a/arch/arm/dts/stm32mp13xx-dhcor-u-boot.dtsi b/arch/arm/dts/stm32mp13xx-dhcor-u-boot.dtsi index 30e3b91bccc..9ff42ab8248 100644 --- a/arch/arm/dts/stm32mp13xx-dhcor-u-boot.dtsi +++ b/arch/arm/dts/stm32mp13xx-dhcor-u-boot.dtsi @@ -13,6 +13,8 @@ config { dh,ddr3-coding-gpios = <&gpiod 5 0>, <&gpiod 9 0>; dh,som-coding-gpios = <&gpioa 13 0>, <&gpioi 1 0>; + u-boot,mmc-env-offset = <0x3fc000>; + u-boot,mmc-env-offset-redundant = <0x3fc000>; }; }; diff --git a/arch/arm/dts/tegra124-xiaomi-mocha.dts b/arch/arm/dts/tegra124-xiaomi-mocha.dts new file mode 100644 index 00000000000..6cb1781566f --- /dev/null +++ b/arch/arm/dts/tegra124-xiaomi-mocha.dts @@ -0,0 +1,592 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; + +#include <dt-bindings/input/input.h> +#include "tegra124.dtsi" + +/ { + model = "Xiaomi Mi Pad A0101"; + compatible = "xiaomi,mocha", "nvidia,tegra124"; + + chosen { + stdout-path = &uartd; + }; + + aliases { + i2c0 = &pwr_i2c; + i2c1 = &gen1_i2c; + + mmc0 = &sdmmc4; /* eMMC */ + mmc1 = &sdmmc3; /* uSD slot */ + + usb0 = &usb1; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x80000000>; + }; + + host1x@50000000 { + dsia: dsi@54300000 { + status = "okay"; + + avdd-dsi-csi-supply = <&avdd_dsi_csi>; + nvidia,ganged-mode = <&dsib>; + + panel@0 { + compatible = "sharp,lq079l1sx01"; + reg = <0>; + + link2 = <&panel_secondary>; + + avdd-supply = <&avdd_lcd>; + vddio-supply = <&vdd_lcd_io>; + + vsp-supply = <&vsp_5v5_lcd>; + vsn-supply = <&vsn_5v5_lcd>; + + reset-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_LOW>; + + backlight = <&lp8556>; + }; + }; + + dsib: dsi@54400000 { + status = "okay"; + + avdd-dsi-csi-supply = <&avdd_dsi_csi>; + + panel_secondary: panel@0 { + compatible = "sharp,lq079l1sx01"; + reg = <0>; + }; + }; + }; + + pinmux@70000868 { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + /* Keys pinmux */ + keys { + nvidia,pins = "kb_col0_pq0", + "kb_col6_pq6", + "kb_col7_pq7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + hall-front { + nvidia,pins = "pi5"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + hall-back { + nvidia,pins = "gpio_w3_aud_pw3"; + nvidia,function = "spi1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Leds pinmux */ + bl-en { + nvidia,pins = "pbb4"; + nvidia,function = "vgp4"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + keys-led { + nvidia,pins = "ph1"; + nvidia,function = "pwm1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Panel pinmux */ + lcd-rst { + nvidia,pins = "ph3"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + lcd-vsp { + nvidia,pins = "pi4"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + lcd-vsn { + nvidia,pins = "kb_row10_ps2"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + lcd-id { + nvidia,pins = "kb_row6_pr6"; + nvidia,function = "displaya_alt"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + lcd-pwm { + nvidia,pins = "ph2"; + nvidia,function = "pwm2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* SDMMC3 pinmux */ + sdmmc3-clk { + nvidia,pins = "sdmmc3_clk_pa6"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + sdmmc3-cmd { + nvidia,pins = "sdmmc3_cmd_pa7", + "sdmmc3_dat0_pb7", + "sdmmc3_dat1_pb6", + "sdmmc3_dat2_pb5", + "sdmmc3_dat3_pb4", + "sdmmc3_clk_lb_out_pee4", + "sdmmc3_clk_lb_in_pee5"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + sdmmc3-cd { + nvidia,pins = "sdmmc3_cd_n_pv2"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + usd-pwr { + nvidia,pins = "kb_row0_pr0"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* SDMMC4 pinmux */ + sdmmc4-clk { + nvidia,pins = "sdmmc4_clk_pcc4"; + nvidia,function = "sdmmc4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + sdmmc4-cmd { + nvidia,pins = "sdmmc4_cmd_pt7", + "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7"; + nvidia,function = "sdmmc4"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* I2C pinmux */ + gen1-i2c { + nvidia,pins = "gen1_i2c_sda_pc5", + "gen1_i2c_scl_pc4"; + nvidia,function = "i2c1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <1>; + nvidia,open-drain = <1>; + }; + gen2-i2c { + nvidia,pins = "gen2_i2c_scl_pt5", + "gen2_i2c_sda_pt6"; + nvidia,function = "i2c2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <1>; + nvidia,open-drain = <1>; + }; + cam-i2c { + nvidia,pins = "cam_i2c_scl_pbb1", + "cam_i2c_sda_pbb2"; + nvidia,function = "i2c3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <1>; + nvidia,open-drain = <1>; + }; + ddc-i2c { + nvidia,pins = "ddc_scl_pv4", + "ddc_sda_pv5"; + nvidia,function = "i2c4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + pwr-i2c { + nvidia,pins = "pwr_i2c_scl_pz6", + "pwr_i2c_sda_pz7"; + nvidia,function = "i2cpwr"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <1>; + }; + + dsi-b { + nvidia,pins = "mipi_pad_ctrl_dsi_b"; + nvidia,function = "dsi_b"; + }; + + /* GPIO power/drive control */ + drive-sdio1 { + nvidia,pins = "drive_sdio1"; + nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <32>; + nvidia,pull-up-strength = <42>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; + + drive-sdio3 { + nvidia,pins = "drive_sdio3"; + nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <20>; + nvidia,pull-up-strength = <36>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; + + drive-gma { + nvidia,pins = "drive_gma"; + nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <1>; + nvidia,pull-up-strength = <2>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; + }; + }; + + uartd: serial@70006300 { + status = "okay"; + }; + + gen1_i2c: i2c@7000c000 { + status = "okay"; + clock-frequency = <400000>; + + lp8556: backlight@2c { + compatible = "ti,lp8556"; + reg = <0x2c>; + + dev-ctrl = /bits/ 8 <0x83>; + init-brt = /bits/ 8 <0x1f>; + + power-supply = <&vdd_3v3_sys>; + enable-supply = <&vddio_1v8_bl>; + + rom-98h { + rom-addr = /bits/ 8 <0x98>; + rom-val = /bits/ 8 <0x80>; + }; + + rom-9eh { + rom-addr = /bits/ 8 <0x9e>; + rom-val = /bits/ 8 <0x21>; + }; + + rom-a0h { + rom-addr = /bits/ 8 <0xa0>; + rom-val = /bits/ 8 <0xff>; + }; + + rom-a1h { + rom-addr = /bits/ 8 <0xa1>; + rom-val = /bits/ 8 <0x3f>; + }; + + rom-a2h { + rom-addr = /bits/ 8 <0xa2>; + rom-val = /bits/ 8 <0x20>; + }; + + rom-a3h { + rom-addr = /bits/ 8 <0xa3>; + rom-val = /bits/ 8 <0x00>; + }; + + rom-a4h { + rom-addr = /bits/ 8 <0xa4>; + rom-val = /bits/ 8 <0x72>; + }; + + rom-a5h { + rom-addr = /bits/ 8 <0xa5>; + rom-val = /bits/ 8 <0x24>; + }; + + rom-a6h { + rom-addr = /bits/ 8 <0xa6>; + rom-val = /bits/ 8 <0x80>; + }; + + rom-a7h { + rom-addr = /bits/ 8 <0xa7>; + rom-val = /bits/ 8 <0xf5>; + }; + + rom-a8h { + rom-addr = /bits/ 8 <0xa8>; + rom-val = /bits/ 8 <0x24>; + }; + + rom-a9h { + rom-addr = /bits/ 8 <0xa9>; + rom-val = /bits/ 8 <0xb2>; + }; + + rom-aah { + rom-addr = /bits/ 8 <0xaa>; + rom-val = /bits/ 8 <0x8f>; + }; + + rom-aeh { + rom-addr = /bits/ 8 <0xae>; + rom-val = /bits/ 8 <0x0f>; + }; + }; + }; + + pwr_i2c: i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + + /* Texas Instruments TPS65913 PMIC */ + pmic: tps65913@58 { + compatible = "ti,tps65913"; + reg = <0x58>; + + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <2>; + interrupt-controller; + + ti,system-power-controller; + + palmas_gpio: gpio { + compatible = "ti,palmas-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + + pinmux { + compatible = "ti,tps65913-pinctrl"; + + pinctrl-names = "default"; + pinctrl-0 = <&palmas_default>; + + palmas_default: pinmux { + pin_gpio4 { + pins = "gpio4"; + function = "gpio"; + }; + }; + }; + + pmic { + compatible = "ti,tps65913-pmic"; + + regulators { + vdd_1v8_vio: smps8 { + regulator-name = "vdd_1v8_gen"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + vdd_hv_sdmmc: smps9 { + regulator-name = "vdd_hv_sdmmc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + avdd_lcd: ldo2 { + regulator-name = "avdd_lcd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + + avdd_dsi_csi: ldo5 { + regulator-name = "avdd_dsi_csi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + + vddio_usd: ldo9 { + regulator-name = "vddio_sdmmc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + avdd_usb: ldousb { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + }; + }; + }; + }; + + sdmmc3: sdhci@700b0400 { + status = "okay"; + bus-width = <4>; + + cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>; + power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>; + + vmmc-supply = <&vdd_hv_sdmmc>; + vqmmc-supply = <&vddio_usd>; + }; + + sdmmc4: sdhci@700b0600 { + status = "okay"; + bus-width = <8>; + non-removable; + + vmmc-supply = <&vdd_hv_sdmmc>; + vqmmc-supply = <&vdd_1v8_vio>; + }; + + usb1: usb@7d000000 { + status = "okay"; + dr_mode = "otg"; + }; + + clk32k_in: clock-32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "ref-oscillator"; + }; + + extcon-keys { + compatible = "gpio-keys"; + + switch-back-hall-sensor { + label = "Hall sensor (back)"; + gpios = <&gpio TEGRA_GPIO(W, 3) GPIO_ACTIVE_LOW>; + linux,code = <SW_LID>; + }; + + switch-front-hall-sensor { + label = "Hall sensor (front)"; + gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>; + linux,code = <SW_LID>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-power { + label = "Power"; + gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; + linux,code = <KEY_ENTER>; + }; + + key-volume-down { + label = "Volume Down"; + gpios = <&gpio TEGRA_GPIO(Q, 7) GPIO_ACTIVE_LOW>; + linux,code = <KEY_DOWN>; + }; + + key-volume-up { + label = "Volume Up"; + gpios = <&gpio TEGRA_GPIO(Q, 6) GPIO_ACTIVE_LOW>; + linux,code = <KEY_UP>; + }; + }; + + vdd_3v3_sys: regulator-bl-en { + compatible = "regulator-fixed"; + regulator-name = "vdd_5v0_bl"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + }; + + vddio_1v8_bl: regulator-bl-io { + compatible = "regulator-fixed"; + regulator-name = "vddio_1v8_bl"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + gpio = <&gpio TEGRA_GPIO(BB, 4) GPIO_ACTIVE_HIGH>; + }; + + vdd_lcd_io: regulator-lcdvio { + compatible = "regulator-fixed"; + regulator-name = "dvdd_lcd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + gpio = <&palmas_gpio 4 GPIO_ACTIVE_HIGH>; + }; + + vsp_5v5_lcd: regulator-vsp { + compatible = "regulator-fixed"; + regulator-name = "avdd_lcd_vsp"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + enable-active-high; + gpio = <&gpio TEGRA_GPIO(I, 4) GPIO_ACTIVE_HIGH>; + }; + + vsn_5v5_lcd: regulator-vsn { + compatible = "regulator-fixed"; + regulator-name = "avdd_lcd_vsn"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + enable-active-high; + gpio = <&gpio TEGRA_GPIO(S, 2) GPIO_ACTIVE_HIGH>; + }; +}; diff --git a/arch/arm/dts/tegra20-u-boot.dtsi b/arch/arm/dts/tegra20-u-boot.dtsi index fa582bcb9fd..b74aa5bb0d4 100644 --- a/arch/arm/dts/tegra20-u-boot.dtsi +++ b/arch/arm/dts/tegra20-u-boot.dtsi @@ -9,5 +9,9 @@ dc@54200000 { bootph-all; }; + + dc@54240000 { + bootph-all; + }; }; }; diff --git a/arch/arm/dts/tegra30-htc-endeavoru.dts b/arch/arm/dts/tegra30-htc-endeavoru.dts index dbff795bd89..8a0ba3c07cc 100644 --- a/arch/arm/dts/tegra30-htc-endeavoru.dts +++ b/arch/arm/dts/tegra30-htc-endeavoru.dts @@ -48,7 +48,17 @@ avdd-dsi-csi-supply = <&avdd_dsi_csi>; - panel = <&panel>; + panel@0 { + compatible = "htc,edge-panel"; + reg = <0>; + + reset-gpios = <&gpio TEGRA_GPIO(N, 6) GPIO_ACTIVE_LOW>; + + vdd-supply = <&vdd_3v3_panel>; + vddio-supply = <&vdd_1v8_panel>; + + backlight = <&backlight>; + }; }; }; @@ -1292,17 +1302,6 @@ }; }; - panel: panel { - compatible = "htc,edge-panel"; - - reset-gpios = <&gpio TEGRA_GPIO(N, 6) GPIO_ACTIVE_LOW>; - - vdd-supply = <&vdd_3v3_panel>; - vddio-supply = <&vdd_1v8_panel>; - - backlight = <&backlight>; - }; - vcore_emmc: regulator-emmc { compatible = "regulator-fixed"; regulator-name = "vdd_2v85_sdmmc"; diff --git a/arch/arm/include/asm/arch-tegra124/pinmux.h b/arch/arm/include/asm/arch-tegra124/pinmux.h index 3aba17d21e4..fbe15fc612d 100644 --- a/arch/arm/include/asm/arch-tegra124/pinmux.h +++ b/arch/arm/include/asm/arch-tegra124/pinmux.h @@ -578,6 +578,10 @@ static const char * const tegra_pinctrl_to_drvgrp[] = { [PMUX_DRVGRP_AO4] = "ao4", }; +static const char * const tegra_pinctrl_to_mipipadgrp[] = { + [PMUX_MIPIPADCTRLGRP_DSI_B] = "mipi_pad_ctrl_dsi_b", +}; + static const char * const tegra_pinctrl_to_func[] = { [PMUX_FUNC_DEFAULT] = "default", [PMUX_FUNC_BLINK] = "blink", diff --git a/arch/arm/include/asm/arch-tegra20/clock-tables.h b/arch/arm/include/asm/arch-tegra20/clock-tables.h index 861b3d5d07c..82685353bd1 100644 --- a/arch/arm/include/asm/arch-tegra20/clock-tables.h +++ b/arch/arm/include/asm/arch-tegra20/clock-tables.h @@ -32,6 +32,7 @@ enum clock_id { CLOCK_ID_COUNT, /* number of clocks */ CLOCK_ID_NONE = -1, + CLOCK_ID_DISPLAY2 = CLOCK_ID_NONE, /* for compatibility */ }; /* The clocks supported by the hardware */ @@ -159,6 +160,7 @@ enum periph_id { PERIPH_ID_COUNT, PERIPH_ID_NONE = -1, + PERIPH_ID_DSIB = CLOCK_ID_NONE, /* for compatibility */ }; enum pll_out_id { diff --git a/arch/arm/include/asm/setjmp.h b/arch/arm/include/asm/setjmp.h index 662bec86321..a9eccf7f632 100644 --- a/arch/arm/include/asm/setjmp.h +++ b/arch/arm/include/asm/setjmp.h @@ -4,13 +4,11 @@ * (C) Copyright 2016 Alexander Graf <agraf@suse.de> */ -#ifndef _SETJMP_H_ -#define _SETJMP_H_ 1 +#ifndef _ASM_SETJMP_H_ +#define _ASM_SETJMP_H_ 1 + +#include <asm-generic/int-ll64.h> -/* - * This really should be opaque, but the EFI implementation wrongly - * assumes that a 'struct jmp_buf_data' is defined. - */ struct jmp_buf_data { #if defined(__aarch64__) u64 regs[13]; @@ -19,9 +17,4 @@ struct jmp_buf_data { #endif }; -typedef struct jmp_buf_data jmp_buf[1]; - -int setjmp(jmp_buf jmp); -void longjmp(jmp_buf jmp, int ret); - -#endif /* _SETJMP_H_ */ +#endif /* _ASM_SETJMP_H_ */ diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 974cbfe8400..7eb764e1f4e 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -61,10 +61,6 @@ static void announce_and_cleanup(int fake) bootstage_report(); #endif -#ifdef CONFIG_USB_DEVICE - udc_disconnect(); -#endif - board_quiesce_devices(); printf("\nStarting kernel ...%s\n\n", fake ? diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig index 0fe9c46e499..89f2b50c8a2 100644 --- a/arch/arm/mach-imx/imx8m/Kconfig +++ b/arch/arm/mach-imx/imx8m/Kconfig @@ -92,6 +92,8 @@ config TARGET_IMX8MM_EVK select FSL_CAAM select ARCH_MISC_INIT select SPL_CRYPTO if SPL + imply BOOTSTD_FULL + imply BOOTSTD_BOOTCOMMAND imply OF_UPSTREAM config TARGET_IMX8MM_ICORE_MX8MM diff --git a/arch/arm/mach-k3/am65x/Kconfig b/arch/arm/mach-k3/am65x/Kconfig index 72a8298aebf..056ae118c9e 100644 --- a/arch/arm/mach-k3/am65x/Kconfig +++ b/arch/arm/mach-k3/am65x/Kconfig @@ -35,6 +35,8 @@ config TARGET_IOT2050_A53 select BOARD_LATE_INIT select SYS_DISABLE_DCACHE_OPS select BINMAN + select SYSINFO + select SPL_SYSINFO if SPL help This builds U-Boot for the IOT2050 devices. diff --git a/arch/arm/mach-k3/j722s/j722s_init.c b/arch/arm/mach-k3/j722s/j722s_init.c index f8c5c2a5edc..af211377e7c 100644 --- a/arch/arm/mach-k3/j722s/j722s_init.c +++ b/arch/arm/mach-k3/j722s/j722s_init.c @@ -27,6 +27,9 @@ struct fwl_data cbass_main_fwls[] = { u32 bootindex __section(".data"); static struct rom_extended_boot_data bootdata __section(".data"); +#define CTRLMMR_MCU_RST_CTRL (MCU_CTRL_MMR0_BASE + 0x18170) +#define RST_CTRL_ESM_ERROR_RST_EN_Z_MASK (~BIT(17)) + static void store_boot_info_from_rom(void) { bootindex = *(u32 *)(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX); @@ -161,11 +164,40 @@ static void k3_mem_init(void) } } +static __maybe_unused void enable_mcu_esm_reset(void) +{ + /* Set CTRLMMR_MCU_RST_CTRL:MCU_ESM_ERROR_RST_EN_Z to '0' (low active) */ + u32 stat = readl(CTRLMMR_MCU_RST_CTRL); + + stat &= RST_CTRL_ESM_ERROR_RST_EN_Z_MASK; + writel(stat, CTRLMMR_MCU_RST_CTRL); +} + void board_init_f(ulong dummy) { + int ret; + struct udevice *dev; + k3_spl_init(); k3_mem_init(); setup_qos(); + + if (IS_ENABLED(CONFIG_ESM_K3)) { + /* Probe/configure ESM0 */ + ret = uclass_get_device_by_name(UCLASS_MISC, "esm@420000", &dev); + if (ret) { + printf("esm main init failed: %d\n", ret); + return; + } + + /* Probe/configure MCUESM */ + ret = uclass_get_device_by_name(UCLASS_MISC, "esm@4100000", &dev); + if (ret) { + printf("esm mcu init failed: %d\n", ret); + return; + } + enable_mcu_esm_reset(); + } } static u32 __get_backup_bootmedia(u32 devstat) diff --git a/arch/arm/mach-rockchip/bootrom.c b/arch/arm/mach-rockchip/bootrom.c index 82a0b3efef9..1db38546d55 100644 --- a/arch/arm/mach-rockchip/bootrom.c +++ b/arch/arm/mach-rockchip/bootrom.c @@ -4,11 +4,11 @@ */ #include <hang.h> +#include <setjmp.h> #include <asm/arch-rockchip/bootrom.h> #include <asm/arch-rockchip/boot_mode.h> #include <asm/cache.h> #include <asm/io.h> -#include <asm/setjmp.h> #include <asm/system.h> /* diff --git a/arch/arm/mach-sc5xx/soc.c b/arch/arm/mach-sc5xx/soc.c index f3619206e91..8f13127a660 100644 --- a/arch/arm/mach-sc5xx/soc.c +++ b/arch/arm/mach-sc5xx/soc.c @@ -172,42 +172,6 @@ void fixup_dp83867_phy(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x3100); } -extern char __bss_start, __bss_end; -extern char __rel_dyn_end; - -void bss_clear(void) -{ - char *bss_start = &__bss_start; - char *bss_end = &__bss_end; - char *rel_dyn_end = &__rel_dyn_end; - - char *start; - - if (rel_dyn_end >= bss_start && rel_dyn_end <= bss_end) - start = rel_dyn_end; - else - start = bss_start; - - u32 *pt; - size_t sz = bss_end - start; - - for (int i = 0; i < sz; i += 4) { - pt = (u32 *)(start + i); - *pt = 0; - } -} - -int board_early_init_f(void) -{ - bss_clear(); - return 0; -} - -int board_init(void) -{ - return 0; -} - int dram_init(void) { gd->ram_size = CFG_SYS_SDRAM_SIZE; diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index 25663a99464..002da2e3d3b 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/arch/arm/mach-stm32mp/Kconfig @@ -153,6 +153,12 @@ config CMD_STM32KEY This command is used to evaluate the secure boot on stm32mp SOC, it is deactivated by default in real products. +config MFD_STM32_TIMERS + bool "STM32 multifonction timer support" + help + Select this to enable support for the multifunction timer found on + STM32 devices. + source "arch/arm/mach-stm32mp/Kconfig.13x" source "arch/arm/mach-stm32mp/Kconfig.15x" source "arch/arm/mach-stm32mp/Kconfig.25x" diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile index db7ed19bd91..103e3410ad9 100644 --- a/arch/arm/mach-stm32mp/Makefile +++ b/arch/arm/mach-stm32mp/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_STM32MP15X) += stm32mp1/ obj-$(CONFIG_STM32MP13X) += stm32mp1/ obj-$(CONFIG_STM32MP25X) += stm32mp2/ +obj-$(CONFIG_MFD_STM32_TIMERS) += timers.o obj-$(CONFIG_STM32_ECDSA_VERIFY) += ecdsa_romapi.o ifndef CONFIG_XPL_BUILD obj-y += cmd_stm32prog/ diff --git a/arch/arm/mach-stm32mp/include/mach/timers.h b/arch/arm/mach-stm32mp/include/mach/timers.h new file mode 100644 index 00000000000..a84465bb28e --- /dev/null +++ b/arch/arm/mach-stm32mp/include/mach/timers.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2025, STMicroelectronics - All Rights Reserved + * Author: Cheick Traore <cheick.traore@foss.st.com> + * + * Originally based on the Linux kernel v6.1 include/linux/mfd/stm32-timers.h. + */ + +#ifndef __STM32_TIMERS_H +#define __STM32_TIMERS_H + +#include <clk.h> + +#define TIM_CR1 0x00 /* Control Register 1 */ +#define TIM_CR2 0x04 /* Control Register 2 */ +#define TIM_SMCR 0x08 /* Slave mode control reg */ +#define TIM_DIER 0x0C /* DMA/interrupt register */ +#define TIM_SR 0x10 /* Status register */ +#define TIM_EGR 0x14 /* Event Generation Reg */ +#define TIM_CCMR1 0x18 /* Capt/Comp 1 Mode Reg */ +#define TIM_CCMR2 0x1C /* Capt/Comp 2 Mode Reg */ +#define TIM_CCER 0x20 /* Capt/Comp Enable Reg */ +#define TIM_CNT 0x24 /* Counter */ +#define TIM_PSC 0x28 /* Prescaler */ +#define TIM_ARR 0x2c /* Auto-Reload Register */ +#define TIM_CCRx(x) (0x34 + 4 * ((x) - 1)) /* Capt/Comp Register x (x ∈ {1, .. 4}) */ +#define TIM_BDTR 0x44 /* Break and Dead-Time Reg */ +#define TIM_DCR 0x48 /* DMA control register */ +#define TIM_DMAR 0x4C /* DMA register for transfer */ +#define TIM_TISEL 0x68 /* Input Selection */ + +#define TIM_CR1_CEN BIT(0) /* Counter Enable */ +#define TIM_CR1_ARPE BIT(7) +#define TIM_CCER_CCXE (BIT(0) | BIT(4) | BIT(8) | BIT(12)) +#define TIM_CCER_CC1E BIT(0) +#define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */ +#define TIM_CCER_CC1NE BIT(2) /* Capt/Comp 1N out Ena */ +#define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */ +#define TIM_CCMR_PE BIT(3) /* Channel Preload Enable */ +#define TIM_CCMR_M1 (BIT(6) | BIT(5)) /* Channel PWM Mode 1 */ +#define TIM_BDTR_MOE BIT(15) /* Main Output Enable */ +#define TIM_EGR_UG BIT(0) /* Update Generation */ + +#define MAX_TIM_PSC 0xFFFF + +struct stm32_timers_plat { + void __iomem *base; +}; + +struct stm32_timers_priv { + u32 max_arr; + ulong rate; +}; + +#endif diff --git a/arch/arm/mach-stm32mp/stm32mp1/cpu.c b/arch/arm/mach-stm32mp/stm32mp1/cpu.c index cb1b84c9af9..18175fd12cc 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/cpu.c +++ b/arch/arm/mach-stm32mp/stm32mp1/cpu.c @@ -82,7 +82,7 @@ void dram_bank_mmu_setup(int bank) option = DCACHE_DEFAULT_OPTION; if (use_lmb && (lmb_is_reserved_flags(i << MMU_SECTION_SHIFT, LMB_NOMAP) || - addr >= gd->ram_top) + (gd->ram_top && addr >= gd->ram_top)) ) option = 0; /* INVALID ENTRY in TLB */ set_section_dcache(i, option); @@ -138,8 +138,6 @@ int mach_cpu_init(void) if (IS_ENABLED(CONFIG_CMD_STM32PROG_SERIAL) && (boot_mode & TAMP_BOOT_DEVICE_MASK) == BOOT_SERIAL_UART) gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE; - else if (IS_ENABLED(CONFIG_DEBUG_UART) && IS_ENABLED(CONFIG_XPL_BUILD)) - debug_uart_init(); return 0; } diff --git a/arch/arm/mach-stm32mp/timers.c b/arch/arm/mach-stm32mp/timers.c new file mode 100644 index 00000000000..a3207895f40 --- /dev/null +++ b/arch/arm/mach-stm32mp/timers.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025, STMicroelectronics - All Rights Reserved + * Author: Cheick Traore <cheick.traore@foss.st.com> + * + * Originally based on the Linux kernel v6.1 drivers/mfd/stm32-timers.c. + */ + +#include <dm.h> +#include <asm/io.h> +#include <asm/arch/timers.h> +#include <dm/device_compat.h> + +static void stm32_timers_get_arr_size(struct udevice *dev) +{ + struct stm32_timers_plat *plat = dev_get_plat(dev); + struct stm32_timers_priv *priv = dev_get_priv(dev); + u32 arr; + + /* Backup ARR to restore it after getting the maximum value */ + arr = readl(plat->base + TIM_ARR); + + /* + * Only the available bits will be written so when readback + * we get the maximum value of auto reload register + */ + writel(~0L, plat->base + TIM_ARR); + priv->max_arr = readl(plat->base + TIM_ARR); + writel(arr, plat->base + TIM_ARR); +} + +static int stm32_timers_of_to_plat(struct udevice *dev) +{ + struct stm32_timers_plat *plat = dev_get_plat(dev); + + plat->base = dev_read_addr_ptr(dev); + if (!plat->base) { + dev_err(dev, "can't get address\n"); + return -ENOENT; + } + + return 0; +} + +static int stm32_timers_probe(struct udevice *dev) +{ + struct stm32_timers_priv *priv = dev_get_priv(dev); + struct clk clk; + int ret = 0; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) + return ret; + + ret = clk_enable(&clk); + if (ret) { + dev_err(dev, "failed to enable clock: ret=%d\n", ret); + return ret; + } + + priv->rate = clk_get_rate(&clk); + + stm32_timers_get_arr_size(dev); + + return ret; +} + +static const struct udevice_id stm32_timers_ids[] = { + { .compatible = "st,stm32-timers" }, + {} +}; + +U_BOOT_DRIVER(stm32_timers) = { + .name = "stm32_timers", + .id = UCLASS_NOP, + .of_match = stm32_timers_ids, + .of_to_plat = stm32_timers_of_to_plat, + .plat_auto = sizeof(struct stm32_timers_plat), + .probe = stm32_timers_probe, + .priv_auto = sizeof(struct stm32_timers_priv), + .bind = dm_scan_fdt_dev, +}; diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 78b89729f19..4690dcb3ea6 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -247,7 +247,7 @@ config CMD_ENTERRCM config CMD_EBTUPDATE bool "Enable 'ebtupdate' command" - depends on TEGRA20 || TEGRA30 + depends on TEGRA20 || TEGRA30 || TEGRA124 select TEGRA_CRYPTO help Updating u-boot from within u-boot in rather complex or even diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 157e6c4911a..a375693481e 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -358,6 +358,13 @@ unsigned long clock_get_periph_rate(enum periph_id periph_id, break; } + /* + * PLLD/PLLD2 raw clock rate is never used, instead plld_out0 is used + * that is PLLD/PLLD2 halved. + */ + if (parent == CLOCK_ID_DISPLAY || parent == CLOCK_ID_DISPLAY2) + parent_rate /= 2; + return get_rate_from_divider(parent_rate, div); } @@ -449,6 +456,7 @@ unsigned clock_adjust_periph_pll_div(enum periph_id periph_id, enum clock_id parent, unsigned rate, int *extra_div) { unsigned effective_rate; + unsigned int parent_rate; int mux_bits, divider_bits, source; int divider; int xdiv = 0; @@ -457,7 +465,17 @@ unsigned clock_adjust_periph_pll_div(enum periph_id periph_id, source = get_periph_clock_source(periph_id, parent, &mux_bits, ÷r_bits); - divider = find_best_divider(divider_bits, pll_rate[parent], + /* + * Clocks derived from PLLD/D2 are actually sourced from its halved + * output, plld_out0/plld2_out0. No peripheral clocks use the raw + * PLLD/D2 frequency. This halving must be accounted for in derived + * clock calculations. + */ + parent_rate = pll_rate[parent]; + if (parent == CLOCK_ID_DISPLAY || parent == CLOCK_ID_DISPLAY2) + parent_rate /= 2; + + divider = find_best_divider(divider_bits, parent_rate, rate, &xdiv); if (extra_div) *extra_div = xdiv; @@ -685,6 +703,16 @@ int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon) else writel(base_reg, &simple_pll->pll_base); + /* + * Changing clocks was never intended in the U-Boot for Tegra. + * If a clock is changed after clock_init() the parent rate is wrong. + * Usually there is no reason to change peripheral clocks, but Display + * PLLs which needs to generate a precise pixelclock might be adjusted. + * Especially in the case of HDMI display with changing and prior + * unknown resolution. + */ + pll_rate[clkid] = clock_get_rate(clkid); + return 0; } diff --git a/arch/arm/mach-tegra/tegra124/Kconfig b/arch/arm/mach-tegra/tegra124/Kconfig index 84c8f86bad0..a62b055f7e6 100644 --- a/arch/arm/mach-tegra/tegra124/Kconfig +++ b/arch/arm/mach-tegra/tegra124/Kconfig @@ -30,6 +30,10 @@ config TARGET_CEI_TK1_SOM the SoC are assigned to which functions, and the PCIEe configuration. +config TARGET_MOCHA + bool "Xiaomi Tegra124 Mi Pad board" + select BOARD_LATE_INIT + config TARGET_NYAN_BIG bool "Google/NVIDIA Nyan-big Chromebook" select BOARD_LATE_INIT @@ -54,5 +58,6 @@ source "board/nvidia/jetson-tk1/Kconfig" source "board/nvidia/nyan-big/Kconfig" source "board/nvidia/venice2/Kconfig" source "board/toradex/apalis-tk1/Kconfig" +source "board/xiaomi/mocha/Kconfig" endif diff --git a/arch/arm/mach-tegra/tegra124/Makefile b/arch/arm/mach-tegra/tegra124/Makefile index dee790015a3..7b93db89c0f 100644 --- a/arch/arm/mach-tegra/tegra124/Makefile +++ b/arch/arm/mach-tegra/tegra124/Makefile @@ -6,6 +6,7 @@ # obj-$(CONFIG_XPL_BUILD) += cpu.o +obj-$(CONFIG_$(XPL_)CMD_EBTUPDATE) += bct.o obj-y += clock.o obj-y += pmc.o diff --git a/arch/arm/mach-tegra/tegra124/bct.c b/arch/arm/mach-tegra/tegra124/bct.c new file mode 100644 index 00000000000..a71aa87fce1 --- /dev/null +++ b/arch/arm/mach-tegra/tegra124/bct.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, Ramin <raminterex@yahoo.com> + * Copyright (c) 2022, Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <command.h> +#include <log.h> +#include <vsprintf.h> +#include <asm/arch-tegra/crypto.h> +#include "bct.h" +#include "uboot_aes.h" + +/* Device with "sbk burned: false" will expose zero key */ +const u8 nosbk[AES128_KEY_LENGTH] = { 0 }; + +/* + * @param bct boot config table start in RAM + * @param ect bootloader start in RAM + * @param ebt_size bootloader file size in bytes + * Return: 0, or 1 if failed + */ +static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) +{ + struct nvboot_config_table *bct_tbl = NULL; + u8 ebt_hash[AES128_KEY_LENGTH] = { 0 }; + u8 bct_hash[AES128_KEY_LENGTH] = { 0 }; + u8 sbk[AES128_KEY_LENGTH] = { 0 }; + u8 *sbct = bct + UBCT_LENGTH; + bool encrypted; + int ret; + + ebt_size = roundup(ebt_size, EBT_ALIGNMENT); + + memcpy(sbk, (u8 *)(bct + UBCT_LENGTH + SBCT_LENGTH), + NVBOOT_CMAC_AES_HASH_LENGTH * 4); + + encrypted = memcmp(&sbk, &nosbk, AES128_KEY_LENGTH); + + if (encrypted) { + ret = decrypt_data_block(sbct, SBCT_LENGTH, sbk); + if (ret) + return 1; + + ret = encrypt_data_block(ebt, ebt_size, sbk); + if (ret) + return 1; + } + + ret = sign_enc_data_block(ebt, ebt_size, ebt_hash, sbk); + if (ret) + return 1; + + bct_tbl = (struct nvboot_config_table *)bct; + + memcpy((u8 *)&bct_tbl->bootloader[0].crypto_hash, + ebt_hash, NVBOOT_CMAC_AES_HASH_LENGTH * 4); + bct_tbl->bootloader[0].entry_point = CONFIG_SPL_TEXT_BASE; + bct_tbl->bootloader[0].load_addr = CONFIG_SPL_TEXT_BASE; + bct_tbl->bootloader[0].length = ebt_size; + + if (encrypted) { + ret = encrypt_data_block(sbct, SBCT_LENGTH, sbk); + if (ret) + return 1; + } + + ret = sign_enc_data_block(sbct, SBCT_LENGTH, bct_hash, sbk); + if (ret) + return 1; + + memcpy((u8 *)&bct_tbl->crypto_hash, bct_hash, + NVBOOT_CMAC_AES_HASH_LENGTH * 4); + + return 0; +} + +static int do_ebtupdate(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + u32 bct_addr = hextoul(argv[1], NULL); + u32 ebt_addr = hextoul(argv[2], NULL); + u32 ebt_size = hextoul(argv[3], NULL); + + return bct_patch((u8 *)bct_addr, (u8 *)ebt_addr, ebt_size); +} + +U_BOOT_CMD(ebtupdate, 4, 0, do_ebtupdate, + "update bootloader on re-crypted Tegra124 devices", + "" +); diff --git a/arch/arm/mach-tegra/tegra124/bct.h b/arch/arm/mach-tegra/tegra124/bct.h new file mode 100644 index 00000000000..eb0f712d595 --- /dev/null +++ b/arch/arm/mach-tegra/tegra124/bct.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _BCT_H_ +#define _BCT_H_ + +/* + * Defines the BCT parametres for T124 + */ +#define UBCT_LENGTH 0x6b0 /* bytes */ +#define SBCT_LENGTH 0x1950 /* bytes */ + +#define BCT_HASH 0x10 +#define EBT_ALIGNMENT 0x10 + +/* + * Defines the CMAC-AES-128 hash length in 32 bit words. (128 bits = 4 words) + */ +#define NVBOOT_CMAC_AES_HASH_LENGTH 4 + +/* + * Defines the RSA modulus length in 32 bit words used for PKC secure boot. + */ +#define NVBOOT_SE_RSA_MODULUS_LENGTH 64 + +/* + * Defines the maximum number of bootloader descriptions in the BCT. + */ +#define NVBOOT_MAX_BOOTLOADERS 4 + +struct nv_bootloader_info { + u32 version; + u32 start_blk; + u32 start_page; + u32 length; + u32 load_addr; + u32 entry_point; + u32 attribute; + + /* Specifies the AES-CMAC MAC or RSASSA-PSS signature of the BL. */ + u32 crypto_hash[NVBOOT_CMAC_AES_HASH_LENGTH]; + u32 bl_rsa_sig[NVBOOT_SE_RSA_MODULUS_LENGTH]; +}; + +struct nvboot_config_table { + u32 ubct_unused1[196]; + u32 crypto_hash[NVBOOT_CMAC_AES_HASH_LENGTH]; + u32 ubct_unused2[228]; + + u32 sbct_unused1[1318]; + u32 bootloader_used; + struct nv_bootloader_info bootloader[NVBOOT_MAX_BOOTLOADERS]; + u32 sbct_unused2; +}; + +#endif /* _BCT_H_ */ diff --git a/arch/arm/mach-versal2/include/mach/hardware.h b/arch/arm/mach-versal2/include/mach/hardware.h index 42e3061a0ae..15085f941e0 100644 --- a/arch/arm/mach-versal2/include/mach/hardware.h +++ b/arch/arm/mach-versal2/include/mach/hardware.h @@ -51,7 +51,8 @@ struct crp_regs { #define PMC_TAP_VERSION (PMC_TAP + 0x4) # define PMC_VERSION_MASK GENMASK(7, 0) # define PS_VERSION_MASK GENMASK(15, 8) -# define PS_VERSION_PRODUCTION 0x20 +# define PS_VERSION_MAJOR GENMASK(7, 4) +# define PS_VERSION_MINOR GENMASK(3, 0) # define RTL_VERSION_MASK GENMASK(23, 16) # define PLATFORM_MASK GENMASK(27, 24) # define PLATFORM_VERSION_MASK GENMASK(31, 28) diff --git a/arch/riscv/include/asm/setjmp.h b/arch/riscv/include/asm/setjmp.h index 72383d43303..08687e0f92b 100644 --- a/arch/riscv/include/asm/setjmp.h +++ b/arch/riscv/include/asm/setjmp.h @@ -3,13 +3,9 @@ * (C) Copyright 2018 Alexander Graf <agraf@suse.de> */ -#ifndef _SETJMP_H_ -#define _SETJMP_H_ 1 +#ifndef _ASM_SETJMP_H_ +#define _ASM_SETJMP_H_ 1 -/* - * This really should be opaque, but the EFI implementation wrongly - * assumes that a 'struct jmp_buf_data' is defined. - */ struct jmp_buf_data { /* x2, x8, x9, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, sp */ unsigned long s_regs[12]; /* s0 - s11 */ @@ -17,9 +13,4 @@ struct jmp_buf_data { unsigned long sp; }; -typedef struct jmp_buf_data jmp_buf[1]; - -int setjmp(jmp_buf jmp); -void longjmp(jmp_buf jmp, int ret); - -#endif /* _SETJMP_H_ */ +#endif /* _ASM_SETJMP_H_ */ diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c index 76c610bcee0..9544907ab1e 100644 --- a/arch/riscv/lib/bootm.c +++ b/arch/riscv/lib/bootm.c @@ -46,10 +46,6 @@ static void announce_and_cleanup(int fake) bootstage_report(); #endif -#ifdef CONFIG_USB_DEVICE - udc_disconnect(); -#endif - board_quiesce_devices(); /* diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig index 4c169034d9a..d61a327f151 100644 --- a/arch/sandbox/Kconfig +++ b/arch/sandbox/Kconfig @@ -77,7 +77,7 @@ config SANDBOX_BITS_PER_LONG config SYS_FDT_LOAD_ADDR hex "Address at which to load devicetree" - default 0x100 + default 0x1000 help With sandbox the devicetree is loaded into the emulated RAM. This sets the address that is used. There must be enough space at this address diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index 6407193c5f1..6db8739e66b 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -10,10 +10,10 @@ #include <errno.h> #include <log.h> #include <os.h> +#include <setjmp.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/malloc.h> -#include <asm/setjmp.h> #include <asm/state.h> #include <dm/ofnode.h> #include <linux/delay.h> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index b8f3012873e..52e9ddbf50f 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -1047,6 +1047,31 @@ }; }; + lvds-encoder { + compatible = "lvds-encoder"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + bridge_input: endpoint { + /* link to output */ + }; + }; + + port@1 { + reg = <1>; + + bridge_output: endpoint { + remote-endpoint = <&panel_input>; + }; + }; + }; + }; + wdt-gpio-toggle { gpios = <&gpio_a 8 0>; compatible = "linux,wdt-gpio"; @@ -1402,6 +1427,27 @@ panel { compatible = "simple-panel"; backlight = <&backlight 0 100>; + + display-timings { + timing@0 { + /* 1280x800@60Hz */ + clock-frequency = <68000000>; + hactive = <1280>; + hfront-porch = <48>; + hback-porch = <18>; + hsync-len = <30>; + vactive = <800>; + vfront-porch = <3>; + vback-porch = <12>; + vsync-len = <5>; + }; + }; + + port { + panel_input: endpoint { + remote-endpoint = <&bridge_output>; + }; + }; }; scsi { @@ -2048,6 +2094,61 @@ sandbox,err-step-size = <512>; }; }; + + graph1 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <0>; + + endpoint@0 { + reg = <0>; + }; + + endpoint@1 { + reg = <1>; + }; + }; + + port@1 { + reg = <1>; + + endpoint { + test-property-0; + }; + }; + + port@2 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <2>; + + graph2_link: endpoint@0 { + reg = <0>; + test-property-1; + remote-endpoint = <&graph1_link>; + }; + + endpoint@1 { + reg = <1>; + }; + }; + }; + }; + + graph2 { + port { + graph1_link: endpoint { + remote-endpoint = <&graph2_link>; + }; + }; + }; }; #include "sandbox_pmic.dtsi" diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h index 001c7ea322d..3413c747783 100644 --- a/arch/sandbox/include/asm/setjmp.h +++ b/arch/sandbox/include/asm/setjmp.h @@ -4,8 +4,8 @@ * Written by Simon Glass <sjg@chromium.org> */ -#ifndef _SETJMP_H_ -#define _SETJMP_H_ +#ifndef _ASM_SETJMP_H_ +#define _ASM_SETJMP_H_ struct jmp_buf_data { /* @@ -19,17 +19,7 @@ struct jmp_buf_data { * We don't need to worry about 16-byte alignment, since this does not * run on Windows. */ - ulong data[128]; + unsigned long data[128]; }; -typedef struct jmp_buf_data jmp_buf[1]; - -/* - * We have to directly link with the system versions of - * setjmp/longjmp, because setjmp must not return as otherwise - * the stack may become invalid. - */ -int setjmp(jmp_buf jmp); -__noreturn void longjmp(jmp_buf jmp, int ret); - -#endif /* _SETJMP_H_ */ +#endif /* _ASM_SETJMP_H_ */ diff --git a/arch/x86/cpu/intel_common/intel_opregion.c b/arch/x86/cpu/intel_common/intel_opregion.c index 78caff0dc12..4a2717b3584 100644 --- a/arch/x86/cpu/intel_common/intel_opregion.c +++ b/arch/x86/cpu/intel_common/intel_opregion.c @@ -31,6 +31,7 @@ static int locate_vbt(char **vbtp, int *sizep) size = vbt.size; if (size > sizeof(vbt_data)) return log_msg_ret("vbt", -E2BIG); + vbt.image_pos += CONFIG_ROM_SIZE; ret = spi_flash_read_dm(dev, vbt.image_pos, size, vbt_data); if (ret) return log_msg_ret("read", ret); diff --git a/arch/x86/include/asm/setjmp.h b/arch/x86/include/asm/setjmp.h index 15915d0dc6b..13772574e15 100644 --- a/arch/x86/include/asm/setjmp.h +++ b/arch/x86/include/asm/setjmp.h @@ -5,8 +5,8 @@ * From Linux arch/um/sys-i386/setjmp.S */ -#ifndef __setjmp_h -#define __setjmp_h +#ifndef _ASM_SETJMP_H_ +#define _ASM_SETJMP_H_ 1 #ifdef CONFIG_X86_64 @@ -34,9 +34,4 @@ struct jmp_buf_data { #endif -typedef struct jmp_buf_data jmp_buf[1]; - -int setjmp(jmp_buf env); -void longjmp(jmp_buf env, int val); - -#endif +#endif /* _ASM_SETJMP_H_ */ diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c index 1a2bf46c5c5..0be892b14dc 100644 --- a/arch/x86/lib/fsp2/fsp_init.c +++ b/arch/x86/lib/fsp2/fsp_init.c @@ -107,7 +107,6 @@ int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry, bool use_spi_flash, struct udevice **devp, struct fsp_header **hdrp, ulong *rom_offsetp) { - ulong mask = CONFIG_ROM_SIZE - 1; struct udevice *dev; ulong rom_offset = 0; uint map_size; @@ -141,7 +140,7 @@ int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry, if (ret) return log_msg_ret("binman entry", ret); if (!use_spi_flash) - rom_offset = (map_base & mask) - CONFIG_ROM_SIZE; + rom_offset = map_base + CONFIG_ROM_SIZE; } else { ret = -ENOENT; if (false) diff --git a/board/emulation/qemu-sbsa/Kconfig b/board/emulation/qemu-sbsa/Kconfig index 72c76b351fa..728cecae6b3 100644 --- a/board/emulation/qemu-sbsa/Kconfig +++ b/board/emulation/qemu-sbsa/Kconfig @@ -33,6 +33,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select OF_SEPARATE select PCI select PCIE_ECAM_GENERIC + select SYS_PCI_64BIT select USB select GIC_V3 select GIC_V3_ITS @@ -48,6 +49,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply CFI_FLASH imply SYS_MTDPARTS_RUNTIME imply SET_DFU_ALT_INFO + imply PCI_INIT_R if DEBUG_UART diff --git a/board/freescale/imx8mp_evk/imx8mp_evk.env b/board/freescale/imx8mp_evk/imx8mp_evk.env index 18f6c6e200e..f70e18fa9d9 100644 --- a/board/freescale/imx8mp_evk/imx8mp_evk.env +++ b/board/freescale/imx8mp_evk/imx8mp_evk.env @@ -16,6 +16,7 @@ mmcroot=/dev/mmcblk1p2 rootwait rw mmcautodetect=yes mmcargs=setenv bootargs ${jh_clk} ${mcore_clk} console=${console} root=${mmcroot} prepare_mcore=setenv mcore_clk clk-imx8mp.mcore_booted +kernel_addr_r=CONFIG_SYS_LOAD_ADDR loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image} loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} ${fdtfile} mmcboot=echo Booting from mmc ...; diff --git a/board/freescale/imx93_evk/imx93_evk.env b/board/freescale/imx93_evk/imx93_evk.env index f692f42f78a..8c3aef6b557 100644 --- a/board/freescale/imx93_evk/imx93_evk.env +++ b/board/freescale/imx93_evk/imx93_evk.env @@ -16,6 +16,7 @@ mmcroot=/dev/mmcblk1p2 rootwait rw mmcautodetect=yes mmcargs=setenv bootargs ${jh_clk} ${mcore_clk} console=${console} root=${mmcroot} prepare_mcore=setenv mcore_clk clk-imx93.mcore_booted +kernel_addr_r=CONFIG_SYS_LOAD_ADDR loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image} loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} ${fdtfile} loadcntr=fatload mmc ${mmcdev}:${mmcpart} ${cntr_addr} ${cntr_file} diff --git a/board/freescale/ls1021atsn/ls1021atsn.c b/board/freescale/ls1021atsn/ls1021atsn.c index d1acccec110..c92430c0896 100644 --- a/board/freescale/ls1021atsn/ls1021atsn.c +++ b/board/freescale/ls1021atsn/ls1021atsn.c @@ -166,10 +166,9 @@ void board_init_f(ulong dummy) get_clocks(); -#if defined(CONFIG_DEEP_SLEEP) - if (is_warm_boot()) - fsl_dp_disable_console(); -#endif + if (CONFIG_IS_ENABLED(DEEP_SLEEP)) + if (is_warm_boot()) + fsl_dp_disable_console(); preloader_console_init(); @@ -187,9 +186,11 @@ void board_init_f(ulong dummy) * it from SD since it has already been reserved in memory * in last boot. */ - if (is_warm_boot()) { - second_uboot = (void (*)(void))CONFIG_TEXT_BASE; - second_uboot(); + if (CONFIG_IS_ENABLED(DEEP_SLEEP)) { + if (is_warm_boot()) { + second_uboot = (void (*)(void))CONFIG_TEXT_BASE; + second_uboot(); + } } board_init_r(NULL, 0); diff --git a/board/freescale/ls1021atwr/ls1021atwr.c b/board/freescale/ls1021atwr/ls1021atwr.c index cc9665c0410..0758e5eae25 100644 --- a/board/freescale/ls1021atwr/ls1021atwr.c +++ b/board/freescale/ls1021atwr/ls1021atwr.c @@ -417,10 +417,9 @@ void board_init_f(ulong dummy) get_clocks(); -#if defined(CONFIG_DEEP_SLEEP) - if (is_warm_boot()) - fsl_dp_disable_console(); -#endif + if (CONFIG_IS_ENABLED(DEEP_SLEEP)) + if (is_warm_boot()) + fsl_dp_disable_console(); preloader_console_init(); @@ -438,9 +437,11 @@ void board_init_f(ulong dummy) * it from SD since it has already been reserved in memeory * in last boot. */ - if (is_warm_boot()) { - second_uboot = (void (*)(void))CONFIG_TEXT_BASE; - second_uboot(); + if (CONFIG_IS_ENABLED(DEEP_SLEEP)) { + if (is_warm_boot()) { + second_uboot = (void (*)(void))CONFIG_TEXT_BASE; + second_uboot(); + } } board_init_r(NULL, 0); diff --git a/board/gdsys/a38x/ihs_phys.c b/board/gdsys/a38x/ihs_phys.c index 0c68087912a..d51301869cd 100644 --- a/board/gdsys/a38x/ihs_phys.c +++ b/board/gdsys/a38x/ihs_phys.c @@ -123,9 +123,9 @@ struct gpio_mii { { 2, {}, {}, 46, 24, 1 }, }; -static int mii_mdio_init(struct bb_miiphy_bus *bus) +static int mii_mdio_init(const int k) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = &gpio_mii_set[k]; char name[32] = {}; struct udevice *gpio_dev1 = NULL; struct udevice *gpio_dev2 = NULL; @@ -164,27 +164,27 @@ static int mii_mdio_init(struct bb_miiphy_bus *bus) return 0; } -static int mii_mdio_active(struct bb_miiphy_bus *bus) +static int mii_mdio_active(struct mii_dev *miidev) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = miidev->priv; dm_gpio_set_value(&gpio_mii->mdc_gpio, gpio_mii->mdio_value); return 0; } -static int mii_mdio_tristate(struct bb_miiphy_bus *bus) +static int mii_mdio_tristate(struct mii_dev *miidev) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = miidev->priv; dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN); return 0; } -static int mii_set_mdio(struct bb_miiphy_bus *bus, int v) +static int mii_set_mdio(struct mii_dev *miidev, int v) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = miidev->priv; dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_OUT); dm_gpio_set_value(&gpio_mii->mdio_gpio, v); @@ -193,9 +193,9 @@ static int mii_set_mdio(struct bb_miiphy_bus *bus, int v) return 0; } -static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v) +static int mii_get_mdio(struct mii_dev *miidev, int *v) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = miidev->priv; dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN); *v = (dm_gpio_get_value(&gpio_mii->mdio_gpio)); @@ -203,51 +203,61 @@ static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v) return 0; } -static int mii_set_mdc(struct bb_miiphy_bus *bus, int v) +static int mii_set_mdc(struct mii_dev *miidev, int v) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = miidev->priv; dm_gpio_set_value(&gpio_mii->mdc_gpio, v); return 0; } -static int mii_delay(struct bb_miiphy_bus *bus) +static int mii_delay(struct mii_dev *miidev) { udelay(1); return 0; } +static const struct bb_miiphy_bus_ops mii_bb_miiphy_bus_ops = { + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, +}; + +static int mii_bb_miiphy_read(struct mii_dev *miidev, int addr, + int devad, int reg) +{ + return bb_miiphy_read(miidev, &mii_bb_miiphy_bus_ops, + addr, devad, reg); +} + +static int mii_bb_miiphy_write(struct mii_dev *miidev, int addr, + int devad, int reg, u16 value) +{ + return bb_miiphy_write(miidev, &mii_bb_miiphy_bus_ops, + addr, devad, reg, value); +} + int register_miiphy_bus(uint k, struct mii_dev **bus) { - struct bb_miiphy_bus *bb_miiphy = bb_miiphy_alloc(); - struct mii_dev *mdiodev; + struct mii_dev *mdiodev = mdio_alloc(); int retval; - if (!bb_miiphy) - return -ENOMEM; - - mdiodev = &bb_miiphy->mii; snprintf(mdiodev->name, MDIO_NAME_LEN, "ihs%d", k); - mdiodev->read = bb_miiphy_read; - mdiodev->write = bb_miiphy_write; - - /* Copy the bus accessors and private data */ - bb_miiphy->mdio_active = mii_mdio_active; - bb_miiphy->mdio_tristate = mii_mdio_tristate; - bb_miiphy->set_mdio = mii_set_mdio; - bb_miiphy->get_mdio = mii_get_mdio; - bb_miiphy->set_mdc = mii_set_mdc; - bb_miiphy->delay = mii_delay; - bb_miiphy->priv = &gpio_mii_set[k]; + mdiodev->read = mii_bb_miiphy_read; + mdiodev->write = mii_bb_miiphy_write; + mdiodev->priv = &gpio_mii_set[k]; retval = mdio_register(mdiodev); if (retval < 0) return retval; - *bus = &bb_miiphy->mii; + *bus = mdiodev; - return mii_mdio_init(bb_miiphy); + return mii_mdio_init(k); } struct porttype *get_porttype(uint octo_phy_mask, uint k) diff --git a/board/siemens/iot2050/board.c b/board/siemens/iot2050/board.c index e6bedc38917..d827f728a08 100644 --- a/board/siemens/iot2050/board.c +++ b/board/siemens/iot2050/board.c @@ -25,28 +25,7 @@ #include <asm/gpio.h> #include <asm/io.h> -#define IOT2050_INFO_MAGIC 0x20502050 - -struct iot2050_info { - u32 magic; - u16 size; - char name[20 + 1]; - char serial[16 + 1]; - char mlfb[18 + 1]; - char uuid[32 + 1]; - char a5e[18 + 1]; - u8 mac_addr_cnt; - u8 mac_addr[8][ARP_HLEN]; - char seboot_version[40 + 1]; - u8 padding[3]; - u32 ddr_size_mb; -} __packed; - -/* - * Scratch SRAM (available before DDR RAM) contains extracted EEPROM data. - */ -#define IOT2050_INFO_DATA ((struct iot2050_info *) \ - TI_SRAM_SCRATCH_BOARD_EEPROM_START) +#include "../../../../drivers/sysinfo/iot2050.h" DECLARE_GLOBAL_DATA_PTR; @@ -117,6 +96,8 @@ static const char *m2_connector_mode_name[] = { static enum m2_connector_mode connector_mode; +static char iot2050_board_name[21]; + #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) static void *connector_overlay; static u32 connector_overlay_size; @@ -149,37 +130,57 @@ static void set_pinvalue(const char *gpio_name, const char *label, int value) dm_gpio_set_value(&gpio, value); } +static bool setup_sysinfo(struct udevice **sysinfo_ptr) +{ + if (sysinfo_get(sysinfo_ptr)) { + pr_err("Could not find sysinfo device.\n"); + return false; + } + if (sysinfo_detect(*sysinfo_ptr)) { + pr_err("Board info parsing error\n"); + return false; + } + return true; +} + +static void get_board_name(void) +{ + struct udevice *sysinfo; + + if (iot2050_board_name[0] != 0) + return; + + if (!setup_sysinfo(&sysinfo)) + return; + + sysinfo_get_str(sysinfo, BOARD_NAME, sizeof(iot2050_board_name), + iot2050_board_name); +} + static bool board_is_advanced(void) { - struct iot2050_info *info = IOT2050_INFO_DATA; - return info->magic == IOT2050_INFO_MAGIC && - strstr((char *)info->name, "IOT2050-ADVANCED") != NULL; + get_board_name(); + return strstr(iot2050_board_name, "IOT2050-ADVANCED") != NULL; } static bool board_is_pg1(void) { - struct iot2050_info *info = IOT2050_INFO_DATA; - - return info->magic == IOT2050_INFO_MAGIC && - (strcmp((char *)info->name, "IOT2050-BASIC") == 0 || - strcmp((char *)info->name, "IOT2050-ADVANCED") == 0); + get_board_name(); + return strcmp(iot2050_board_name, "IOT2050-BASIC") == 0 || + strcmp(iot2050_board_name, "IOT2050-ADVANCED") == 0; } static bool board_is_m2(void) { - struct iot2050_info *info = IOT2050_INFO_DATA; - - return info->magic == IOT2050_INFO_MAGIC && - strcmp((char *)info->name, "IOT2050-ADVANCED-M2") == 0; + get_board_name(); + return strcmp(iot2050_board_name, "IOT2050-ADVANCED-M2") == 0; } static bool board_is_sm(void) { - struct iot2050_info *info = IOT2050_INFO_DATA; - - return info->magic == IOT2050_INFO_MAGIC && - strcmp((char *)info->name, "IOT2050-ADVANCED-SM") == 0; + get_board_name(); + return strcmp(iot2050_board_name, "IOT2050-ADVANCED-SM") == 0; } static void remove_mmc1_target(void) @@ -206,33 +207,43 @@ static void enable_pcie_connector_power(void) void set_board_info_env(void) { - struct iot2050_info *info = IOT2050_INFO_DATA; - u8 __maybe_unused mac_cnt; + struct udevice *sysinfo; const char *fdtfile; + char buf[41]; - if (info->magic != IOT2050_INFO_MAGIC) { - pr_err("IOT2050: Board info parsing error!\n"); + if (env_get("board_uuid")) return; - } - if (env_get("board_uuid")) + if (!setup_sysinfo(&sysinfo)) return; - env_set("board_name", info->name); - env_set("board_serial", info->serial); - env_set("mlfb", info->mlfb); - env_set("board_uuid", info->uuid); - env_set("board_a5e", info->a5e); + if (sysinfo_get_str(sysinfo, BOARD_NAME, sizeof(buf), buf) == 0) + env_set("board_name", buf); + if (sysinfo_get_str(sysinfo, SYSID_SM_SYSTEM_SERIAL, sizeof(buf), buf) == 0) + env_set("board_serial", buf); + if (sysinfo_get_str(sysinfo, BOARD_MLFB, sizeof(buf), buf) == 0) + env_set("mlfb", buf); + if (sysinfo_get_str(sysinfo, BOARD_UUID, sizeof(buf), buf) == 0) + env_set("board_uuid", buf); + if (sysinfo_get_str(sysinfo, BOARD_A5E, sizeof(buf), buf) == 0) + env_set("board_a5e", buf); + if (sysinfo_get_str(sysinfo, BOARD_SEBOOT_VER, sizeof(buf), buf) == 0) + env_set("seboot_version", buf); env_set("fw_version", PLAIN_VERSION); - env_set("seboot_version", info->seboot_version); if (IS_ENABLED(CONFIG_NET)) { + int mac_cnt; + + mac_cnt = sysinfo_get_item_count(sysinfo, SYSID_BOARD_MAC_ADDR); /* set MAC addresses to ensure forwarding to the OS */ - for (mac_cnt = 0; mac_cnt < info->mac_addr_cnt; mac_cnt++) { - if (is_valid_ethaddr(info->mac_addr[mac_cnt])) - eth_env_set_enetaddr_by_index("eth", - mac_cnt + 1, - info->mac_addr[mac_cnt]); + for (int i = 0; i < mac_cnt; i++) { + u8 *mac = NULL; + size_t bytes = 0; + + sysinfo_get_data_by_index(sysinfo, SYSID_BOARD_MAC_ADDR, + i, (void **)&mac, &bytes); + if (bytes == ARP_HLEN && is_valid_ethaddr(mac)) + eth_env_set_enetaddr_by_index("eth", i + 1, mac); } } @@ -288,7 +299,7 @@ static void do_overlay_prepare(const char *overlay_path) return; fit_error: - pr_err("M.2 device tree overlay %s not available,\n", overlay_path); + pr_err("M.2 device tree overlay %s not available.\n", overlay_path); #endif } @@ -362,8 +373,15 @@ int board_init(void) int dram_init(void) { - struct iot2050_info *info = IOT2050_INFO_DATA; - gd->ram_size = ((phys_size_t)(info->ddr_size_mb)) << 20; + struct udevice *sysinfo; + u32 ddr_size_mb; + + if (!setup_sysinfo(&sysinfo)) + return -ENODEV; + + sysinfo_get_int(sysinfo, SYSID_BOARD_RAM_SIZE_MB, &ddr_size_mb); + + gd->ram_size = ((phys_size_t)(ddr_size_mb)) << 20; return 0; } @@ -405,18 +423,18 @@ int dram_init_banksize(void) #ifdef CONFIG_SPL_LOAD_FIT int board_fit_config_name_match(const char *name) { - struct iot2050_info *info = IOT2050_INFO_DATA; char upper_name[32]; + get_board_name(); + /* skip the prefix "ti/k3-am65x8-" */ name += 13; - if (info->magic != IOT2050_INFO_MAGIC || - strlen(name) >= sizeof(upper_name)) + if (strlen(name) >= sizeof(upper_name)) return -1; str_to_upper(name, upper_name, sizeof(upper_name)); - if (!strcmp(upper_name, (char *)info->name)) + if (!strcmp(upper_name, iot2050_board_name)) return 0; return -1; diff --git a/board/st/stm32f746-disco/MAINTAINERS b/board/st/stm32f746-disco/MAINTAINERS index 18e4c99c4fb..f9c3af6fb8b 100644 --- a/board/st/stm32f746-disco/MAINTAINERS +++ b/board/st/stm32f746-disco/MAINTAINERS @@ -1,5 +1,5 @@ STM32F746 DISCOVERY BOARD -M: Vikas Manocha <vikas.manocha@st.com> +M: Patrice Chotard <patrice.chotard@foss.st.com> S: Maintained F: doc/board/st/ F: board/st/stm32f746-disco diff --git a/board/st/stm32f746-disco/stm32f746-disco.c b/board/st/stm32f746-disco/stm32f746-disco.c index 8966a09501e..07bc8a5f0a2 100644 --- a/board/st/stm32f746-disco/stm32f746-disco.c +++ b/board/st/stm32f746-disco/stm32f746-disco.c @@ -76,42 +76,6 @@ u32 spl_boot_device(void) } #endif -int board_late_init(void) -{ - struct gpio_desc gpio = {}; - int node; - - node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "st,led1"); - if (node < 0) - return -1; - - gpio_request_by_name_nodev(offset_to_ofnode(node), "led-gpio", 0, &gpio, - GPIOD_IS_OUT); - - if (dm_gpio_is_valid(&gpio)) { - dm_gpio_set_value(&gpio, 0); - mdelay(10); - dm_gpio_set_value(&gpio, 1); - } - - /* read button 1*/ - node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "st,button1"); - if (node < 0) - return -1; - - gpio_request_by_name_nodev(offset_to_ofnode(node), "button-gpio", 0, - &gpio, GPIOD_IS_IN); - - if (dm_gpio_is_valid(&gpio)) { - if (dm_gpio_get_value(&gpio)) - puts("usr button is at HIGH LEVEL\n"); - else - puts("usr button is at LOW LEVEL\n"); - } - - return 0; -} - int board_init(void) { #ifdef CONFIG_ETH_DESIGNWARE diff --git a/board/toradex/verdin-am62/verdin-am62.c b/board/toradex/verdin-am62/verdin-am62.c index b80b39b6767..a1c471111a0 100644 --- a/board/toradex/verdin-am62/verdin-am62.c +++ b/board/toradex/verdin-am62/verdin-am62.c @@ -15,6 +15,7 @@ #include <init.h> #include <k3-ddrss.h> #include <spl.h> +#include <asm/arch/k3-ddr.h> #include "../common/tdx-cfg-block.h" @@ -43,6 +44,9 @@ int dram_init_banksize(void) if (ret) printf("Error setting up memory banksize. %d\n", ret); + /* Use the detected RAM size, we only support 1 bank right now. */ + gd->bd->bi_dram[0].size = gd->ram_size; + return ret; } @@ -108,6 +112,13 @@ int board_late_init(void) #define CORE_VOLTAGE 0x80000000 #define MCU_CTRL_LFXOSC_32K_BYPASS_VAL BIT(4) +#if IS_ENABLED(CONFIG_XPL_BUILD) +void spl_perform_fixups(struct spl_image_info *spl_image) +{ + fixup_memory_node(spl_image); +} +#endif + #ifdef CONFIG_SPL_BOARD_INIT void spl_board_init(void) { diff --git a/board/xiaomi/mocha/Kconfig b/board/xiaomi/mocha/Kconfig new file mode 100644 index 00000000000..25c61d4169e --- /dev/null +++ b/board/xiaomi/mocha/Kconfig @@ -0,0 +1,12 @@ +if TARGET_MOCHA + +config SYS_BOARD + default "mocha" + +config SYS_VENDOR + default "xiaomi" + +config SYS_CONFIG_NAME + default "mocha" + +endif diff --git a/board/xiaomi/mocha/MAINTAINERS b/board/xiaomi/mocha/MAINTAINERS new file mode 100644 index 00000000000..c3871a15a35 --- /dev/null +++ b/board/xiaomi/mocha/MAINTAINERS @@ -0,0 +1,8 @@ +MOCHA BOARD +M: Svyatoslav Ryhel <clamor95@gmail.com> +S: Maintained +F: arch/arm/dts/tegra124-xiaomi-mocha.dts +F: board/xiaomi/mocha/ +F: configs/mocha_defconfig +F: doc/board/xiaomi/mocha.rst +F: include/configs/mocha.h diff --git a/board/xiaomi/mocha/Makefile b/board/xiaomi/mocha/Makefile new file mode 100644 index 00000000000..c42e42639b3 --- /dev/null +++ b/board/xiaomi/mocha/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2024, Svyatoslav Ryhel <clamor95@gmail.com> +# + +obj-$(CONFIG_XPL_BUILD) += mocha-spl.o + +obj-y += mocha.o + diff --git a/board/xiaomi/mocha/mocha-spl.c b/board/xiaomi/mocha/mocha-spl.c new file mode 100644 index 00000000000..5fb11df0a93 --- /dev/null +++ b/board/xiaomi/mocha/mocha-spl.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Mocha SPL stage configuration + * + * (C) Copyright 2024 + * Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/tegra_i2c.h> +#include <linux/delay.h> + +#define TPS65913_I2C_ADDR (0x58 << 1) + +#define TPS65913_SMPS12_CTRL 0x20 +#define TPS65913_SMPS12_VOLTAGE 0x23 +#define TPS65913_SMPS45_CTRL 0x28 +#define TPS65913_SMPS45_VOLTAGE 0x2B +#define TPS65913_SMPS7_CTRL 0x30 +#define TPS65913_SMPS7_VOLTAGE 0x33 + +#define TPS65913_SMPS12_CTRL_DATA (0x5100 | TPS65913_SMPS12_CTRL) +#define TPS65913_SMPS12_VOLTAGE_DATA (0x3800 | TPS65913_SMPS12_VOLTAGE) +#define TPS65913_SMPS45_CTRL_DATA (0x5100 | TPS65913_SMPS45_CTRL) +#define TPS65913_SMPS45_VOLTAGE_DATA (0x3800 | TPS65913_SMPS45_VOLTAGE) +#define TPS65913_SMPS7_CTRL_DATA (0x5100 | TPS65913_SMPS7_CTRL) +#define TPS65913_SMPS7_VOLTAGE_DATA (0x4700 | TPS65913_SMPS7_VOLTAGE) + +void pmic_enable_cpu_vdd(void) +{ + /* Set CORE VDD to 1.150V. */ + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS7_VOLTAGE_DATA); + udelay(1000); + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS7_CTRL_DATA); + + udelay(1000); + + /* Set CPU VDD to 1.0V. */ + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS12_VOLTAGE_DATA); + udelay(1000); + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS12_CTRL_DATA); + udelay(10 * 1000); + + /* Set GPU VDD to 1.0V. */ + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS45_VOLTAGE_DATA); + udelay(1000); + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS45_CTRL_DATA); + udelay(10 * 1000); +} diff --git a/board/xiaomi/mocha/mocha.c b/board/xiaomi/mocha/mocha.c new file mode 100644 index 00000000000..5026d541a5f --- /dev/null +++ b/board/xiaomi/mocha/mocha.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2024 + * Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <dm.h> +#include <fdt_support.h> +#include <i2c.h> +#include <log.h> + +#ifdef CONFIG_MMC_SDHCI_TEGRA + +#define TPS65913_I2C_ADDRESS 0x58 +#define TPS65913_PRIMARY_SECONDARY_PAD2 0xfb +#define GPIO_4 BIT(0) +#define TPS65913_PRIMARY_SECONDARY_PAD3 0xfe +#define DVFS2 BIT(1) +#define DVFS1 BIT(0) + +/* We are using this function only till palmas pinctrl driver is available */ +void pin_mux_mmc(void) +{ + struct udevice *dev; + int ret; + + ret = i2c_get_chip_for_busnum(0, TPS65913_I2C_ADDRESS, 1, &dev); + if (ret) { + log_debug("%s: cannot find PMIC I2C chip\n", __func__); + return; + } + + /* GPIO4 function has to be GPIO */ + dm_i2c_reg_clrset(dev, TPS65913_PRIMARY_SECONDARY_PAD2, + GPIO_4, 0); + + /* DVFS1 and DVFS2 are disabled */ + dm_i2c_reg_clrset(dev, TPS65913_PRIMARY_SECONDARY_PAD3, + DVFS2 | DVFS1, 0); +} +#endif diff --git a/board/xiaomi/mocha/mocha.env b/board/xiaomi/mocha/mocha.env new file mode 100644 index 00000000000..d93e24316f6 --- /dev/null +++ b/board/xiaomi/mocha/mocha.env @@ -0,0 +1,23 @@ +#include <env/nvidia/prod_upd.env> + +button_cmd_0_name=Volume Down +button_cmd_0=bootmenu +button_cmd_1_name=Hall sensor (back) +button_cmd_1=poweroff +button_cmd_1_name=Hall sensor (front) +button_cmd_1=poweroff + +partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs} + +boot_block_size_r=0x400000 +boot_block_size=0x2000 +boot_dev=1 + +bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu +bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu +bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu +bootmenu_3=update bootloader=run flash_uboot +bootmenu_4=reboot RCM=enterrcm +bootmenu_5=reboot=reset +bootmenu_6=power off=poweroff +bootmenu_delay=-1 diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index a852d5b8ed5..8dbfa560423 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -179,6 +179,7 @@ void set_dfu_alt_info(char *interface, char *devstr) memset(buf, 0, sizeof(buf)); switch ((zynq_slcr_get_boot_mode()) & ZYNQ_BM_MASK) { +#if defined(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME) case ZYNQ_BM_SD: snprintf(buf, DFU_ALT_BUF_LEN, "mmc 0=boot.bin fat 0 1;" @@ -193,6 +194,7 @@ void set_dfu_alt_info(char *interface, char *devstr) CONFIG_SYS_SPI_U_BOOT_OFFS); break; #endif +#endif default: return; } diff --git a/boot/image-pre-load.c b/boot/image-pre-load.c index cc19017404c..adf3b341a20 100644 --- a/boot/image-pre-load.c +++ b/boot/image-pre-load.c @@ -3,13 +3,24 @@ * Copyright (C) 2021 Philippe Reynes <philippe.reynes@softathome.com> */ +#ifdef USE_HOSTCC +#include "mkimage.h" +#else #include <asm/global_data.h> -DECLARE_GLOBAL_DATA_PTR; -#include <image.h> #include <mapmem.h> +DECLARE_GLOBAL_DATA_PTR; +#endif /* !USE_HOSTCC*/ +#include <image.h> #include <u-boot/sha256.h> +#ifdef USE_HOSTCC +/* Define compat stuff for use in tools. */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +#endif + /* * Offset of the image * @@ -17,6 +28,47 @@ DECLARE_GLOBAL_DATA_PTR; */ ulong image_load_offset; +#ifdef USE_HOSTCC +/* Host tools use these implementations to setup information related to the + * pre-load signatures + */ +static struct image_sig_info *host_info; + +#define log_info(fmt, args...) printf(fmt, ##args) +#define log_err(fmt, args...) printf(fmt, ##args) + +void image_pre_load_sig_set_info(struct image_sig_info *info) +{ + host_info = info; +} + +/* + * This function sets a pointer to information for the signature check. + * It expects that host_info has been initially provision by the host + * application. + * + * return: + * < 0 => an error has occurred + * 0 => OK + */ +static int image_pre_load_sig_setup(struct image_sig_info *info) +{ + if (!info) { + log_err("ERROR: info is NULL\n"); + return -EINVAL; + } + + if (!host_info) { + log_err("ERROR: host_info is NULL\n"); + log_err("ERROR: Set it with image_pre_load_sig_set_info()\n"); + return -EINVAL; + } + + memcpy(info, host_info, sizeof(struct image_sig_info)); + + return 0; +} +#else /* * This function gathers information about the signature check * that could be done before launching the image. @@ -106,6 +158,7 @@ static int image_pre_load_sig_setup(struct image_sig_info *info) out: return ret; } +#endif /* !USE_HOSTCC */ static int image_pre_load_sig_get_magic(ulong addr, u32 *magic) { diff --git a/cmd/Kconfig b/cmd/Kconfig index 8dd42571abc..cd391d422ae 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2169,7 +2169,6 @@ config WGET_HTTPS select ASYMMETRIC_PUBLIC_KEY_SUBTYPE select X509_CERTIFICATE_PARSER select PKCS7_MESSAGE_PARSER - select MBEDTLS_LIB_CRYPTO select MBEDTLS_LIB_TLS select RSA_VERIFY_WITH_PKEY select X509_CERTIFICATE_PARSER @@ -2177,6 +2176,28 @@ config WGET_HTTPS help Enable TLS over http for wget. +config WGET_CACERT + bool "wget cacert" + depends on CMD_WGET + depends on WGET_HTTPS + help + Adds the "cacert" sub-command to wget to provide root certificates + to the HTTPS engine. Must be in DER format. + +config WGET_BUILTIN_CACERT + bool "Built-in CA certificates" + depends on WGET_HTTPS + select BUILD_BIN2C + +config WGET_BUILTIN_CACERT_PATH + string "Path to root certificates" + depends on WGET_BUILTIN_CACERT + default "cacert.crt" + help + Set this to the path to a DER-encoded X509 file containing + Certification Authority certificates, a.k.a. root certificates, for + the purpose of authenticating HTTPS connections. + endif # if CMD_NET config CMD_PXE @@ -110,3 +110,17 @@ U_BOOT_CMD( fstypes, 1, 1, do_fstypes_wrapper, "List supported filesystem types", "" ); + +static int do_mv_wrapper(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + return do_mv(cmdtp, flag, argc, argv, FS_TYPE_ANY); +} + +U_BOOT_CMD( + mv, 5, 1, do_mv_wrapper, + "rename/move a file/directory", + "<interface> [<dev[:part]>] <old_path> <new_path>\n" + " - renames/moves a file/directory in 'dev' on 'interface' from\n" + " 'old_path' to 'new_path'" +); diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c index 0fd446ecb20..58c10fbec7d 100644 --- a/cmd/net-lwip.c +++ b/cmd/net-lwip.c @@ -27,9 +27,24 @@ U_BOOT_CMD(dns, 3, 1, do_dns, "lookup the IP of a hostname", #endif #if defined(CONFIG_CMD_WGET) -U_BOOT_CMD(wget, 3, 1, do_wget, - "boot image via network using HTTP/HTTPS protocol", +U_BOOT_CMD(wget, 4, 1, do_wget, + "boot image via network using HTTP/HTTPS protocol" +#if defined(CONFIG_WGET_CACERT) + "\nwget cacert - configure wget root certificates" +#endif + , "[loadAddress] url\n" - "wget [loadAddress] [host:]path" + "wget [loadAddress] [host:]path\n" + " - load file" +#if defined(CONFIG_WGET_CACERT) + "\nwget cacert <address> <length>\n" + " - provide CA certificates (0 0 to remove current)" + "\nwget cacert none|optional|required\n" + " - set server certificate verification mode (default: optional)" +#if defined(CONFIG_WGET_BUILTIN_CACERT) + "\nwget cacert builtin\n" + " - use the builtin CA certificates" +#endif +#endif ); #endif diff --git a/cmd/ufetch.c b/cmd/ufetch.c index ed5a856c7ab..46bd16824e6 100644 --- a/cmd/ufetch.c +++ b/cmd/ufetch.c @@ -24,8 +24,8 @@ DECLARE_GLOBAL_DATA_PTR; #define LINE_WIDTH 40 -#define BLUE "\033[38;5;4m" -#define YELLOW "\033[38;5;11m" +#define BLUE "\033[34m" +#define YELLOW "\033[33m" #define BOLD "\033[1m" #define RESET "\033[0m" static const char * const logo_lines[] = { diff --git a/common/Kconfig b/common/Kconfig index 1d6de8badf7..a1f65559a1b 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1080,7 +1080,7 @@ endchoice config BLOBLIST_ADDR hex "Address of bloblist" - default 0xb000 if SANDBOX + default 0x100 if SANDBOX depends on BLOBLIST_FIXED help Sets the address of the bloblist, set up by the first part of U-Boot diff --git a/common/board_f.c b/common/board_f.c index 2912320054f..baf98fb8ec8 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -828,13 +828,13 @@ static int initf_dm(void) bootstage_start(BOOTSTAGE_ID_ACCUM_DM_F, "dm_f"); ret = dm_init_and_scan(true); - bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F); if (ret) return ret; ret = dm_autoprobe(); if (ret) return ret; + bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F); if (IS_ENABLED(CONFIG_TIMER_EARLY)) { ret = dm_timer_init(); diff --git a/common/edid.c b/common/edid.c index 48a737690db..e2ac7100a88 100644 --- a/common/edid.c +++ b/common/edid.c @@ -16,6 +16,197 @@ #include <linux/ctype.h> #include <linux/string.h> +#define TIMING(c, ha, hfp, hbp, hsl, va, vfp, vbp, vsl, f) \ + .pixelclock = { (c), (c), (c) }, \ + .hactive = { (ha), (ha), (ha) }, \ + .hfront_porch = { (hfp), (hfp), (hfp) }, \ + .hback_porch = { (hbp), (hbp), (hbp) }, \ + .hsync_len = { (hsl), (hsl), (hsl) }, \ + .vactive = { (va), (va), (va) }, \ + .vfront_porch = { (vfp), (vfp), (vfp) }, \ + .vback_porch = { (vbp), (vbp), (vbp) }, \ + .vsync_len = { (vsl), (vsl), (vsl) }, \ + .flags = (f) + +static const struct display_timing dmt_timings[] = { + { TIMING(31500000, 640, 32, 64, 96, 350, 32, 3, 60, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(31500000, 640, 32, 64, 96, 400, 1, 3, 41, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(35500000, 720, 36, 72, 108, 400, 1, 3, 42, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(25175000, 640, 16, 96, 48, 480, 10, 2, 33, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(31500000, 640, 24, 40, 128, 480, 9, 3, 28, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(31500000, 640, 16, 64, 120, 480, 1, 3, 16, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(36000000, 640, 56, 56, 80, 480, 1, 3, 25, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(36000000, 800, 24, 72, 128, 600, 1, 2, 22, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(40000000, 800, 40, 128, 88, 600, 1, 4, 23, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(50000000, 800, 56, 120, 64, 600, 37, 6, 23, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(49500000, 800, 16, 80, 160, 600, 1, 3, 21, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(56250000, 800, 32, 64, 152, 600, 1, 3, 27, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(73250000, 800, 48, 32, 80, 600, 3, 4, 29, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(33750000, 848, 16, 112, 112, 480, 6, 8, 23, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(44900000, 1024, 8, 176, 56, 768, 0, 8, 41, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(65000000, 1024, 24, 136, 160, 768, 3, 6, 29, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(75000000, 1024, 24, 136, 144, 768, 3, 6, 29, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(78750000, 1024, 16, 96, 176, 768, 1, 3, 28, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(94500000, 1024, 48, 96, 208, 768, 1, 3, 36, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(115500000, 1024, 48, 32, 80, 768, 3, 4, 38, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(108000000, 1152, 64, 128, 256, 864, 1, 3, 32, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(74250000, 1280, 110, 40, 220, 720, 5, 5, 20, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(68250000, 1280, 48, 32, 80, 768, 3, 7, 12, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(79500000, 1280, 64, 128, 192, 768, 3, 7, 20, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(102250000, 1280, 80, 128, 208, 768, 3, 7, 27, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(117500000, 1280, 80, 136, 216, 768, 3, 7, 31, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(140250000, 1280, 48, 32, 80, 768, 3, 7, 35, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(71000000, 1280, 48, 32, 80, 800, 3, 6, 14, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(83500000, 1280, 72, 128, 200, 800, 3, 6, 22, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(106500000, 1280, 80, 128, 208, 800, 3, 6, 29, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(122500000, 1280, 80, 136, 216, 800, 3, 6, 34, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(146250000, 1280, 48, 32, 80, 800, 3, 6, 38, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(108000000, 1280, 96, 112, 312, 960, 1, 3, 36, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(148500000, 1280, 64, 160, 224, 960, 1, 3, 47, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(175500000, 1280, 48, 32, 80, 960, 3, 4, 50, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(108000000, 1280, 48, 112, 248, 1024, 1, 3, 38, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(135000000, 1280, 16, 144, 248, 1024, 1, 3, 38, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(157500000, 1280, 64, 160, 224, 1024, 1, 3, 44, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(187250000, 1280, 48, 32, 80, 1024, 3, 7, 50, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(85500000, 1360, 64, 112, 256, 768, 3, 6, 18, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(148250000, 1360, 48, 32, 80, 768, 3, 5, 37, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(85500000, 1366, 70, 143, 213, 768, 3, 3, 24, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(72000000, 1366, 14, 56, 64, 768, 1, 3, 28, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(101000000, 1400, 48, 32, 80, 1050, 3, 4, 23, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(121750000, 1400, 88, 144, 232, 1050, 3, 4, 32, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(156000000, 1400, 104, 144, 248, 1050, 3, 4, 42, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(179500000, 1400, 104, 152, 256, 1050, 3, 4, 48, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(208000000, 1400, 48, 32, 80, 1050, 3, 4, 55, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(88750000, 1440, 48, 32, 80, 900, 3, 6, 17, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(106500000, 1440, 80, 152, 232, 900, 3, 6, 25, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(136750000, 1440, 96, 152, 248, 900, 3, 6, 33, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(157000000, 1440, 104, 152, 256, 900, 3, 6, 39, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(182750000, 1440, 48, 32, 80, 900, 3, 6, 44, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(108000000, 1600, 24, 80, 96, 900, 1, 3, 96, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(162000000, 1600, 64, 192, 304, 1200, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(175500000, 1600, 64, 192, 304, 1200, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(189000000, 1600, 64, 192, 304, 1200, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(202500000, 1600, 64, 192, 304, 1200, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(229500000, 1600, 64, 192, 304, 1200, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(268250000, 1600, 48, 32, 80, 1200, 3, 4, 64, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(119000000, 1680, 48, 32, 80, 1050, 3, 6, 21, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(146250000, 1680, 104, 176, 280, 1050, 3, 6, 30, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(187000000, 1680, 120, 176, 296, 1050, 3, 6, 40, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(214750000, 1680, 128, 176, 304, 1050, 3, 6, 46, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(245500000, 1680, 48, 32, 80, 1050, 3, 6, 53, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(204750000, 1792, 128, 200, 328, 1344, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(261000000, 1792, 96, 216, 352, 1344, 1, 3, 69, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(333250000, 1792, 48, 32, 80, 1344, 3, 4, 72, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(218250000, 1856, 96, 224, 352, 1392, 1, 3, 43, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(288000000, 1856, 128, 224, 352, 1392, 1, 3, 104, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(356500000, 1856, 48, 32, 80, 1392, 3, 4, 75, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(148500000, 1920, 88, 44, 148, 1080, 4, 5, 36, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(154000000, 1920, 48, 32, 80, 1200, 3, 6, 26, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(193250000, 1920, 136, 200, 336, 1200, 3, 6, 36, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(245250000, 1920, 136, 208, 344, 1200, 3, 6, 46, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(281250000, 1920, 144, 208, 352, 1200, 3, 6, 53, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(317000000, 1920, 48, 32, 80, 1200, 3, 6, 62, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(234000000, 1920, 128, 208, 344, 1440, 1, 3, 56, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(297000000, 1920, 144, 224, 352, 1440, 1, 3, 56, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(380500000, 1920, 48, 32, 80, 1440, 3, 4, 78, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(162000000, 2048, 26, 80, 96, 1152, 1, 3, 44, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(268500000, 2560, 48, 32, 80, 1600, 3, 6, 37, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(348500000, 2560, 192, 280, 472, 1600, 3, 6, 49, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(443250000, 2560, 208, 280, 488, 1600, 3, 6, 63, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(505250000, 2560, 208, 280, 488, 1600, 3, 6, 73, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(552750000, 2560, 48, 32, 80, 1600, 3, 6, 85, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(556744000, 4096, 8, 32, 40, 2160, 48, 8, 6, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(556188000, 4096, 8, 32, 40, 2160, 48, 8, 6, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, +}; + int edid_check_info(struct edid1_info *edid_info) { if ((edid_info == NULL) || (edid_info->version == 0)) @@ -168,11 +359,11 @@ static bool cea_is_hdmi_vsdb_present(struct edid_cea861_info *info) return false; } -static bool edid_find_valid_timing(void *buf, int count, - struct display_timing *timing, - bool (*mode_valid)(void *priv, - const struct display_timing *timing), - void *mode_valid_priv) +static bool edid_find_valid_detailed_timing(void *buf, int count, + struct display_timing *timing, + bool (*mode_valid)(void *priv, + const struct display_timing *timing), + void *mode_valid_priv) { struct edid_detailed_timing *t = buf; bool found = false; @@ -191,6 +382,71 @@ static bool edid_find_valid_timing(void *buf, int count, return found; } +static bool edid_get_standard_timing(struct edid1_info *edid, int i, unsigned int *x, + unsigned int *y, unsigned int *freq) +{ + unsigned int aspect = 10000; + unsigned char xres, vfreq; + + xres = EDID1_INFO_STANDARD_TIMING_XRESOLUTION(*edid, i); + vfreq = EDID1_INFO_STANDARD_TIMING_VFREQ(*edid, i); + if (xres != vfreq || (xres != 0 && xres != 1) || + (vfreq != 0 && vfreq != 1)) { + switch (EDID1_INFO_STANDARD_TIMING_ASPECT(*edid, i)) { + case ASPECT_625: // 16:10 + aspect = 6250; + break; + case ASPECT_75: // 4:3 + aspect = 7500; + break; + case ASPECT_8: // 5:4 + aspect = 8000; + break; + case ASPECT_5625: // 16:9 + aspect = 5625; + break; + } + + *x = (xres + 31) * 8; + *y = *x * aspect / 10000; + *freq = (vfreq & 0x3f) + 60; + + return true; + } + + return false; +} + +static bool edid_find_valid_standard_timing(struct edid1_info *buf, + struct display_timing *timing, + bool (*mode_valid)(void *priv, + const struct display_timing *timing), + void *mode_valid_priv) +{ + unsigned int x, y, freq; + bool found = false; + int i, k; + + for (i = 0; i < ARRAY_SIZE(buf->standard_timings); i++) { + if (!edid_get_standard_timing(buf, i, &x, &y, &freq)) + continue; + + for (k = 0; k < ARRAY_SIZE(dmt_timings); k++) { + const struct display_timing *dt = &dmt_timings[k]; + + if (dt->hactive.typ == x && dt->vactive.typ == y) { + found = mode_valid(mode_valid_priv, dt); + if (found) { + memcpy(timing, dt, sizeof(*timing)); + return true; + } + } + } + } + + return found; +} + int edid_get_timing_validate(u8 *buf, int buf_size, struct display_timing *timing, int *panel_bits_per_colourp, @@ -217,8 +473,8 @@ int edid_get_timing_validate(u8 *buf, int buf_size, } /* Look for detailed timing in base EDID */ - found = edid_find_valid_timing(edid->monitor_details.descriptor, 4, - timing, mode_valid, mode_valid_priv); + found = edid_find_valid_detailed_timing(edid->monitor_details.descriptor, 4, + timing, mode_valid, mode_valid_priv); /* Look for detailed timing in CTA-861 Extension Block */ if (!found && edid->extension_flag && buf_size >= EDID_EXT_SIZE) { @@ -231,12 +487,17 @@ int edid_get_timing_validate(u8 *buf, int buf_size, int size = count * sizeof(struct edid_detailed_timing); if (offset >= 4 && offset + size < EDID_SIZE) - found = edid_find_valid_timing( + found = edid_find_valid_detailed_timing( (u8 *)info + offset, count, timing, mode_valid, mode_valid_priv); } } + /* Look for timing in Standard Timings */ + if (!found) + found = edid_find_valid_standard_timing(edid, timing, mode_valid, + mode_valid_priv); + if (!found) return -EINVAL; @@ -461,34 +722,11 @@ void edid_print_info(struct edid1_info *edid_info) /* Standard timings. */ printf("Standard timings:\n"); for (i = 0; i < ARRAY_SIZE(edid_info->standard_timings); i++) { - unsigned int aspect = 10000; - unsigned int x, y; - unsigned char xres, vfreq; - - xres = EDID1_INFO_STANDARD_TIMING_XRESOLUTION(*edid_info, i); - vfreq = EDID1_INFO_STANDARD_TIMING_VFREQ(*edid_info, i); - if ((xres != vfreq) || - ((xres != 0) && (xres != 1)) || - ((vfreq != 0) && (vfreq != 1))) { - switch (EDID1_INFO_STANDARD_TIMING_ASPECT(*edid_info, - i)) { - case ASPECT_625: - aspect = 6250; - break; - case ASPECT_75: - aspect = 7500; - break; - case ASPECT_8: - aspect = 8000; - break; - case ASPECT_5625: - aspect = 5625; - break; - } - x = (xres + 31) * 8; - y = x * aspect / 10000; + unsigned int x, y, freq; + + if (edid_get_standard_timing(edid_info, i, &x, &y, &freq)) { printf("\t%dx%d%c\t%d Hz\n", x, y, - x > 1000 ? ' ' : '\t', (vfreq & 0x3f) + 60); + x > 1000 ? ' ' : '\t', freq); have_timing = 1; } } diff --git a/common/miiphyutil.c b/common/miiphyutil.c index 2a034d3a77c..274e88a4921 100644 --- a/common/miiphyutil.c +++ b/common/miiphyutil.c @@ -30,7 +30,7 @@ #define debug(fmt, args...) #endif /* MII_DEBUG */ -static struct list_head mii_devs; +static LIST_HEAD(mii_devs); static struct mii_dev *current_mii; /* @@ -55,24 +55,6 @@ struct mii_dev *miiphy_get_dev_by_name(const char *devname) return NULL; } -/***************************************************************************** - * - * Initialize global data. Need to be called before any other miiphy routine. - */ -void miiphy_init(void) -{ - INIT_LIST_HEAD(&mii_devs); - current_mii = NULL; -} - -void mdio_init(struct mii_dev *bus) -{ - memset(bus, 0, sizeof(*bus)); - - /* initialize mii_dev struct fields */ - INIT_LIST_HEAD(&bus->link); -} - struct mii_dev *mdio_alloc(void) { struct mii_dev *bus; @@ -81,7 +63,10 @@ struct mii_dev *mdio_alloc(void) if (!bus) return bus; - mdio_init(bus); + memset(bus, 0, sizeof(*bus)); + + /* initialize mii_dev struct fields */ + INIT_LIST_HEAD(&bus->link); return bus; } diff --git a/common/stdio.c b/common/stdio.c index a61220ce4b9..3eeb289dd8b 100644 --- a/common/stdio.c +++ b/common/stdio.c @@ -357,9 +357,6 @@ int stdio_add_devices(void) drv_system_init(); serial_stdio_init(); -#ifdef CONFIG_USB_TTY - drv_usbtty_init(); -#endif #ifdef CONFIG_USB_FUNCTION_ACM drv_usbacm_init (); #endif diff --git a/configs/amd_versal2_virt_defconfig b/configs/amd_versal2_virt_defconfig index 8bee002777a..9911caa0e46 100644 --- a/configs/amd_versal2_virt_defconfig +++ b/configs/amd_versal2_virt_defconfig @@ -70,7 +70,6 @@ CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_LWIP=y CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_TFTP_BLOCKSIZE=4096 CONFIG_SIMPLE_PM_BUS=y CONFIG_CLK_CCF=y CONFIG_CLK_SCMI=y diff --git a/configs/endeavoru_defconfig b/configs/endeavoru_defconfig index 2152153714e..5e422f673f4 100644 --- a/configs/endeavoru_defconfig +++ b/configs/endeavoru_defconfig @@ -21,7 +21,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/grouper_defconfig b/configs/grouper_defconfig index 85f53e84a0d..b98f23a4baf 100644 --- a/configs/grouper_defconfig +++ b/configs/grouper_defconfig @@ -21,7 +21,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/imx8mm_evk_defconfig b/configs/imx8mm_evk_defconfig index 338fde1abbf..e8cd6a524fa 100644 --- a/configs/imx8mm_evk_defconfig +++ b/configs/imx8mm_evk_defconfig @@ -25,7 +25,8 @@ CONFIG_FIT=y CONFIG_FIT_EXTERNAL_OFFSET=0x3000 CONFIG_SPL_LOAD_FIT=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_DEFAULT_FDT_FILE="imx8mp-evk.dtb" +CONFIG_BOOTCOMMAND="bootflow scan -lb; run bsp_bootcmd" +CONFIG_DEFAULT_FDT_FILE="imx8mm-evk.dtb" CONFIG_SYS_CBSIZE=2048 CONFIG_SYS_PBSIZE=2074 CONFIG_BOARD_LATE_INIT=y diff --git a/configs/imx8mm_evk_fspi_defconfig b/configs/imx8mm_evk_fspi_defconfig index 4e2f2842985..902585b3b6d 100644 --- a/configs/imx8mm_evk_fspi_defconfig +++ b/configs/imx8mm_evk_fspi_defconfig @@ -5,7 +5,6 @@ CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y -CONFIG_ENV_SOURCE_FILE="imx8mn_evk" CONFIG_SF_DEFAULT_SPEED=40000000 CONFIG_SF_DEFAULT_MODE=0 CONFIG_ENV_SIZE=0x1000 @@ -29,7 +28,8 @@ CONFIG_FIT=y CONFIG_FIT_EXTERNAL_OFFSET=0x3000 CONFIG_SPL_LOAD_FIT=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_DEFAULT_FDT_FILE="imx8mp-evk.dtb" +CONFIG_BOOTCOMMAND="bootflow scan -lb; run bsp_bootcmd" +CONFIG_DEFAULT_FDT_FILE="imx8mm-evk.dtb" CONFIG_SYS_CBSIZE=2048 CONFIG_SYS_PBSIZE=2074 CONFIG_BOARD_LATE_INIT=y diff --git a/configs/imx8mq_evk_defconfig b/configs/imx8mq_evk_defconfig index 13c681dfad6..a2a6991bee2 100644 --- a/configs/imx8mq_evk_defconfig +++ b/configs/imx8mq_evk_defconfig @@ -32,7 +32,7 @@ CONFIG_FIT_EXTERNAL_OFFSET=0x3000 CONFIG_SPL_LOAD_FIT=y CONFIG_OF_SYSTEM_SETUP=y CONFIG_BOOTCOMMAND="bootflow scan -lb; run bsp_bootcmd" -CONFIG_DEFAULT_FDT_FILE="imx8mp-evk.dtb" +CONFIG_DEFAULT_FDT_FILE="imx8mq-evk.dtb" CONFIG_SYS_PBSIZE=1050 CONFIG_BOARD_EARLY_INIT_F=y CONFIG_BOARD_LATE_INIT=y diff --git a/configs/j722s_evm_r5_defconfig b/configs/j722s_evm_r5_defconfig index d51b21d6d0a..d96392db479 100644 --- a/configs/j722s_evm_r5_defconfig +++ b/configs/j722s_evm_r5_defconfig @@ -124,4 +124,7 @@ CONFIG_TIMER=y CONFIG_SPL_TIMER=y CONFIG_OMAP_TIMER=y CONFIG_LIB_RATIONAL=y +CONFIG_ESM_K3=y +CONFIG_SPL_DRIVERS_MISC=y +CONFIG_SPL_MISC=y CONFIG_SPL_LIB_RATIONAL=y diff --git a/configs/j784s4_evm_a72_defconfig b/configs/j784s4_evm_a72_defconfig index 1ac2430d7d1..1ba2bfed2cf 100644 --- a/configs/j784s4_evm_a72_defconfig +++ b/configs/j784s4_evm_a72_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_ARCH_K3=y CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_SYS_MALLOC_F_LEN=0x8000 +CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y @@ -14,13 +15,13 @@ CONFIG_ENV_SIZE=0x20000 CONFIG_DM_GPIO=y CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="ti/k3-j784s4-evm" -CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_DM_RESET=y CONFIG_SPL_MMC=y CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_STACK_R_ADDR=0x82000000 +CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x80a00000 CONFIG_SPL_BSS_MAX_SIZE=0x80000 @@ -29,6 +30,7 @@ CONFIG_SPL_FS_FAT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI=y +CONFIG_EFI_SET_TIME=y CONFIG_SPL_LOAD_FIT=y CONFIG_SPL_LOAD_FIT_ADDRESS=0x81000000 CONFIG_BOOTSTD_FULL=y @@ -38,10 +40,8 @@ CONFIG_SPL_MAX_SIZE=0xc0000 CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_SYS_MMCSD_RAW_MODE=y -CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400 CONFIG_SPL_DMA=y -CONFIG_SPL_DM_DEVICE_REMOVE=y CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FS_LOAD_PAYLOAD_NAME="u-boot.img" CONFIG_SPL_I2C=y @@ -49,7 +49,6 @@ CONFIG_SPL_DM_MAILBOX=y CONFIG_SPL_DM_SPI_FLASH=y CONFIG_SPL_DM_RESET=y CONFIG_SPL_POWER_DOMAIN=y -CONFIG_SPL_RAM_SUPPORT=y CONFIG_SPL_RAM_DEVICE=y # CONFIG_SPL_SPI_FLASH_TINY is not set CONFIG_SPL_SPI_FLASH_SFDP_SUPPORT=y @@ -58,10 +57,9 @@ CONFIG_SYS_SPI_U_BOOT_OFFS=0x280000 CONFIG_SPL_THERMAL=y CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_CMD_BOOTEFI_SELFTEST=y -CONFIG_CMD_ASKENV=y CONFIG_CMD_NVEDIT_EFI=y CONFIG_CMD_MTD=y -CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y CONFIG_CMD_EFIDEBUG=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y @@ -72,6 +70,7 @@ CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y +CONFIG_SPL_DM_DEVICE_REMOVE=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_REGMAP=y CONFIG_SPL_REGMAP=y @@ -81,6 +80,8 @@ CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_CLK_CCF=y CONFIG_CLK_TI_SCI=y +CONFIG_DFU_MMC=y +CONFIG_DFU_RAM=y CONFIG_DFU_SF=y CONFIG_SYS_DFU_DATA_BUF_SIZE=0x40000 CONFIG_SYS_DFU_MAX_FILE_SIZE=0x800000 @@ -154,7 +155,20 @@ CONFIG_SYSRESET=y CONFIG_SPL_SYSRESET=y CONFIG_SYSRESET_TI_SCI=y CONFIG_DM_THERMAL=y -CONFIG_EFI_SET_TIME=y -CONFIG_TI_COMMON_CMD_OPTIONS=y +CONFIG_USB=y +CONFIG_DM_USB_GADGET=y +CONFIG_SPL_DM_USB_GADGET=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_CDNS3=y +CONFIG_USB_CDNS3_GADGET=y +CONFIG_USB_CDNS3_HOST=y +CONFIG_SPL_USB_CDNS3_GADGET=y +CONFIG_USB_GADGET=y +CONFIG_SPL_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" +CONFIG_USB_GADGET_VENDOR_NUM=0x0451 +CONFIG_USB_GADGET_PRODUCT_NUM=0x6168 +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_SPL_DFU=y #include <configs/k3_efi_capsule.config> diff --git a/configs/j784s4_evm_r5_defconfig b/configs/j784s4_evm_r5_defconfig index a307055c5d0..5a5b0458b9b 100644 --- a/configs/j784s4_evm_r5_defconfig +++ b/configs/j784s4_evm_r5_defconfig @@ -62,6 +62,7 @@ CONFIG_SYS_SPI_U_BOOT_OFFS=0x80000 CONFIG_SPL_THERMAL=y CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_HUSH_PARSER=y +CONFIG_CMD_DFU=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_TIME=y @@ -84,6 +85,7 @@ CONFIG_SPL_CLK=y CONFIG_SPL_CLK_CCF=y CONFIG_SPL_CLK_K3_PLL=y CONFIG_SPL_CLK_K3=y +CONFIG_SYS_DFU_DATA_BUF_SIZE=0x40000 CONFIG_DMA_CHANNELS=y CONFIG_TI_K3_NAVSS_UDMA=y CONFIG_TI_SCI_PROTOCOL=y @@ -142,6 +144,19 @@ CONFIG_DM_THERMAL=y CONFIG_TIMER=y CONFIG_SPL_TIMER=y CONFIG_OMAP_TIMER=y +CONFIG_USB=y +CONFIG_DM_USB_GADGET=y +CONFIG_SPL_DM_USB_GADGET=y +CONFIG_USB_CDNS3=y +CONFIG_USB_CDNS3_GADGET=y +CONFIG_SPL_USB_CDNS3_GADGET=y +CONFIG_USB_GADGET=y +CONFIG_SPL_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" +CONFIG_USB_GADGET_VENDOR_NUM=0x0451 +CONFIG_USB_GADGET_PRODUCT_NUM=0x6168 +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_SPL_DFU=y CONFIG_FS_EXT4=y CONFIG_FS_FAT_MAX_CLUSTSIZE=16384 CONFIG_PANIC_HANG=y diff --git a/configs/mocha_defconfig b/configs/mocha_defconfig new file mode 100644 index 00000000000..0cbedb21797 --- /dev/null +++ b/configs/mocha_defconfig @@ -0,0 +1,91 @@ +CONFIG_ARM=y +CONFIG_ARCH_TEGRA=y +CONFIG_SUPPORT_PASSING_ATAGS=y +CONFIG_CMDLINE_TAG=y +CONFIG_INITRD_TAG=y +CONFIG_TEXT_BASE=0x80110000 +CONFIG_SYS_MALLOC_LEN=0x2500000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_ENV_SOURCE_FILE="mocha" +CONFIG_ENV_SIZE=0x3000 +CONFIG_ENV_OFFSET=0xFFFFD000 +CONFIG_DEFAULT_DEVICE_TREE="tegra124-xiaomi-mocha" +CONFIG_SPL_STACK=0x800ffffc +CONFIG_SPL_TEXT_BASE=0x80108000 +CONFIG_SYS_LOAD_ADDR=0x82000000 +CONFIG_TEGRA124=y +CONFIG_TARGET_MOCHA=y +CONFIG_TEGRA_ENABLE_UARTD=y +CONFIG_CMD_EBTUPDATE=y +CONFIG_TEGRA_GPU=y +CONFIG_BUTTON_CMD=y +CONFIG_BOOTDELAY=0 +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_KEYED_CTRLC=y +CONFIG_OF_SYSTEM_SETUP=y +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" +CONFIG_SYS_PBSIZE=2086 +CONFIG_SPL_FOOTPRINT_LIMIT=y +CONFIG_SPL_MAX_FOOTPRINT=0x8000 +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x80090000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x10000 +CONFIG_SYS_PROMPT="Tegra124 (Mocha) # " +# CONFIG_CMD_BOOTEFI_BOOTMGR is not set +CONFIG_CMD_BOOTMENU=y +# CONFIG_CMD_IMI is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_GPT_RENAME=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_POWEROFF=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_CMD_UMS_ABORT_KEYED=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_PAUSE=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_EXT4_WRITE=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_ENV_OVERWRITE=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SYS_MMC_ENV_PART=2 +CONFIG_BUTTON=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0x91000000 +CONFIG_FASTBOOT_BUF_SIZE=0x10000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_FASTBOOT_CMD_OEM_FORMAT=y +CONFIG_PALMAS_GPIO=y +CONFIG_SYS_I2C_TEGRA=y +CONFIG_BUTTON_KEYBOARD=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_PALMAS=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_PALMAS=y +CONFIG_PWM_TEGRA=y +CONFIG_SYS_NS16550=y +CONFIG_SYSRESET_PALMAS=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_TEGRA=y +CONFIG_USB_KEYBOARD=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Xiaomi" +CONFIG_USB_GADGET_VENDOR_NUM=0x18d1 +CONFIG_USB_GADGET_PRODUCT_NUM=0xd00d +CONFIG_CI_UDC=y +CONFIG_VIDEO=y +CONFIG_VIDEO_BRIDGE=y +# CONFIG_VIDEO_FONT_8X16 is not set +CONFIG_VIDEO_FONT_16X32=y +# CONFIG_VIDEO_LOGO is not set +CONFIG_VIDEO_LCD_SHARP_LQ079L1SX01=y +CONFIG_BACKLIGHT_LP855x=y +CONFIG_VIDEO_DSI_TEGRA30=y diff --git a/configs/nanopi-r3s-rk3566_defconfig b/configs/nanopi-r3s-rk3566_defconfig index 870613f690a..16e09753a72 100644 --- a/configs/nanopi-r3s-rk3566_defconfig +++ b/configs/nanopi-r3s-rk3566_defconfig @@ -54,7 +54,6 @@ CONFIG_PHY_REALTEK=y CONFIG_DWC_ETH_QOS=y CONFIG_DWC_ETH_QOS_ROCKCHIP=y CONFIG_RTL8169=y -CONFIG_NVME_PCI=y CONFIG_PCIE_DW_ROCKCHIP=y CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y diff --git a/configs/picasso_defconfig b/configs/picasso_defconfig index e37f61a9ef9..fe1eeb6ed10 100644 --- a/configs/picasso_defconfig +++ b/configs/picasso_defconfig @@ -21,7 +21,7 @@ CONFIG_BOOTDELAY=0 CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2085 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/qc750_defconfig b/configs/qc750_defconfig index 664832cbc33..a42860dc9ba 100644 --- a/configs/qc750_defconfig +++ b/configs/qc750_defconfig @@ -22,7 +22,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig index e4abfdf16bb..661a484f7bf 100644 --- a/configs/qcom_defconfig +++ b/configs/qcom_defconfig @@ -45,6 +45,7 @@ CONFIG_USE_DEFAULT_ENV_FILE=y CONFIG_DEFAULT_ENV_FILE="board/qualcomm/default.env" CONFIG_BUTTON_QCOM_PMIC=y CONFIG_CLK=y +CONFIG_CLK_STUB=y CONFIG_CLK_QCOM_APQ8016=y CONFIG_CLK_QCOM_APQ8096=y CONFIG_CLK_QCOM_QCM2290=y diff --git a/configs/qemu_arm64_lwip_defconfig b/configs/qemu_arm64_lwip_defconfig index 754c770c33f..814e98729a3 100644 --- a/configs/qemu_arm64_lwip_defconfig +++ b/configs/qemu_arm64_lwip_defconfig @@ -8,3 +8,4 @@ CONFIG_CMD_DNS=y CONFIG_CMD_WGET=y CONFIG_EFI_HTTP_BOOT=y CONFIG_WGET_HTTPS=y +CONFIG_WGET_CACERT=y diff --git a/configs/rcar3_salvator-x_defconfig b/configs/rcar3_salvator-x_defconfig index adfe4e9490f..35904f19152 100644 --- a/configs/rcar3_salvator-x_defconfig +++ b/configs/rcar3_salvator-x_defconfig @@ -29,6 +29,8 @@ CONFIG_CMD_DFU=y CONFIG_CMD_MMC=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_DM_USB_GADGET=y CONFIG_OF_LIST="renesas/r8a77951-salvator-x renesas/r8a77960-salvator-x renesas/r8a77965-salvator-x" CONFIG_MULTI_DTB_FIT_LZO=y CONFIG_MULTI_DTB_FIT_USER_DEFINED_AREA=y @@ -75,4 +77,10 @@ CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Renesas" +CONFIG_USB_GADGET_VENDOR_NUM=0x045b +CONFIG_USB_GADGET_PRODUCT_NUM=0x023c +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_USB_RENESAS_USBHS=y CONFIG_USB_STORAGE=y diff --git a/configs/rock-s0-rk3308_defconfig b/configs/rock-s0-rk3308_defconfig index 0a46e7bb187..063e0b921d7 100644 --- a/configs/rock-s0-rk3308_defconfig +++ b/configs/rock-s0-rk3308_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_SKIP_LOWLEVEL_INIT=y CONFIG_COUNTER_FREQUENCY=24000000 CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="rockchip/rk3308-rock-s0" CONFIG_DM_RESET=y CONFIG_ROCKCHIP_RK3308=y @@ -53,6 +54,7 @@ CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PINCTRL=y CONFIG_REGULATOR_PWM=y CONFIG_DM_REGULATOR_FIXED=y +CONFIG_SPL_DM_REGULATOR_FIXED=y CONFIG_PWM_ROCKCHIP=y CONFIG_RAM=y CONFIG_BAUDRATE=1500000 diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 7b35ad8a88f..0b3c765389c 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -328,6 +328,8 @@ CONFIG_USB_ETH_CDC=y CONFIG_VIDEO=y CONFIG_VIDEO_FONT_SUN12X22=y CONFIG_VIDEO_COPY=y +CONFIG_VIDEO_BRIDGE=y +CONFIG_VIDEO_BRIDGE_LVDS_CODEC=y CONFIG_CONSOLE_ROTATION=y CONFIG_CONSOLE_TRUETYPE=y CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y @@ -354,7 +356,6 @@ CONFIG_ADDR_MAP=y CONFIG_PANIC_HANG=y CONFIG_CMD_DHRYSTONE=y CONFIG_MBEDTLS_LIB=y -CONFIG_MBEDTLS_LIB_CRYPTO=y CONFIG_HKDF_MBEDTLS=y CONFIG_ECDSA=y CONFIG_ECDSA_VERIFY=y diff --git a/configs/sandbox_vpl_defconfig b/configs/sandbox_vpl_defconfig index f0315f6ab33..46329395ba5 100644 --- a/configs/sandbox_vpl_defconfig +++ b/configs/sandbox_vpl_defconfig @@ -252,8 +252,6 @@ CONFIG_FS_CBFS=y CONFIG_FS_CRAMFS=y # CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_CMD_DHRYSTONE=y -CONFIG_VPL_SHA1_LEGACY=y -CONFIG_VPL_SHA256_LEGACY=y CONFIG_RSA_VERIFY_WITH_PKEY=y CONFIG_TPM=y CONFIG_ZSTD=y diff --git a/configs/snow_defconfig b/configs/snow_defconfig index 7a1dc80b1cc..27698f5ef36 100644 --- a/configs/snow_defconfig +++ b/configs/snow_defconfig @@ -34,6 +34,8 @@ CONFIG_SYS_PBSIZE=1024 CONFIG_SILENT_CONSOLE=y CONFIG_BLOBLIST=y # CONFIG_SPL_BLOBLIST is not set +CONFIG_BLOBLIST_FIXED=y +CONFIG_BLOBLIST_ADDR=0x43d00000 # CONFIG_SPL_FRAMEWORK is not set CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x3800 diff --git a/configs/stm32746g-eval_defconfig b/configs/stm32746g-eval_defconfig index 4346ecd6e42..bd3a48b20a2 100644 --- a/configs/stm32746g-eval_defconfig +++ b/configs/stm32746g-eval_defconfig @@ -21,7 +21,6 @@ CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel" CONFIG_SYS_PBSIZE=1050 # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_BOARD_LATE_INIT=y CONFIG_SYS_PROMPT="U-Boot > " CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y diff --git a/configs/stm32746g-eval_spl_defconfig b/configs/stm32746g-eval_spl_defconfig index 2756ad5508f..d47d059d23b 100644 --- a/configs/stm32746g-eval_spl_defconfig +++ b/configs/stm32746g-eval_spl_defconfig @@ -30,7 +30,6 @@ CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel" CONFIG_SYS_PBSIZE=1050 # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_BOARD_LATE_INIT=y CONFIG_SPL_PAD_TO=0x9000 CONFIG_SPL_NO_BSS_LIMIT=y CONFIG_SPL_BOARD_INIT=y diff --git a/configs/stm32f746-disco_defconfig b/configs/stm32f746-disco_defconfig index 35a489c34e0..f6fbf83f68f 100644 --- a/configs/stm32f746-disco_defconfig +++ b/configs/stm32f746-disco_defconfig @@ -21,7 +21,6 @@ CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel" CONFIG_SYS_PBSIZE=1050 # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_BOARD_LATE_INIT=y CONFIG_SYS_PROMPT="U-Boot > " CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y diff --git a/configs/stm32f746-disco_spl_defconfig b/configs/stm32f746-disco_spl_defconfig index 6826b1cb755..dcf077dbfee 100644 --- a/configs/stm32f746-disco_spl_defconfig +++ b/configs/stm32f746-disco_spl_defconfig @@ -30,7 +30,6 @@ CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel" CONFIG_SYS_PBSIZE=1050 # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_BOARD_LATE_INIT=y CONFIG_SPL_PAD_TO=0x9000 CONFIG_SPL_NO_BSS_LIMIT=y CONFIG_SPL_BOARD_INIT=y diff --git a/configs/stm32f769-disco_defconfig b/configs/stm32f769-disco_defconfig index 5be221afd2f..9edda0e36b2 100644 --- a/configs/stm32f769-disco_defconfig +++ b/configs/stm32f769-disco_defconfig @@ -18,7 +18,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n" CONFIG_AUTOBOOT_STOP_STR=" " CONFIG_USE_BOOTARGS=y -CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel" +CONFIG_BOOTARGS="console=ttySTM0,115200n8 earlyprintk consoleblank=0 ignore_loglevel" CONFIG_SYS_PBSIZE=1050 # CONFIG_DISPLAY_CPUINFO is not set CONFIG_CYCLIC_MAX_CPU_TIME_US=8000 diff --git a/configs/stm32mp13_defconfig b/configs/stm32mp13_defconfig index 0acd1487c9a..4c6a7f82fe5 100644 --- a/configs/stm32mp13_defconfig +++ b/configs/stm32mp13_defconfig @@ -10,6 +10,7 @@ CONFIG_SYS_LOAD_ADDR=0xc2000000 CONFIG_STM32MP13X=y CONFIG_DDR_CACHEABLE_SIZE=0x8000000 CONFIG_CMD_STM32KEY=y +CONFIG_MFD_STM32_TIMERS=y CONFIG_TARGET_ST_STM32MP13X=y CONFIG_ENV_OFFSET_REDUND=0x940000 CONFIG_CMD_STM32PROG=y @@ -31,6 +32,7 @@ CONFIG_CMD_UNZIP=y CONFIG_CMD_CLK=y CONFIG_CMD_FUSE=y CONFIG_CMD_GPIO=y +CONFIG_CMD_PWM=y CONFIG_CMD_I2C=y CONFIG_CMD_LSBLK=y CONFIG_CMD_MMC=y @@ -80,6 +82,8 @@ CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_GPIO=y CONFIG_DM_REGULATOR_SCMI=y +CONFIG_DM_PWM=y +CONFIG_PWM_STM32=y CONFIG_RESET_SCMI=y CONFIG_DM_RNG=y CONFIG_RNG_STM32=y diff --git a/configs/stm32mp13_dhcor_defconfig b/configs/stm32mp13_dhcor_defconfig index 4dc3954128d..2da9287ea7b 100644 --- a/configs/stm32mp13_dhcor_defconfig +++ b/configs/stm32mp13_dhcor_defconfig @@ -28,10 +28,14 @@ CONFIG_CMD_RNG=y CONFIG_CMD_LOG=y CONFIG_CMD_UBI=y CONFIG_ENV_IS_NOWHERE=y +CONFIG_ENV_IS_IN_MMC=y +CONFIG_ENV_MMC_USE_DT=y CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_CLK_SCMI=y CONFIG_SET_DFU_ALT_INFO=y CONFIG_SYS_I2C_EEPROM_ADDR=0x50 +CONFIG_SYS_MMC_ENV_DEV=0 +CONFIG_SYS_MMC_ENV_PART=1 CONFIG_PHY_REALTEK=y CONFIG_DM_REGULATOR_SCMI=y CONFIG_RESET_SCMI=y @@ -44,4 +48,3 @@ CONFIG_OPTEE=y CONFIG_USB_ONBOARD_HUB=y CONFIG_USB_HUB_DEBOUNCE_TIMEOUT=2000 CONFIG_ERRNO_STR=y -CONFIG_BOOTCOUNT_ALTBOOTCMD=" diff --git a/configs/stm32mp15_dhcom_basic.config b/configs/stm32mp15_dhcom_basic.config new file mode 100644 index 00000000000..d78916bb5b2 --- /dev/null +++ b/configs/stm32mp15_dhcom_basic.config @@ -0,0 +1,8 @@ +#include <configs/stm32mp15_dhsom.config> + +CONFIG_ARM=y +CONFIG_ARCH_STM32MP=y +CONFIG_SYS_MEMTEST_START=0xc0000000 +CONFIG_SYS_MEMTEST_END=0xc4000000 +CONFIG_SYS_I2C_EEPROM_BUS=3 +CONFIG_SYS_I2C_EEPROM_ADDR=0x50 diff --git a/configs/stm32mp15_dhcom_basic_defconfig b/configs/stm32mp15_dhcom_basic_defconfig index f89c921925d..297092bd746 100644 --- a/configs/stm32mp15_dhcom_basic_defconfig +++ b/configs/stm32mp15_dhcom_basic_defconfig @@ -1,11 +1,4 @@ -#include <configs/stm32mp15_dhsom.config> +#include <configs/stm32mp15_dhcom_basic.config> -CONFIG_ARM=y -CONFIG_ARCH_STM32MP=y CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp157c-dhcom-pdk2" -CONFIG_SYS_MEMTEST_START=0xc0000000 -CONFIG_SYS_MEMTEST_END=0xc4000000 -CONFIG_SYS_I2C_EEPROM_BUS=3 CONFIG_OF_LIST="st/stm32mp157c-dhcom-pdk2 st/stm32mp153c-dhcom-drc02 st/stm32mp157c-dhcom-picoitx" -CONFIG_SYS_I2C_EEPROM_ADDR=0x50 -CONFIG_BOOTCOUNT_ALTBOOTCMD=" diff --git a/configs/stm32mp15_dhcom_drc02_basic_defconfig b/configs/stm32mp15_dhcom_drc02_basic_defconfig new file mode 100644 index 00000000000..838c3db253d --- /dev/null +++ b/configs/stm32mp15_dhcom_drc02_basic_defconfig @@ -0,0 +1,4 @@ +#include <configs/stm32mp15_dhcom_basic.config> + +CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp153c-dhcom-drc02" +CONFIG_OF_LIST="st/stm32mp153c-dhcom-drc02" diff --git a/configs/stm32mp15_dhcom_pdk2_basic_defconfig b/configs/stm32mp15_dhcom_pdk2_basic_defconfig new file mode 100644 index 00000000000..c6996233c9f --- /dev/null +++ b/configs/stm32mp15_dhcom_pdk2_basic_defconfig @@ -0,0 +1,4 @@ +#include <configs/stm32mp15_dhcom_basic.config> + +CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp157c-dhcom-pdk2" +CONFIG_OF_LIST="st/stm32mp157c-dhcom-pdk2" diff --git a/configs/stm32mp15_dhcom_picoitx_basic_defconfig b/configs/stm32mp15_dhcom_picoitx_basic_defconfig new file mode 100644 index 00000000000..5682edbfcbf --- /dev/null +++ b/configs/stm32mp15_dhcom_picoitx_basic_defconfig @@ -0,0 +1,4 @@ +#include <configs/stm32mp15_dhcom_basic.config> + +CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp157c-dhcom-picoitx" +CONFIG_OF_LIST="st/stm32mp157c-dhcom-picoitx" diff --git a/configs/stm32mp15_dhcor_avenger96_basic_defconfig b/configs/stm32mp15_dhcor_avenger96_basic_defconfig new file mode 100644 index 00000000000..5d27cd5ed7e --- /dev/null +++ b/configs/stm32mp15_dhcor_avenger96_basic_defconfig @@ -0,0 +1,4 @@ +#include <configs/stm32mp15_dhcor_basic.config> + +CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp157a-dhcor-avenger96" +CONFIG_OF_LIST="st/stm32mp157a-dhcor-avenger96" diff --git a/configs/stm32mp15_dhcor_basic.config b/configs/stm32mp15_dhcor_basic.config new file mode 100644 index 00000000000..e9c0cb9f95a --- /dev/null +++ b/configs/stm32mp15_dhcor_basic.config @@ -0,0 +1,8 @@ +#include <configs/stm32mp15_dhsom.config> + +CONFIG_ARM=y +CONFIG_ARCH_STM32MP=y +CONFIG_SYS_I2C_EEPROM_BUS=2 +CONFIG_SYS_I2C_EEPROM_ADDR=0x53 +CONFIG_PHY_MICREL=y +CONFIG_PHY_MICREL_KSZ90X1=y diff --git a/configs/stm32mp15_dhcor_basic_defconfig b/configs/stm32mp15_dhcor_basic_defconfig index bde668761b3..beb6d1d5a9a 100644 --- a/configs/stm32mp15_dhcor_basic_defconfig +++ b/configs/stm32mp15_dhcor_basic_defconfig @@ -1,11 +1,4 @@ -#include <configs/stm32mp15_dhsom.config> +#include <configs/stm32mp15_dhcor_basic.config> -CONFIG_ARM=y -CONFIG_ARCH_STM32MP=y CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp157a-dhcor-avenger96" -CONFIG_SYS_I2C_EEPROM_BUS=2 CONFIG_OF_LIST="st/stm32mp157a-dhcor-avenger96 st/stm32mp151a-dhcor-testbench st/stm32mp153c-dhcor-drc-compact" -CONFIG_SYS_I2C_EEPROM_ADDR=0x53 -CONFIG_PHY_MICREL=y -CONFIG_PHY_MICREL_KSZ90X1=y -CONFIG_BOOTCOUNT_ALTBOOTCMD=" diff --git a/configs/stm32mp15_dhcor_drc_compact_basic_defconfig b/configs/stm32mp15_dhcor_drc_compact_basic_defconfig new file mode 100644 index 00000000000..7b1d73a33b5 --- /dev/null +++ b/configs/stm32mp15_dhcor_drc_compact_basic_defconfig @@ -0,0 +1,4 @@ +#include <configs/stm32mp15_dhcor_basic.config> + +CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp153c-dhcor-drc-compact" +CONFIG_OF_LIST="st/stm32mp153c-dhcor-drc-compact" diff --git a/configs/stm32mp15_dhcor_testbench_basic_defconfig b/configs/stm32mp15_dhcor_testbench_basic_defconfig new file mode 100644 index 00000000000..7ba327cbd82 --- /dev/null +++ b/configs/stm32mp15_dhcor_testbench_basic_defconfig @@ -0,0 +1,4 @@ +#include <configs/stm32mp15_dhcor_basic.config> + +CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp151a-dhcor-testbench" +CONFIG_OF_LIST="st/stm32mp151a-dhcor-testbench" diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig index cecd26175d1..e64bb768440 100644 --- a/configs/tools-only_defconfig +++ b/configs/tools-only_defconfig @@ -9,10 +9,11 @@ CONFIG_EFI_LOADER=n CONFIG_ANDROID_BOOT_IMAGE=y CONFIG_TIMESTAMP=y CONFIG_FIT=y -CONFIG_FIT_SIGNATURE=y CONFIG_BOOTSTD_FULL=n CONFIG_BOOTMETH_CROS=n CONFIG_BOOTMETH_VBE=n +CONFIG_IMAGE_PRE_LOAD=y +CONFIG_IMAGE_PRE_LOAD_SIG=y CONFIG_USE_BOOTCOMMAND=y CONFIG_BOOTCOMMAND="run distro_bootcmd" CONFIG_CMD_BOOTD=n diff --git a/configs/transformer_t20_defconfig b/configs/transformer_t20_defconfig index 010d375b429..50b5885bb09 100644 --- a/configs/transformer_t20_defconfig +++ b/configs/transformer_t20_defconfig @@ -21,7 +21,7 @@ CONFIG_BOOTDELAY=0 CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2085 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/transformer_t30_defconfig b/configs/transformer_t30_defconfig index 20aa131d0b9..91074e998df 100644 --- a/configs/transformer_t30_defconfig +++ b/configs/transformer_t30_defconfig @@ -21,7 +21,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/x3_t30_defconfig b/configs/x3_t30_defconfig index 9fc5a84e860..12be929600e 100644 --- a/configs/x3_t30_defconfig +++ b/configs/x3_t30_defconfig @@ -21,7 +21,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/xilinx_versal_net_virt_defconfig b/configs/xilinx_versal_net_virt_defconfig index 5ef5fd44fd3..1604b5915db 100644 --- a/configs/xilinx_versal_net_virt_defconfig +++ b/configs/xilinx_versal_net_virt_defconfig @@ -70,7 +70,6 @@ CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_LWIP=y CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_TFTP_BLOCKSIZE=4096 CONFIG_SIMPLE_PM_BUS=y CONFIG_CLK_VERSAL=y CONFIG_DFU_RAM=y diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index f228eef7c95..baa4b8e412e 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -74,7 +74,6 @@ CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_LWIP=y CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_TFTP_BLOCKSIZE=4096 CONFIG_SIMPLE_PM_BUS=y CONFIG_CLK_VERSAL=y CONFIG_DFU_TIMEOUT=y diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst index a8b0d7f0395..7e641306da2 100644 --- a/doc/arch/sandbox/sandbox.rst +++ b/doc/arch/sandbox/sandbox.rst @@ -658,10 +658,10 @@ that are mapped into that memory: ======== ======================== =============================== Addr Config Usage ======== ======================== =============================== - 100 CONFIG_SYS_FDT_LOAD_ADDR Device tree - b000 CONFIG_BLOBLIST_ADDR Blob list - 10000 CFG_MALLOC_F_ADDR Early memory allocation + 100 CONFIG_BLOBLIST_ADDR Blob list + 1000 CONFIG_SYS_FDT_LOAD_ADDR Device tree f0000 CONFIG_PRE_CON_BUF_ADDR Pre-console buffer + f4000 CFG_MALLOC_F_ADDR Early memory allocation 100000 TCG Event log TCG Event Log 200000 CONFIG_TRACE_EARLY_ADDR Early trace buffer (if enabled). Also used 400000 CONFIG_TEXT_BASE Load buffer for U-Boot (sandbox_spl only) diff --git a/doc/board/index.rst b/doc/board/index.rst index b055046e649..84c135e02c1 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -69,4 +69,5 @@ Board-specific doc variscite/index wexler/index xen/index + xiaomi/index xilinx/index diff --git a/doc/board/xiaomi/index.rst b/doc/board/xiaomi/index.rst new file mode 100644 index 00000000000..109ab4a251f --- /dev/null +++ b/doc/board/xiaomi/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Xiaomi +====== + +.. toctree:: + :maxdepth: 2 + + mocha diff --git a/doc/board/xiaomi/mocha.rst b/doc/board/xiaomi/mocha.rst new file mode 100644 index 00000000000..be3e333127b --- /dev/null +++ b/doc/board/xiaomi/mocha.rst @@ -0,0 +1,112 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot for the Xiaomi Mi Pad tablet +=================================== + +``DISCLAMER!`` Moving your Xiaomi Mi Pad to use U-Boot assumes replacement +of the vendor bootloader. Vendor Android firmwares will no longer be able +to run on the device. This replacement IS reversible. + +Quick Start +----------- + +- Build U-Boot +- Boot U-Boot +- Process and flash U-Boot +- Boot Linux +- Self Upgrading +- Chainload configuration + +Build U-Boot +------------ + +.. code-block:: bash + + $ export CROSS_COMPILE=arm-none-eabi- + $ make mocha_defconfig + $ make + +After the build succeeds, you will obtain the final ``u-boot-dtb-tegra.bin`` +image, ready for booting or further processing. + +Boot U-Boot +----------- +Existing tegrarcm loader can be used to pre-load U-Boot you have build +into RAM and basically perform a tethered cold-boot. + +.. code-block:: bash + + $ tegrarcm --bct mocha.bct --bootloader u-boot-dtb-tegra.bin --loadaddr 0x80108000 + +U-Boot will try to load Linux kernel and if fails, it will turn the +tablet off. While pre-loading U-Boot, hold the ``volume down`` button +which will trigger the bootmenu. + +Process and flash U-Boot +------------------------ + +``DISCLAMER!`` All questions related to the re-crypt work should be asked +in re-crypt repo issues. NOT HERE! + +re-crypt is a tool that processes the ``u-boot-dtb-tegra.bin`` binary into +form usable by device. This process is required only on the first +installation or to recover the device in case of a failed update. + +.. code-block:: bash + + $ git clone https://gitlab.com/grate-driver/re-crypt.git + $ cd re-crypt # place your u-boot-dtb-tegra.bin here + $ ./re-crypt.py --dev mocha + +The script will produce ``bct.img`` and ``ebt.img`` ready to flash. + +Permanent installation can be performed by pre-loading just built U-Boot +into RAM via tegrarcm. While pre-loading U-Boot, hold the ``volume down`` +button which will trigger the bootmenu. There, select ``fastboot`` using +the volume and power buttons. + +After, on host PC, do: + +.. code-block:: bash + + $ fastboot flash 0.1 bct.img + $ fastboot flash 0.2 ebt.img + $ fastboot reboot + +Device will reboot. + +Boot Linux +---------- + +To boot Linux, U-Boot will look for an ``extlinux.conf`` on MicroSD and then on +eMMC. Additionally, if the ``volume down`` button is pressed while booting, the +device will enter bootmenu. Bootmenu contains entries to mount MicroSD and eMMC +as mass storage, fastboot, reboot, reboot RCM, poweroff, enter U-Boot console +and update bootloader (check the next chapter). + +Flashing ``bct.img`` and ``ebt.img`` eliminates vendor restrictions on eMMC and +allows the user to use/partition it in any way the user desires. + +Self Upgrading +-------------- + +Place your ``u-boot-dtb-tegra.bin`` on the first partition of the MicroSD card +and insert it into the tablet. Enter bootmenu, choose update the bootloader +option with the Power button and U-Boot should update itself. Once the process +is completed, U-Boot will ask to press any button to reboot. + +Chainload configuration +----------------------- + +To build U-Boot without SPL suitable for chainloading adjust mocha_defconfig: + +.. code-block:: + + CONFIG_TEXT_BASE=0x80A00000 + CONFIG_SKIP_LOWLEVEL_INIT=y + # CONFIG_OF_BOARD_SETUP is not set + CONFIG_TEGRA_SUPPORT_NON_SECURE=y + +After the build succeeds, you will obtain the final ``u-boot-dtb.bin`` +file, ready for booting using vendor bootloader's fastboot or which can be +further processed into a flashable image. diff --git a/doc/develop/release_cycle.rst b/doc/develop/release_cycle.rst index b6ad7218614..dc5bb340ff2 100644 --- a/doc/develop/release_cycle.rst +++ b/doc/develop/release_cycle.rst @@ -74,7 +74,7 @@ For the next scheduled release, release candidates were made on:: * U-Boot v2025.04-rc3 was released on Mon 24 February 2025. -.. * U-Boot v2025.04-rc4 was released on Mon 10 March 2025. +* U-Boot v2025.04-rc4 was released on Mon 10 March 2025. .. * U-Boot v2025.04-rc5 was released on Mon 24 March 2025. diff --git a/doc/device-tree-bindings/pinctrl/adi,adsp-pinctrl.yaml b/doc/device-tree-bindings/pinctrl/adi,adsp-pinctrl.yaml new file mode 100644 index 00000000000..418ebd5ce41 --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/adi,adsp-pinctrl.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/adi,adsp-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Pinctrl Driver for Analog Devices SC5xx Processors + +maintainers: + - Vasileios Bimpikas <vasileios.bimpikas@analog.com> + - Utsav Agarwal <utsav.agarwal@analog.com> + - Arturs Artamonovs <arturs.artamonovs@analog.com> + +description: | + This driver provides an interface for performing pin configuration + Analog Devices SoCs using the ADSP PORT hardware for pin + configuration according to the HRM. Currently this is only the + SC5xx series. + +properties: + compatible: + const: adi,adsp-pinctrl + + reg: + maxItems: 1 + + adi,npins: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Total number of pins available to this SoC's pin controller, + found in the HRM. + +patternProperties: + '_pins$': + type: object + + properties: + adi,pins: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + For n pins, 2n values must be provided as a sequence of pin + name as identified with the ADI_ADSP_PIN() macro and a pin + function constant, both defined in + include/dt-bindings/pinctrl/adi-adsp.h. + + required: + - adi,pins + + additionalProperties: false + +required: + - compatible + - reg + - adi,npins + +additionalProperties: false + +examples: + - | + #include <dt-bindings/pinctrl/adi-adsp.h> + + soc { + pinctrl0: pinctrl@0x31004000 { + compatible = "adi,adsp-pinctrl"; + reg = <0x31004000 0x500>; + adi,npins = <135>; + uart0_default: uart0_pins { + adi,pins = <ADI_ADSP_PIN('A', 6) ADI_ADSP_PINFUNC_ALT1>, + <ADI_ADSP_PIN('A', 7) ADI_ADSP_PINFUNC_ALT1>; + }; + }; + + }; diff --git a/doc/usage/cmd/mv.rst b/doc/usage/cmd/mv.rst new file mode 100644 index 00000000000..99864371038 --- /dev/null +++ b/doc/usage/cmd/mv.rst @@ -0,0 +1,61 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +.. index:: + single: mv (command) + +mv command +========== + +Synopsis +-------- + +:: + + mv <interface> [<dev[:part]>] <old_path> <new_path> + +Description +----------- + +The mv command renames/moves a file or directory within a filesystem. + +interface + interface for accessing the block device (mmc, sata, scsi, usb, ....) + +dev + device number + +part + partition number, defaults to 0 (whole device) + +old_path + existing path to file/directory + +new_path + new path/name for the rename/move + + +Example +------- + + # Rename file 'foo' in directory 'dir' to 'bar' + mv mmc 0:0 dir/foo dir/bar + + # Move file 'f' from directory 'foo' to existing directory 'bar' renaming + # 'f' to 'g' + mv mmc 0:0 foo/f bar/g + + # Move directory 'abc' in directory 'dir1' into existing directory 'dir2' + mv mmc 0:0 dir1/abc dir2 + +Configuration +------------- + +The mv command is only available if CONFIG_CMD_FS_GENERIC=y. + +Return value +------------ + +The return value $? is set to 0 (true) if the file was successfully +renamed/moved. + +If an error occurs, the return value $? is set to 1 (false). diff --git a/doc/usage/cmd/wget.rst b/doc/usage/cmd/wget.rst index 48bedf1e845..cc82e495a29 100644 --- a/doc/usage/cmd/wget.rst +++ b/doc/usage/cmd/wget.rst @@ -12,7 +12,9 @@ Synopsis :: wget [address] [host:]path - wget [address] url # lwIP only + wget [address] url # lwIP only + wget cacert none|optional|required # lwIP only + wget cacert <address> <size> # lwIP only Description @@ -54,6 +56,32 @@ address url HTTP or HTTPS URL, that is: http[s]://<host>[:<port>]/<path>. +The cacert (stands for 'Certification Authority certificates') subcommand is +used to provide root certificates for the purpose of HTTPS authentication. It +also allows to enable or disable authentication. + +wget cacert <address> <size> + +address + memory address of the root certificates in X509 DER format + +size + the size of the root certificates + +wget cacert none|optional|required + +none + certificate verification is disabled. HTTPS is used without any server + authentication (unsafe) +optional + certificate verification is enabled provided root certificates have been + provided via wget cacert <addr> <size> or wget cacert builtin. Otherwise + HTTPS is used without any server authentication (unsafe). +required + certificate verification is mandatory. If no root certificates have been + configured, HTTPS transfers will fail. + + Examples -------- @@ -97,11 +125,61 @@ In the example the following steps are executed: 1694892032 bytes transferred in 492181 ms (3.3 MiB/s) Bytes transferred = 1694892032 (65060000 hex) +Here is an example showing how to configure built-in root certificates as +well as providing some at run time. In this example it is assumed that +CONFIG_WGET_BUILTIN_CACERT_PATH=DigiCertTLSRSA4096RootG5.crt downloaded from +https://cacerts.digicert.com/DigiCertTLSRSA4096RootG5.crt. + +:: + + # Make sure IP is configured + => dhcp + # When built-in certificates are configured, authentication is mandatory + # (i.e., "wget cacert required"). Use a test server... + => wget https://digicert-tls-rsa4096-root-g5.chain-demos.digicert.com/ + 1864 bytes transferred in 1 ms (1.8 MiB/s) + Bytes transferred = 1864 (748 hex) + # Another server not signed against Digicert will fail + => wget https://www.google.com/ + Certificate verification failed + + HTTP client error 4 + # Disable authentication to allow the command to proceed anyways + => wget cacert none + => wget https://www.google.com/ + WARNING: no CA certificates, HTTPS connections not authenticated + 16683 bytes transferred in 15 ms (1.1 MiB/s) + Bytes transferred = 16683 (412b hex) + # Force verification but unregister the CA certificates + => wget cacert required + => wget cacert 0 0 + # Unsurprisingly, download fails + => wget https://digicert-tls-rsa4096-root-g5.chain-demos.digicert.com/ + Error: cacert authentication mode is 'required' but no CA certificates given + # Get the same certificates as above from the network + => wget cacert none + => wget https://cacerts.digicert.com/DigiCertTLSRSA4096RootG5.crt + WARNING: no CA certificates, HTTPS connections not authenticated + 1386 bytes transferred in 1 ms (1.3 MiB/s) + Bytes transferred = 1386 (56a hex) + # Register them and force authentication + => wget cacert $fileaddr $filesize + => wget cacert required + # Authentication is operational again + => wget https://digicert-tls-rsa4096-root-g5.chain-demos.digicert.com/ + 1864 bytes transferred in 1 ms (1.8 MiB/s) + Bytes transferred = 1864 (748 hex) + # The builtin certificates can be restored at any time + => wget cacert builtin + Configuration ------------- The command is only available if CONFIG_CMD_WGET=y. -To enable lwIP support set CONFIG_NET_LWIP=y. +To enable lwIP support set CONFIG_NET_LWIP=y. In this case, root certificates +support can be enabled via CONFIG_WGET_BUILTIN_CACERT=y +CONFIG_WGET_BUILTIN_CACERT_PATH=<some path> (for built-in certificates) and/or +CONFIG_WGET_CACERT=y (for the wget cacert command). TCP Selective Acknowledgments in the legacy network stack can be enabled via CONFIG_PROT_TCP_SACK=y. This will improve the download speed. Selective diff --git a/doc/usage/environment.rst b/doc/usage/environment.rst index 30fc16794fc..7e2f2863d06 100644 --- a/doc/usage/environment.rst +++ b/doc/usage/environment.rst @@ -87,6 +87,18 @@ settings. For example:: #include <env/ti/mmc.env> +Quotes are not suppressed, for example:: + + fdtfile=CONFIG_DEFAULT_DEVICE_TREE.dtb + # produces: fdtfile="sun7i-a20-pcduino3.dtb" + +For this particular issue you can use ``DEFAULT_DEVICE_TREE`` instead:: + + fdtfile=DEFAULT_DEVICE_TREE.dtb + # produces: fdtfile=sun7i-a20-pcduino3.dtb + +There is no general way to remove quotes. + If CONFIG_ENV_SOURCE_FILE is empty and the default filename is not present, then the old-style C environment is used instead. See below. diff --git a/doc/usage/index.rst b/doc/usage/index.rst index bf2335dc8f0..fc058476f39 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -93,6 +93,7 @@ Shell commands cmd/msr cmd/mtest cmd/mtrr + cmd/mv cmd/optee cmd/panic cmd/part diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index d9d518d7038..18bd640a68b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -96,6 +96,13 @@ config SPL_CLK_GPIO Enable this option to add GPIO-controlled clock gate driver in U-Boot SPL. +config CLK_STUB + bool "Stub clock driver" + depends on CLK + help + Enable this to provide a stub clock driver for non-essential clock + controllers. + config CLK_BCM6345 bool "Clock controller driver for BCM6345" depends on CLK && ARCH_BMIPS diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 7f84f22d4b1..fe0e49f6112 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_$(PHASE_)CLK_CCF) += clk.o clk-divider.o clk-mux.o clk-gate.o obj-$(CONFIG_$(PHASE_)CLK_CCF) += clk-fixed-factor.o obj-$(CONFIG_$(PHASE_)CLK_COMPOSITE_CCF) += clk-composite.o obj-$(CONFIG_$(PHASE_)CLK_GPIO) += clk-gpio.o +obj-$(CONFIG_$(PHASE_)CLK_STUB) += clk-stub.o obj-y += adi/ obj-y += analogbits/ diff --git a/drivers/clk/clk-stub.c b/drivers/clk/clk-stub.c new file mode 100644 index 00000000000..5fbbb07b7f7 --- /dev/null +++ b/drivers/clk/clk-stub.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Stub clk driver for non-essential clocks. + * + * This driver should be used for clock controllers + * which are described as dependencies in DT but aren't + * actually necessary for hardware functionality. + */ + +#include <clk-uclass.h> +#include <dm.h> + +/* NOP parent nodes to stub clocks */ +static const struct udevice_id nop_parent_ids[] = { + { .compatible = "qcom,rpm-proc" }, + { .compatible = "qcom,glink-rpm" }, + { .compatible = "qcom,rpm-sm6115" }, + { } +}; + +U_BOOT_DRIVER(nop_parent) = { + .name = "nop_parent", + .id = UCLASS_NOP, + .of_match = nop_parent_ids, + .bind = dm_scan_fdt_dev, + .flags = DM_FLAG_DEFAULT_PD_CTRL_OFF, +}; + +static ulong stub_clk_set_rate(struct clk *clk, ulong rate) +{ + return (clk->rate = rate); +} + +static ulong stub_clk_get_rate(struct clk *clk) +{ + return clk->rate; +} + +static int stub_clk_nop(struct clk *clk) +{ + return 0; +} + +static struct clk_ops stub_clk_ops = { + .set_rate = stub_clk_set_rate, + .get_rate = stub_clk_get_rate, + .enable = stub_clk_nop, + .disable = stub_clk_nop, +}; + +static const struct udevice_id stub_clk_ids[] = { + { .compatible = "qcom,rpmcc" }, + { .compatible = "qcom,sm8150-rpmh-clk" }, + { .compatible = "qcom,sm8250-rpmh-clk" }, + { .compatible = "qcom,sm8550-rpmh-clk" }, + { .compatible = "qcom,sm8650-rpmh-clk" }, + { } +}; + +U_BOOT_DRIVER(clk_stub) = { + .name = "clk_stub", + .id = UCLASS_CLK, + .ops = &stub_clk_ops, + .of_match = stub_clk_ids, + .flags = DM_FLAG_DEFAULT_PD_CTRL_OFF, +}; + diff --git a/drivers/clk/clk_versal.c b/drivers/clk/clk_versal.c index 35ee56d0693..cb98f34b5ec 100644 --- a/drivers/clk/clk_versal.c +++ b/drivers/clk/clk_versal.c @@ -106,8 +106,8 @@ struct versal_clk_priv { struct versal_clock *clk; }; -static ulong pl_alt_ref_clk; -static ulong ref_clk; +static ulong pl_alt_ref_clk __section(".data"); +static ulong ref_clk __section(".data"); struct versal_pm_query_data { u32 qid; @@ -116,8 +116,8 @@ struct versal_pm_query_data { u32 arg3; }; -static struct versal_clock *clock; -static unsigned int clock_max_idx; +static struct versal_clock *clock __section(".data"); +static unsigned int clock_max_idx __section(".data"); #define PM_QUERY_DATA 35 @@ -679,12 +679,21 @@ static int versal_clk_probe(struct udevice *dev) debug("%s\n", __func__); - ret = versal_clock_get_freq_by_name("pl_alt_ref_clk", + ret = versal_clock_get_freq_by_name("pl_alt_ref", dev, &pl_alt_ref_clk); + if (ret == -ENODATA) { + /* Fallback to old DT binding clk name "pl_alt_ref_clk" */ + ret = versal_clock_get_freq_by_name("pl_alt_ref_clk", + dev, &pl_alt_ref_clk); + } if (ret < 0) return -EINVAL; - ret = versal_clock_get_freq_by_name("ref_clk", dev, &ref_clk); + ret = versal_clock_get_freq_by_name("ref", dev, &ref_clk); + if (ret == -ENODATA) { + /* Fallback to old DT binding clk name "ref_clk" */ + ret = versal_clock_get_freq_by_name("ref_clk", dev, &ref_clk); + } if (ret < 0) return -EINVAL; diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 3c5340df8ee..7fce1f70d13 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -70,17 +70,12 @@ static int rzg2l_cpg_clk_set(struct clk *clk, bool enable) dev_dbg(clk->dev, "%s %s clock %u\n", enable ? "enable" : "disable", is_mod_clk(clk->id) ? "module" : "core", cpg_clk_id); - if (!is_mod_clk(clk->id)) { - /* - * Non-module clocks are always on. Ignore attempts to enable - * them and reject attempts to disable them. - */ - if (enable) - return 0; - - dev_err(clk->dev, "ID %lu is not a module clock\n", clk->id); - return -EINVAL; - } + /* + * Non-module clocks are always on. Ignore attempts to enable or disable + * them. + */ + if (!is_mod_clk(clk->id)) + return 0; for (i = 0; i < data->info->num_mod_clks; i++) { if (data->info->mod_clks[i].id == cpg_clk_id) { diff --git a/drivers/clk/rockchip/clk_rk3568.c b/drivers/clk/rockchip/clk_rk3568.c index 977699d509d..533031caead 100644 --- a/drivers/clk/rockchip/clk_rk3568.c +++ b/drivers/clk/rockchip/clk_rk3568.c @@ -2680,7 +2680,7 @@ static ulong rk3568_clk_set_rate(struct clk *clk, ulong rate) return ret; }; -#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA)) +#if (CONFIG_IS_ENABLED(OF_CONTROL)) || (!CONFIG_IS_ENABLED(OF_PLATDATA)) static int rk3568_gmac0_src_set_parent(struct clk *clk, struct clk *parent) { struct rk3568_clk_priv *priv = dev_get_priv(clk->dev); @@ -2859,7 +2859,7 @@ static int rk3568_clk_set_parent(struct clk *clk, struct clk *parent) static struct clk_ops rk3568_clk_ops = { .get_rate = rk3568_clk_get_rate, .set_rate = rk3568_clk_set_rate, -#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA)) +#if (CONFIG_IS_ENABLED(OF_CONTROL)) || (!CONFIG_IS_ENABLED(OF_PLATDATA)) .set_parent = rk3568_clk_set_parent, #endif }; diff --git a/drivers/clk/rockchip/clk_rk3588.c b/drivers/clk/rockchip/clk_rk3588.c index 6042fc10cdb..8c3a113526f 100644 --- a/drivers/clk/rockchip/clk_rk3588.c +++ b/drivers/clk/rockchip/clk_rk3588.c @@ -1822,7 +1822,7 @@ static ulong rk3588_clk_set_rate(struct clk *clk, ulong rate) */ #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 -#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA)) +#if (CONFIG_IS_ENABLED(OF_CONTROL)) || (!CONFIG_IS_ENABLED(OF_PLATDATA)) static int __maybe_unused rk3588_dclk_vop_set_parent(struct clk *clk, struct clk *parent) { @@ -1915,7 +1915,7 @@ static int rk3588_clk_set_parent(struct clk *clk, struct clk *parent) static struct clk_ops rk3588_clk_ops = { .get_rate = rk3588_clk_get_rate, .set_rate = rk3588_clk_set_rate, -#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA)) +#if (CONFIG_IS_ENABLED(OF_CONTROL)) || (!CONFIG_IS_ENABLED(OF_PLATDATA)) .set_parent = rk3588_clk_set_parent, #endif }; diff --git a/drivers/core/Makefile b/drivers/core/Makefile index 9ea57911f89..657e589c286 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -16,6 +16,6 @@ ifndef CONFIG_DM_DEV_READ_INLINE obj-$(CONFIG_OF_CONTROL) += read.o endif obj-$(CONFIG_$(XPL_)OF_PLATDATA) += read.o -obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o +obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o ofnode_graph.o ccflags-$(CONFIG_DM_DEBUG) += -DDEBUG diff --git a/drivers/core/ofnode_graph.c b/drivers/core/ofnode_graph.c new file mode 100644 index 00000000000..90c92af3258 --- /dev/null +++ b/drivers/core/ofnode_graph.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#define LOG_CATEGORY LOGC_DT + +#include <dm.h> +#include <log.h> +#include <dm/ofnode.h> +#include <linux/err.h> + +/** + * ofnode_graph_get_endpoint_count() - get the number of endpoints in a device ofnode + * @parent: ofnode to the device containing ports and endpoints + * + * Return: count of endpoint of this device ofnode + */ +unsigned int ofnode_graph_get_endpoint_count(ofnode parent) +{ + ofnode ports, port, endpoint; + unsigned int num = 0; + + /* Check if ports node exists */ + ports = ofnode_find_subnode(parent, "ports"); + if (ofnode_valid(ports)) + parent = ports; + + ofnode_for_each_subnode(port, parent) { + if (!strncmp(ofnode_get_name(port), "port", 4)) { + /* Port node can only contain endpoints */ + ofnode_for_each_subnode(endpoint, port) + num++; + } + }; + + log_debug("%s: detected %d endpoints\n", __func__, num); + + return num++; +} + +/** + * ofnode_graph_get_port_count() - get the number of port in a device or ports ofnode + * @parent: ofnode to the device or ports node + * + * Return: count of port of this device or ports node + */ +unsigned int ofnode_graph_get_port_count(ofnode parent) +{ + ofnode ports, port; + unsigned int num = 0; + + /* Check if ports node exists */ + ports = ofnode_find_subnode(parent, "ports"); + if (ofnode_valid(ports)) + parent = ports; + + ofnode_for_each_subnode(port, parent) + if (!strncmp(ofnode_get_name(port), "port", 4)) + num++; + + log_debug("%s: detected %d ports\n", __func__, num); + + return num++; +} + +/** + * ofnode_graph_get_port_by_id() - get the port matching a given id + * @parent: parent ofnode + * @id: id of the port + * + * Return: ofnode in given port. + */ +ofnode ofnode_graph_get_port_by_id(ofnode parent, u32 id) +{ + ofnode ports, port; + u32 port_id; + + ports = ofnode_find_subnode(parent, "ports"); + if (!ofnode_valid(ports)) + return ofnode_null(); + + /* Check ports for node with desired id */ + ofnode_for_each_subnode(port, ports) { + ofnode_read_u32(port, "reg", &port_id); + log_debug("%s: detected port %d\n", __func__, port_id); + if (port_id == id) + return port; + } + + return ofnode_null(); +} + +/** + * ofnode_graph_get_endpoint_by_regs() - get the endpoint matching a given id + * @parent: parent ofnode + * @reg_id: id of the port + * @id: id for the endpoint + * + * Return: ofnode in given endpoint or ofnode_null() if not found. + * reg and port_reg are ignored when they are -1. + */ +ofnode ofnode_graph_get_endpoint_by_regs(ofnode parent, int reg_id, int id) +{ + ofnode port, endpoint; + u32 ep_id; + + /* get the port to work with */ + if (reg_id < 0) + port = ofnode_find_subnode(parent, "port"); + else + port = ofnode_graph_get_port_by_id(parent, reg_id); + + if (!ofnode_valid(port)) { + log_debug("%s: port node is not found\n", __func__); + return ofnode_null(); + } + + if (id < 0) + return ofnode_find_subnode(port, "endpoint"); + + /* Check endpoints for node with desired id */ + ofnode_for_each_subnode(endpoint, port) { + ofnode_read_u32(endpoint, "reg", &ep_id); + log_debug("%s: detected endpoint %d\n", __func__, ep_id); + if (ep_id == id) + return endpoint; + } + + return ofnode_null(); +} + +/** + * ofnode_graph_get_remote_endpoint() - get remote endpoint node + * @endpoint: ofnode of a local endpoint + * + * Return: Remote endpoint ofnode linked with local endpoint. + */ +ofnode ofnode_graph_get_remote_endpoint(ofnode endpoint) +{ + /* Get remote endpoint node. */ + return ofnode_parse_phandle(endpoint, "remote-endpoint", 0); +} + +/** + * ofnode_graph_get_port_parent() - get port's parent node + * @endpoint: ofnode of a local endpoint + * + * Return: device ofnode associated with endpoint + */ +ofnode ofnode_graph_get_port_parent(ofnode endpoint) +{ + ofnode port = ofnode_get_parent(endpoint); + ofnode parent = ofnode_get_parent(port); + + /* check if we are on top level or in ports node */ + if (!strcmp(ofnode_get_name(parent), "ports")) + parent = ofnode_get_parent(parent); + + return parent; +} + +/** + * ofnode_graph_get_remote_port_parent() - get remote port's parent ofnode + * @endpoint: ofnode of a local endpoint + * + * Return: device ofnode associated with endpoint linked to local endpoint. + */ +ofnode ofnode_graph_get_remote_port_parent(ofnode endpoint) +{ + ofnode remote_endpoint = ofnode_graph_get_remote_endpoint(endpoint); + if (!ofnode_valid(remote_endpoint)) { + log_debug("%s: remote endpoint is not found\n", __func__); + return ofnode_null(); + } + + return ofnode_graph_get_port_parent(remote_endpoint); +} + +/** + * ofnode_graph_get_remote_port() - get remote port ofnode + * @endpoint: ofnode of a local endpoint + * + * Return: port ofnode associated with remote endpoint node linked + * to local endpoint. + */ +ofnode ofnode_graph_get_remote_port(ofnode endpoint) +{ + ofnode remote_endpoint = ofnode_graph_get_remote_endpoint(endpoint); + if (!ofnode_valid(remote_endpoint)) { + log_debug("%s: remote endpoint is not found\n", __func__); + return ofnode_null(); + } + + return ofnode_get_parent(remote_endpoint); +} + +/** + * ofnode_graph_get_remote_node() - get remote parent ofnode for given port/endpoint + * @parent: parent ofnode containing graph port/endpoint + * @port: identifier (value of reg property) of the parent port ofnode + * @endpoint: identifier (value of reg property) of the endpoint ofnode + * + * Return: device ofnode associated with endpoint linked to local endpoint. + */ +ofnode ofnode_graph_get_remote_node(ofnode parent, int port, int endpoint) +{ + ofnode endpoint_ofnode; + + endpoint_ofnode = ofnode_graph_get_endpoint_by_regs(parent, port, endpoint); + if (!ofnode_valid(endpoint_ofnode)) { + log_debug("%s: endpoint is not found\n", __func__); + return ofnode_null(); + } + + return ofnode_graph_get_remote_port_parent(endpoint_ofnode); +} diff --git a/drivers/core/root.c b/drivers/core/root.c index 15b8c83fee9..e53381e3b32 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -295,22 +295,29 @@ void *dm_priv_to_rw(void *priv) * all its children recursively to do the same. * * @dev: Device to (maybe) probe + * @pre_reloc_only: Probe only devices marked with the DM_FLAG_PRE_RELOC flag * Return 0 if OK, -ve on error */ -static int dm_probe_devices(struct udevice *dev) +static int dm_probe_devices(struct udevice *dev, bool pre_reloc_only) { + ofnode node = dev_ofnode(dev); struct udevice *child; + int ret; - if (dev_get_flags(dev) & DM_FLAG_PROBE_AFTER_BIND) { - int ret; + if (pre_reloc_only && + (!ofnode_valid(node) || !ofnode_pre_reloc(node)) && + !(dev->driver->flags & DM_FLAG_PRE_RELOC)) + goto probe_children; + if (dev_get_flags(dev) & DM_FLAG_PROBE_AFTER_BIND) { ret = device_probe(dev); if (ret) return ret; } +probe_children: list_for_each_entry(child, &dev->child_head, sibling_node) - dm_probe_devices(child); + dm_probe_devices(child, pre_reloc_only); return 0; } @@ -319,7 +326,7 @@ int dm_autoprobe(void) { int ret; - ret = dm_probe_devices(gd->dm_root); + ret = dm_probe_devices(gd->dm_root, !(gd->flags & GD_FLG_RELOC)); if (ret) return log_msg_ret("pro", ret); diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c index 79b32e2627c..b721c866095 100644 --- a/drivers/crypto/fsl/fsl_hash.c +++ b/drivers/crypto/fsl/fsl_hash.c @@ -183,6 +183,7 @@ int caam_hash(const unsigned char *pbuf, unsigned int buf_len, { int ret = 0; uint32_t *desc; + unsigned long pbuf_aligned; unsigned int size; desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE); @@ -191,8 +192,9 @@ int caam_hash(const unsigned char *pbuf, unsigned int buf_len, return -ENOMEM; } - size = ALIGN(buf_len, ARCH_DMA_MINALIGN); - flush_dcache_range((unsigned long)pbuf, (unsigned long)pbuf + size); + pbuf_aligned = ALIGN_DOWN((unsigned long)pbuf, ARCH_DMA_MINALIGN); + size = ALIGN(buf_len + ((unsigned long)pbuf - pbuf_aligned), ARCH_DMA_MINALIGN); + flush_dcache_range(pbuf_aligned, pbuf_aligned + size); inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout, driver_hash[algo].alg_type, diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 3c64e894646..4b47be6b016 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -76,6 +76,13 @@ config XILINX_DPDMA this file is used as placeholder for driver. The main reason is to record compatible string and calling power domain driver. +config ADI_DMA + bool "ADI DMA driver" + depends on DMA && DMA_CHANNELS + help + Enable DMA support for Analog Devices SOCs, such as the SC5xx. + Currently this is a minimalistic driver tested against OSPI use only. + if APBH_DMA config APBH_DMA_BURST bool "Enable DMA BURST" diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 48811eaaeb3..00d765864cd 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -13,5 +13,6 @@ obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o obj-$(CONFIG_TI_EDMA3) += ti-edma3.o obj-$(CONFIG_DMA_LPC32XX) += lpc32xx_dma.o obj-$(CONFIG_XILINX_DPDMA) += xilinx_dpdma.o +obj-$(CONFIG_ADI_DMA) += adi_dma.o obj-y += ti/ diff --git a/drivers/dma/adi_dma.c b/drivers/dma/adi_dma.c new file mode 100644 index 00000000000..28afe488db0 --- /dev/null +++ b/drivers/dma/adi_dma.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices DMA controller driver + * + * (C) Copyright 2024 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * Contact: Ian Roberts <ian.roberts@timesys.com> + * + */ +#include <dm.h> +#include <dma.h> +#include <dma-uclass.h> +#include <dm/device_compat.h> +#include <linux/errno.h> +#include <linux/io.h> + +#define HAS_MDMA BIT(0) + +#define REG_ADDRSTART 0x04 +#define REG_CFG 0x08 +#define REG_XCNT 0x0C +#define REG_XMOD 0x10 +#define REG_STAT 0x30 + +#define BITP_DMA_CFG_MSIZE 8 +#define BITP_DMA_CFG_PSIZE 4 +#define BITM_DMA_CFG_WNR 0x00000002 +#define BITM_DMA_CFG_EN 0x00000001 +#define ENUM_DMA_CFG_XCNT_INT 0x00100000 + +#define BITP_DMA_STAT_PBWID 12 +#define BITP_DMA_STAT_ERRC 4 +#define BITM_DMA_STAT_PBWID 0x00003000 +#define BITM_DMA_STAT_ERRC 0x00000070 +#define BITM_DMA_STAT_PIRQ 0x00000004 +#define BITM_DMA_STAT_IRQERR 0x00000002 +#define BITM_DMA_STAT_IRQDONE 0x00000001 + +#define DMA_MDMA_SRC_DEFAULT_CONFIG(psize, msize) \ + (BITM_DMA_CFG_EN | ((psize) << BITP_DMA_CFG_PSIZE) | ((msize) << BITP_DMA_CFG_MSIZE)) +#define DMA_MDMA_DST_DEFAULT_CONFIG(psize, msize) \ + (BITM_DMA_CFG_EN | BITM_DMA_CFG_WNR | ENUM_DMA_CFG_XCNT_INT | \ + ((psize) << BITP_DMA_CFG_PSIZE) | ((msize) << BITP_DMA_CFG_MSIZE)) + +struct adi_dma_channel { + int id; + struct adi_dma *dma; + void __iomem *iosrc; + void __iomem *iodest; +}; + +struct adi_dma { + struct udevice *dev; + struct adi_dma_channel channels[1]; + void __iomem *ioaddr; + unsigned long hw_cfg; +}; + +static const struct udevice_id dma_dt_ids[] = { + { .compatible = "adi,mdma-controller", .data = HAS_MDMA }, + { } +}; + +static u8 adi_dma_get_msize(u32 n_bytecount, u32 n_address) +{ + /* Calculate MSIZE, PSIZE, XCNT and XMOD */ + u8 n_msize = 0; + u32 n_value = n_bytecount | n_address; + u32 n_mask = 0x1; + + for (n_msize = 0; n_msize < 5; n_msize++, n_mask <<= 1) { + if ((n_value & n_mask) == n_mask) + break; + } + + return n_msize; +} + +static int adi_dma_get_ch_error(void __iomem *ch) +{ + u32 cause = (ioread32(ch + REG_STAT) & BITM_DMA_STAT_ERRC) >> + BITP_DMA_STAT_ERRC; + switch (cause) { + case 0: + return -EINVAL; + case 1: + return -EBUSY; + case 2: + return -EFAULT; + case 3: + fallthrough; + case 5: + fallthrough; + case 6: + fallthrough; + default: + return -EIO; + } +} + +static int adi_mdma_transfer(struct udevice *dev, int direction, + dma_addr_t dst, dma_addr_t src, size_t len) +{ + struct adi_dma *priv = dev_get_priv(dev); + void __iomem *chsrc = priv->channels[0].iosrc; + void __iomem *chdst = priv->channels[0].iodest; + + int result = 0; + u32 reg; + u32 bytecount = len; + + u8 n_srcmsize; + u8 n_dstmsize; + u8 n_srcpsize; + u8 n_dstpsize; + u8 n_psize; + u32 srcconfig; + u32 dstconfig; + u8 srcpsizemax = (ioread32(chsrc + REG_STAT) & BITM_DMA_STAT_PBWID) >> + BITP_DMA_STAT_PBWID; + u8 dstpsizemax = (ioread32(chdst + REG_STAT) & BITM_DMA_STAT_PBWID) >> + BITP_DMA_STAT_PBWID; + + const u32 CLRSTAT = (BITM_DMA_STAT_IRQDONE | BITM_DMA_STAT_IRQERR | + BITM_DMA_STAT_PIRQ); + + if (len == 0) + return -EINVAL; + + /* Clear DMA status */ + iowrite32(CLRSTAT, chsrc + REG_STAT); + iowrite32(CLRSTAT, chdst + REG_STAT); + + /* Calculate MSIZE, PSIZE, XCNT and XMOD */ + n_srcmsize = adi_dma_get_msize(bytecount, src); + n_dstmsize = adi_dma_get_msize(bytecount, dst); + n_srcpsize = min(n_srcmsize, srcpsizemax); + n_dstpsize = min(n_dstmsize, dstpsizemax); + n_psize = min(n_srcpsize, n_dstpsize); + + srcconfig = DMA_MDMA_SRC_DEFAULT_CONFIG(n_psize, n_srcmsize); + dstconfig = DMA_MDMA_DST_DEFAULT_CONFIG(n_psize, n_dstmsize); + + /* Load the DMA descriptors */ + iowrite32(src, chsrc + REG_ADDRSTART); + iowrite32(bytecount >> n_srcmsize, chsrc + REG_XCNT); + iowrite32(1 << n_srcmsize, chsrc + REG_XMOD); + iowrite32(dst, chdst + REG_ADDRSTART); + iowrite32(bytecount >> n_dstmsize, chdst + REG_XCNT); + iowrite32(1 << n_dstmsize, chdst + REG_XMOD); + + iowrite32(dstconfig, chdst + REG_CFG); + iowrite32(srcconfig, chsrc + REG_CFG); + + /* Wait for DMA to complete while checking for a DMA error */ + do { + reg = ioread32(chsrc + REG_STAT); + if ((reg & BITM_DMA_STAT_IRQERR) == BITM_DMA_STAT_IRQERR) { + result = adi_dma_get_ch_error(chsrc); + break; + } + reg = ioread32(chdst + REG_STAT); + if ((reg & BITM_DMA_STAT_IRQERR) == BITM_DMA_STAT_IRQERR) { + result = adi_dma_get_ch_error(chdst); + break; + } + } while ((reg & BITM_DMA_STAT_IRQDONE) == 0); + + clrbits_32(chsrc + REG_CFG, 1); + clrbits_32(chdst + REG_CFG, 1); + + return result; +} + +static int adi_dma_init_channel(struct adi_dma *dma, + struct adi_dma_channel *channel, ofnode node) +{ + u32 offset; + + if (ofnode_read_u32(node, "adi,id", &channel->id)) { + dev_err(dma->dev, "Missing adi,id for channel %s\n", + ofnode_get_name(node)); + return -ENOENT; + } + + if (ofnode_read_u32(node, "adi,src-offset", &offset)) { + dev_err(dma->dev, "Missing adi,src-offset for channel %s\n", + ofnode_get_name(node)); + return -ENOENT; + } + + channel->iosrc = dma->ioaddr + offset; + channel->dma = dma; + + if (dma->hw_cfg & HAS_MDMA) { + if (ofnode_read_u32(node, "adi,dest-offset", &offset)) { + dev_err(dma->dev, + "Missing adi,dest-offset for channel %s\n", + ofnode_get_name(node)); + return -ENOENT; + } + channel->iodest = dma->ioaddr + offset; + } + + return 0; +} + +static int adi_dma_probe(struct udevice *dev) +{ + struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct adi_dma *priv = dev_get_priv(dev); + ofnode node, child; + + priv->hw_cfg = dev_get_driver_data(dev); + if (priv->hw_cfg & HAS_MDMA) + uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM; + + priv->ioaddr = dev_remap_addr(dev); + if (!priv->ioaddr) + return -EINVAL; + + node = dev_read_first_subnode(dev); + if (!ofnode_valid(node)) { + dev_err(dev, + "Error: device tree DMA channel config missing!\n"); + return -ENODEV; + } + + node = dev_ofnode(dev); + ofnode_for_each_subnode(child, node) { + adi_dma_init_channel(priv, priv->channels, child); + break; //Only 1 channel supported for now + } + + return 0; +} + +static const struct dma_ops adi_dma_ops = { + .transfer = adi_mdma_transfer, +}; + +U_BOOT_DRIVER(adi_dma) = { + .name = "adi_dma", + .id = UCLASS_DMA, + .of_match = dma_dt_ids, + .ops = &adi_dma_ops, + .probe = adi_dma_probe, + .priv_auto = sizeof(struct adi_dma), +}; diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index 3013c4741d0..723265ab2e5 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -36,6 +36,7 @@ #include "k3-psil-priv.h" #define K3_UDMA_MAX_RFLOWS 1024 +#define K3_UDMA_MAX_TR 2 struct udma_chan; @@ -74,7 +75,6 @@ struct udma_tchan { struct k3_nav_ring *t_ring; /* Transmit ring */ struct k3_nav_ring *tc_ring; /* Transmit Completion ring */ int tflow_id; /* applicable only for PKTDMA */ - }; #define udma_bchan udma_tchan @@ -175,6 +175,7 @@ struct udma_dev { struct udma_rflow *rflows; struct udma_match_data *match_data; + void *bc_desc; struct udma_chan *channels; u32 psil_base; @@ -1349,6 +1350,7 @@ static int udma_setup_resources(struct udma_dev *ud) struct ti_sci_resource_desc *rm_desc; struct ti_sci_resource *rm_res; struct udma_tisci_rm *tisci_rm = &ud->tisci_rm; + size_t desc_size; ud->tchan_map = devm_kmalloc_array(dev, BITS_TO_LONGS(ud->tchan_cnt), sizeof(unsigned long), GFP_KERNEL); @@ -1366,9 +1368,11 @@ static int udma_setup_resources(struct udma_dev *ud) ud->rflows = devm_kcalloc(dev, ud->rflow_cnt, sizeof(*ud->rflows), GFP_KERNEL); + desc_size = cppi5_trdesc_calc_size(K3_UDMA_MAX_TR, sizeof(struct cppi5_tr_type15_t)); + ud->bc_desc = devm_kzalloc(dev, ALIGN(desc_size, ARCH_DMA_MINALIGN), GFP_KERNEL); if (!ud->tchan_map || !ud->rchan_map || !ud->rflow_map || !ud->rflow_map_reserved || !ud->tchans || !ud->rchans || - !ud->rflows) + !ud->rflows || !ud->bc_desc) return -ENOMEM; /* @@ -1444,6 +1448,7 @@ static int bcdma_setup_resources(struct udma_dev *ud) struct ti_sci_resource_desc *rm_desc; struct ti_sci_resource *rm_res; struct udma_tisci_rm *tisci_rm = &ud->tisci_rm; + size_t desc_size; ud->bchan_map = devm_kmalloc_array(dev, BITS_TO_LONGS(ud->bchan_cnt), sizeof(unsigned long), GFP_KERNEL); @@ -1460,9 +1465,12 @@ static int bcdma_setup_resources(struct udma_dev *ud) ud->rflows = devm_kcalloc(dev, ud->rchan_cnt, sizeof(*ud->rflows), GFP_KERNEL); + desc_size = cppi5_trdesc_calc_size(K3_UDMA_MAX_TR, sizeof(struct cppi5_tr_type15_t)); + ud->bc_desc = devm_kzalloc(dev, ALIGN(desc_size, ARCH_DMA_MINALIGN), GFP_KERNEL); + if (!ud->bchan_map || !ud->tchan_map || !ud->rchan_map || !ud->bchans || !ud->tchans || !ud->rchans || - !ud->rflows) + !ud->rflows || !ud->bc_desc) return -ENOMEM; /* Get resource ranges from tisci */ @@ -1718,8 +1726,7 @@ static int *udma_prep_dma_memcpy(struct udma_chan *uc, dma_addr_t dest, int num_tr; size_t tr_size = sizeof(struct cppi5_tr_type15_t); u16 tr0_cnt0, tr0_cnt1, tr1_cnt0; - unsigned long dummy; - void *tr_desc; + void *tr_desc = uc->ud->bc_desc; size_t desc_size; if (len < SZ_64K) { @@ -1748,9 +1755,6 @@ static int *udma_prep_dma_memcpy(struct udma_chan *uc, dma_addr_t dest, } desc_size = cppi5_trdesc_calc_size(num_tr, tr_size); - tr_desc = dma_alloc_coherent(desc_size, &dummy); - if (!tr_desc) - return NULL; memset(tr_desc, 0, desc_size); cppi5_trdesc_init(tr_desc, num_tr, tr_size, 0, 0); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f4a453e1cdd..e11109fb56d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -97,6 +97,15 @@ config SPL_DM_GPIO_LOOKUP_LABEL different gpios on different hardware versions for the same functionality in board code. +config ADI_GPIO + bool "ADI GPIO driver" + depends on DM_GPIO && ARCH_SC5XX + help + This driver supports GPIO banks on SC5xx processors. It + supports inputs and outputs but does not support pin + interrupt functionality (PINT) or other features in the + Linux version of the driver. + config ALTERA_PIO bool "Altera PIO driver" depends on DM_GPIO @@ -516,7 +525,7 @@ config ZYNQ_GPIO config DM_74X164 bool "74x164 serial-in/parallel-out 8-bits shift register" - depends on DM_GPIO + depends on DM_GPIO && DM_SPI help Driver for 74x164 compatible serial-in/parallel-out 8-outputs shift registers, such as 74lv165, 74hc595. @@ -545,6 +554,14 @@ config DM_PCA953X Now, max 24 bits chips and PCA953X compatible chips are supported +config ADP5588_GPIO + bool "ADP5588 GPIO expander driver" + depends on DM_GPIO && DM_I2C + help + Say yes here to support GPIO functionality of ADI ADP5588 chips. + + The ADP5588 is an 18-port I2C GPIO expander and keypad controller. + config SPL_DM_PCA953X bool "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports in SPL" depends on SPL_DM_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 3f882c065d8..d426d3a2d7b 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_$(PHASE_)DM_GPIO) += gpio-uclass.o obj-$(CONFIG_$(XPL_)DM_PCA953X) += pca953x_gpio.o +obj-$(CONFIG_ADI_GPIO) += gpio-adi-adsp.o obj-$(CONFIG_ASPEED_GPIO) += gpio-aspeed.o obj-$(CONFIG_ASPEED_G7_GPIO) += gpio-aspeed-g7.o obj-$(CONFIG_ASPEED_SGPIO) += gpio-aspeed-sgpio.o @@ -74,6 +75,7 @@ obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o obj-$(CONFIG_$(XPL_)MAX77663_GPIO) += max77663_gpio.o obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o +obj-$(CONFIG_ADP5588_GPIO) += adp5588_gpio.o obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o obj-$(CONFIG_FTGPIO010) += ftgpio010.o diff --git a/drivers/gpio/adp5588_gpio.c b/drivers/gpio/adp5588_gpio.c new file mode 100644 index 00000000000..d081e169897 --- /dev/null +++ b/drivers/gpio/adp5588_gpio.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * GPIO Chip driver for Analog Devices + * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller + * + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * + * Based on Michael Hennerich's Linux driver: + * Michael Hennerich <michael.hennerich@analog.com> + * + */ + +#include <dm.h> +#include <i2c.h> +#include <asm-generic/gpio.h> + +#define ADP5588_MAXGPIO 18 +#define ADP5588_BANK(offs) ((offs) >> 3) +#define ADP5588_BIT(offs) (1u << ((offs) & 0x7)) + +#define DEV_ID 0x00 /* Device ID */ +#define GPIO_DAT_STAT1 0x14 /* GPIO Data Status, Read twice to clear */ +#define GPIO_DAT_STAT2 0x15 /* GPIO Data Status, Read twice to clear */ +#define GPIO_DAT_STAT3 0x16 /* GPIO Data Status, Read twice to clear */ +#define GPIO_DAT_OUT1 0x17 /* GPIO DATA OUT */ +#define GPIO_DAT_OUT2 0x18 /* GPIO DATA OUT */ +#define GPIO_DAT_OUT3 0x19 /* GPIO DATA OUT */ +#define GPIO_INT_EN1 0x1A /* GPIO Interrupt Enable */ +#define GPIO_INT_EN2 0x1B /* GPIO Interrupt Enable */ +#define GPIO_INT_EN3 0x1C /* GPIO Interrupt Enable */ +#define KP_GPIO1 0x1D /* Keypad or GPIO Selection */ +#define KP_GPIO2 0x1E /* Keypad or GPIO Selection */ +#define KP_GPIO3 0x1F /* Keypad or GPIO Selection */ +#define GPIO_DIR1 0x23 /* GPIO Data Direction */ +#define GPIO_DIR2 0x24 /* GPIO Data Direction */ +#define GPIO_DIR3 0x25 /* GPIO Data Direction */ +#define GPIO_PULL1 0x2C /* GPIO Pull Disable */ +#define GPIO_PULL2 0x2D /* GPIO Pull Disable */ +#define GPIO_PULL3 0x2E /* GPIO Pull Disable */ +#define ID_MASK 0x0F + +struct adp5588_gpio { + u8 dat_out[3]; + u8 dir[3]; +}; + +static int adp5588_gpio_read(struct udevice *dev, u8 reg) +{ + int ret; + u8 val; + + ret = dm_i2c_read(dev, reg, &val, 1); + + if (ret < 0) { + pr_err("%s: read error\n", __func__); + return ret; + } + + return val; +} + +static int adp5588_gpio_write(struct udevice *dev, u8 reg, u8 val) +{ + int ret; + + ret = dm_i2c_write(dev, reg, &val, 1); + if (ret < 0) { + pr_err("%s: write error\n", __func__); + return ret; + } + + return 0; +} + +static int adp5588_get_value(struct udevice *dev, u32 offset) +{ + struct adp5588_gpio *plat = dev_get_plat(dev); + unsigned int bank = ADP5588_BANK(offset); + unsigned int bit = ADP5588_BIT(offset); + int val; + + if (plat->dir[bank] & bit) + val = plat->dat_out[bank]; + else + val = adp5588_gpio_read(dev, GPIO_DAT_STAT1 + bank); + + return !!(val & bit); +} + +static int adp5588_set_value(struct udevice *dev, u32 offset, + int32_t value) +{ + unsigned int bank, bit; + int ret; + struct adp5588_gpio *plat = dev_get_plat(dev); + + bank = ADP5588_BANK(offset); + bit = ADP5588_BIT(offset); + + if (value) + plat->dat_out[bank] |= bit; + else + plat->dat_out[bank] &= ~bit; + + ret = adp5588_gpio_write(dev, GPIO_DAT_OUT1 + bank, + plat->dat_out[bank]); + + return ret; +} + +static int adp5588_direction_input(struct udevice *dev, u32 offset) +{ + int ret; + unsigned int bank; + struct adp5588_gpio *plat = dev_get_plat(dev); + + bank = ADP5588_BANK(offset); + + plat->dir[bank] &= ~ADP5588_BIT(offset); + ret = adp5588_gpio_write(dev, GPIO_DIR1 + bank, plat->dir[bank]); + + return ret; +} + +static int adp5588_direction_output(struct udevice *dev, + u32 offset, int value) +{ + int ret; + unsigned int bank, bit; + struct adp5588_gpio *plat = dev_get_plat(dev); + + bank = ADP5588_BANK(offset); + bit = ADP5588_BIT(offset); + + plat->dir[bank] |= bit; + + if (value) + plat->dat_out[bank] |= bit; + else + plat->dat_out[bank] &= ~bit; + + ret = adp5588_gpio_write(dev, GPIO_DAT_OUT1 + bank, + plat->dat_out[bank]); + ret |= adp5588_gpio_write(dev, GPIO_DIR1 + bank, + plat->dir[bank]); + + return ret; +} + +static int adp5588_ofdata_platdata(struct udevice *dev) +{ + struct adp5588_gpio *plat = dev_get_plat(dev); + struct gpio_dev_priv *priv = dev_get_uclass_priv(dev); + int node = dev_of_offset(dev); + int ret, i, revid; + + priv->gpio_count = ADP5588_MAXGPIO; + priv->bank_name = fdt_get_name(gd->fdt_blob, node, NULL); + + ret = adp5588_gpio_read(dev, DEV_ID); + if (ret < 0) + return ret; + + revid = ret & ID_MASK; + + printf("ADP5588 Detected: Rev %x, Rev ID %x\n", ret, revid); + + for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) { + plat->dat_out[i] = adp5588_gpio_read(dev, GPIO_DAT_OUT1 + i); + plat->dir[i] = adp5588_gpio_read(dev, GPIO_DIR1 + i); + ret |= adp5588_gpio_write(dev, KP_GPIO1 + i, 0); + ret |= adp5588_gpio_write(dev, GPIO_PULL1 + i, 0); + ret |= adp5588_gpio_write(dev, GPIO_INT_EN1 + i, 0); + if (ret) { + pr_err("%s: Initialization error\n", __func__); + return ret; + } + } + + return 0; +} + +static const struct dm_gpio_ops adp5588_ops = { + .direction_input = adp5588_direction_input, + .direction_output = adp5588_direction_output, + .get_value = adp5588_get_value, + .set_value = adp5588_set_value, +}; + +static const struct udevice_id adp5588_of_match_list[] = { + { .compatible = "adi,adp5588"}, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(gpio_adp5588) = { + .name = "gpio_adp5588", + .id = UCLASS_GPIO, + .ops = &adp5588_ops, + .of_match = adp5588_of_match_list, + .of_to_plat = adp5588_ofdata_platdata, + .plat_auto = sizeof(struct adp5588_gpio), + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/gpio/gpio-adi-adsp.c b/drivers/gpio/gpio-adi-adsp.c new file mode 100644 index 00000000000..0ce00572e08 --- /dev/null +++ b/drivers/gpio/gpio-adi-adsp.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Author: Greg Malysa <greg.malysa@timesys.com> + * Additional Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + */ + +#include <dm.h> +#include <asm-generic/gpio.h> +#include <dm/device_compat.h> +#include <linux/bitops.h> +#include <linux/io.h> + +#define ADSP_PORT_MMIO_SIZE 0x80 +#define ADSP_PORT_PIN_SIZE 16 + +#define ADSP_PORT_REG_FER 0x00 +#define ADSP_PORT_REG_FER_SET 0x04 +#define ADSP_PORT_REG_FER_CLEAR 0x08 +#define ADSP_PORT_REG_DATA 0x0c +#define ADSP_PORT_REG_DATA_SET 0x10 +#define ADSP_PORT_REG_DATA_CLEAR 0x14 +#define ADSP_PORT_REG_DIR 0x18 +#define ADSP_PORT_REG_DIR_SET 0x1c +#define ADSP_PORT_REG_DIR_CLEAR 0x20 +#define ADSP_PORT_REG_INEN 0x24 +#define ADSP_PORT_REG_INEN_SET 0x28 +#define ADSP_PORT_REG_INEN_CLEAR 0x2c +#define ADSP_PORT_REG_PORT_MUX 0x30 +#define ADSP_PORT_REG_DATA_TGL 0x34 +#define ADSP_PORT_REG_POLAR 0x38 +#define ADSP_PORT_REG_POLAR_SET 0x3c +#define ADSP_PORT_REG_POLAR_CLEAR 0x40 +#define ADSP_PORT_REG_LOCK 0x44 +#define ADSP_PORT_REG_TRIG_TGL 0x48 + +struct adsp_gpio_priv { + void __iomem *base; + int ngpio; +}; + +static u32 get_port(unsigned int pin) +{ + return pin / ADSP_PORT_PIN_SIZE; +} + +static u32 get_offset(unsigned int pin) +{ + return pin % ADSP_PORT_PIN_SIZE; +} + +static int adsp_gpio_input(struct udevice *udev, unsigned int pin) +{ + struct adsp_gpio_priv *priv = dev_get_priv(udev); + u32 port, offset; + void __iomem *portbase; + + if (pin < priv->ngpio) { + port = get_port(pin); + offset = get_offset(pin); + portbase = priv->base + port * ADSP_PORT_MMIO_SIZE; + + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_FER_CLEAR); + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DIR_CLEAR); + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_INEN_SET); + return 0; + } + + return -EINVAL; +} + +static int adsp_gpio_output(struct udevice *udev, unsigned int pin, int value) +{ + struct adsp_gpio_priv *priv = dev_get_priv(udev); + u32 port, offset; + void __iomem *portbase; + + if (pin < priv->ngpio) { + port = get_port(pin); + offset = get_offset(pin); + portbase = priv->base + port * ADSP_PORT_MMIO_SIZE; + + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_FER_CLEAR); + + if (value) + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DATA_SET); + else + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DATA_CLEAR); + + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DIR_SET); + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_INEN_CLEAR); + return 0; + } + + return -EINVAL; +} + +static int adsp_gpio_get_value(struct udevice *udev, unsigned int pin) +{ + struct adsp_gpio_priv *priv = dev_get_priv(udev); + u32 port, offset; + u16 val; + void __iomem *portbase; + + if (pin < priv->ngpio) { + port = get_port(pin); + offset = get_offset(pin); + portbase = priv->base + port * ADSP_PORT_MMIO_SIZE; + + val = ioread16(portbase + ADSP_PORT_REG_DATA); + return !!(val & BIT(offset)); + } + + return 0; +} + +static int adsp_gpio_set_value(struct udevice *udev, unsigned int pin, int value) +{ + struct adsp_gpio_priv *priv = dev_get_priv(udev); + u32 port, offset; + void __iomem *portbase; + + if (pin < priv->ngpio) { + port = get_port(pin); + offset = get_offset(pin); + portbase = priv->base + port * ADSP_PORT_MMIO_SIZE; + + if (value) + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DATA_SET); + else + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DATA_CLEAR); + } + + return 0; +} + +static const struct dm_gpio_ops adsp_gpio_ops = { + .direction_input = adsp_gpio_input, + .direction_output = adsp_gpio_output, + .get_value = adsp_gpio_get_value, + .set_value = adsp_gpio_set_value, +}; + +static int adsp_gpio_probe(struct udevice *udev) +{ + struct adsp_gpio_priv *priv = dev_get_priv(udev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(udev); + + uc_priv->bank_name = "adsp gpio"; + uc_priv->gpio_count = dev_read_u32_default(udev, "adi,ngpios", 0); + + if (!uc_priv->gpio_count) { + dev_err(udev, "Missing adi,ngpios property!\n"); + return -ENOENT; + } + + priv->base = dev_read_addr_ptr(udev); + priv->ngpio = uc_priv->gpio_count; + + return 0; +} + +static const struct udevice_id adsp_gpio_match[] = { + { .compatible = "adi,adsp-gpio" }, + { }, +}; + +U_BOOT_DRIVER(adi_adsp_gpio) = { + .name = "adi_adsp_gpio", + .id = UCLASS_GPIO, + .ops = &adsp_gpio_ops, + .probe = adsp_gpio_probe, + .priv_auto = sizeof(struct adsp_gpio_priv), + .of_match = adsp_gpio_match, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index cdae6825736..46e76385961 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -154,6 +154,13 @@ config SPL_DM_I2C_GPIO bindings are supported. Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt +config SYS_I2C_ADI + bool "ADI I2C driver" + depends on DM_I2C && ARCH_SC5XX + help + Add support for the ADI (Analog Devices) I2C driver as used + in SC57X, SC58X, SC59X, SC59X_64. + config SYS_I2C_AT91 bool "Atmel I2C driver" depends on DM_I2C && ARCH_AT91 diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index bebd728e7da..2713289f7db 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_$(XPL_)I2C_CROS_EC_TUNNEL) += cros_ec_tunnel.o obj-$(CONFIG_$(XPL_)I2C_CROS_EC_LDO) += cros_ec_ldo.o obj-$(CONFIG_$(XPL_)SYS_I2C_LEGACY) += i2c_core.o +obj-$(CONFIG_SYS_I2C_ADI) += adi_i2c.o obj-$(CONFIG_SYS_I2C_ASPEED) += ast_i2c.o obj-$(CONFIG_SYS_I2C_AST2600) += ast2600_i2c.o obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c new file mode 100644 index 00000000000..4cddcfa6b7f --- /dev/null +++ b/drivers/i2c/adi_i2c.c @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Converted to driver model by Nathan Barrett-Morrison + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + */ + +#include <clk.h> +#include <dm.h> +#include <i2c.h> +#include <mapmem.h> +#include <linux/io.h> + +#define CLKLOW(x) ((x) & 0xFF) // Periods Clock Is Held Low +#define CLKHI(y) (((y) & 0xFF) << 0x8) // Periods Clock Is High + +#define PRESCALE 0x007F // SCLKs Per Internal Time Reference (10MHz) +#define TWI_ENA 0x0080 // TWI Enable +#define SCCB 0x0200 // SCCB Compatibility Enable + +#define SEN 0x0001 // Slave Enable +#define SADD_LEN 0x0002 // Slave Address Length +#define STDVAL 0x0004 // Slave Transmit Data Valid +#define TSC_NAK 0x0008 // NAK Generated At Conclusion Of Transfer +#define GEN 0x0010 // General Call Adrress Matching Enabled + +#define SDIR 0x0001 // Slave Transfer Direction +#define GCALL 0x0002 // General Call Indicator + +#define MEN 0x0001 // Master Mode Enable +#define MADD_LEN 0x0002 // Master Address Length +#define MDIR 0x0004 // Master Transmit Direction (RX/TX*) +#define FAST 0x0008 // Use Fast Mode Timing Specs +#define STOP 0x0010 // Issue Stop Condition +#define RSTART 0x0020 // Repeat Start or Stop* At End Of Transfer +#define DCNT 0x3FC0 // Data Bytes To Transfer +#define SDAOVR 0x4000 // Serial Data Override +#define SCLOVR 0x8000 // Serial Clock Override + +#define MPROG 0x0001 // Master Transfer In Progress +#define LOSTARB 0x0002 // Lost Arbitration Indicator (Xfer Aborted) +#define ANAK 0x0004 // Address Not Acknowledged +#define DNAK 0x0008 // Data Not Acknowledged +#define BUFRDERR 0x0010 // Buffer Read Error +#define BUFWRERR 0x0020 // Buffer Write Error +#define SDASEN 0x0040 // Serial Data Sense +#define SCLSEN 0x0080 // Serial Clock Sense +#define BUSBUSY 0x0100 // Bus Busy Indicator + +#define SINIT 0x0001 // Slave Transfer Initiated +#define SCOMP 0x0002 // Slave Transfer Complete +#define SERR 0x0004 // Slave Transfer Error +#define SOVF 0x0008 // Slave Overflow +#define MCOMP 0x0010 // Master Transfer Complete +#define MERR 0x0020 // Master Transfer Error +#define XMTSERV 0x0040 // Transmit FIFO Service +#define RCVSERV 0x0080 // Receive FIFO Service + +#define XMTFLUSH 0x0001 // Transmit Buffer Flush +#define RCVFLUSH 0x0002 // Receive Buffer Flush +#define XMTINTLEN 0x0004 // Transmit Buffer Interrupt Length +#define RCVINTLEN 0x0008 // Receive Buffer Interrupt Length + +#define XMTSTAT 0x0003 // Transmit FIFO Status +#define XMT_EMPTY 0x0000 // Transmit FIFO Empty +#define XMT_HALF 0x0001 // Transmit FIFO Has 1 Byte To Write +#define XMT_FULL 0x0003 // Transmit FIFO Full (2 Bytes To Write) + +#define RCVSTAT 0x000C // Receive FIFO Status +#define RCV_EMPTY 0x0000 // Receive FIFO Empty +#define RCV_HALF 0x0004 // Receive FIFO Has 1 Byte To Read +#define RCV_FULL 0x000C // Receive FIFO Full (2 Bytes To Read) + +/* Every register is 32bit aligned, but only 16bits in size */ +#define ureg(name) u16 name; u16 __pad_##name + +struct twi_regs { + ureg(clkdiv); + ureg(control); + ureg(slave_ctl); + ureg(slave_stat); + ureg(slave_addr); + ureg(master_ctl); + ureg(master_stat); + ureg(master_addr); + ureg(int_stat); + ureg(int_mask); + ureg(fifo_ctl); + ureg(fifo_stat); + u8 __pad[0x50]; + + ureg(xmt_data8); + ureg(xmt_data16); + ureg(rcv_data8); + ureg(rcv_data16); +}; + +#undef ureg + +/* + * The way speed is changed into duty often results in integer truncation + * with 50% duty, so we'll force rounding up to the next duty by adding 1 + * to the max. In practice this will get us a speed of something like + * 385 KHz. The other limit is easy to handle as it is only 8 bits. + */ +#define I2C_SPEED_MAX 400000 +#define I2C_SPEED_TO_DUTY(speed) (5000000 / (speed)) +#define I2C_DUTY_MAX (I2C_SPEED_TO_DUTY(I2C_SPEED_MAX) + 1) +#define I2C_DUTY_MIN 0xff /* 8 bit limited */ + +#define I2C_M_COMBO 0x4 +#define I2C_M_STOP 0x2 +#define I2C_M_READ 0x1 + +/* + * All transfers are described by this data structure + */ +struct adi_i2c_msg { + u8 flags; + u32 len; /* msg length */ + u8 *buf; /* pointer to msg data */ + u32 olen; /* addr length */ + u8 *obuf; /* addr buffer */ +}; + +struct adi_i2c_dev { + struct twi_regs __iomem *base; + u32 i2c_clk; + uint speed; +}; + +/* Allow msec timeout per ~byte transfer */ +#define I2C_TIMEOUT 10 + +/** + * wait_for_completion - manage the actual i2c transfer + * @msg: the i2c msg + */ +static int wait_for_completion(struct twi_regs *twi, struct adi_i2c_msg *msg) +{ + u16 int_stat; + ulong timebase = get_timer(0); + + do { + int_stat = ioread16(&twi->int_stat); + + if (int_stat & XMTSERV) { + iowrite16(XMTSERV, &twi->int_stat); + if (msg->olen) { + iowrite16(*(msg->obuf++), &twi->xmt_data8); + --msg->olen; + } else if (!(msg->flags & I2C_M_COMBO) && msg->len) { + iowrite16(*(msg->buf++), &twi->xmt_data8); + --msg->len; + } else { + if (msg->flags & I2C_M_COMBO) + setbits_16(&twi->master_ctl, RSTART | MDIR); + else + setbits_16(&twi->master_ctl, STOP); + } + } + if (int_stat & RCVSERV) { + iowrite16(RCVSERV, &twi->int_stat); + if (msg->len) { + *(msg->buf++) = ioread16(&twi->rcv_data8); + --msg->len; + } else if (msg->flags & I2C_M_STOP) { + setbits_16(&twi->master_ctl, STOP); + } + } + if (int_stat & MERR) { + pr_err("%s: master transmit terror: %d\n", __func__, + ioread16(&twi->master_stat)); + iowrite16(MERR, &twi->int_stat); + return -EIO; + } + if (int_stat & MCOMP) { + iowrite16(MCOMP, &twi->int_stat); + if (msg->flags & I2C_M_COMBO && msg->len) { + u16 mlen = min(msg->len, 0xffu) << 6; + clrsetbits_16(&twi->master_ctl, RSTART, mlen | MEN | MDIR); + } else { + break; + } + } + + /* If we were able to do something, reset timeout */ + if (int_stat) + timebase = get_timer(0); + + } while (get_timer(timebase) < I2C_TIMEOUT); + + return 0; +} + +static int i2c_transfer(struct twi_regs *twi, u8 chip, u8 *offset, + int olen, u8 *buffer, int len, u8 flags) +{ + int ret; + u16 ctl; + + struct adi_i2c_msg msg = { + .flags = flags | (len >= 0xff ? I2C_M_STOP : 0), + .buf = buffer, + .len = len, + .obuf = offset, + .olen = olen, + }; + + /* wait for things to settle */ + while (ioread16(&twi->master_stat) & BUSBUSY) + if (!IS_ENABLED(CONFIG_SPL_BUILD) && ctrlc()) + return -EINTR; + + /* Set Transmit device address */ + iowrite16(chip, &twi->master_addr); + + /* Clear the FIFO before starting things */ + iowrite16(XMTFLUSH | RCVFLUSH, &twi->fifo_ctl); + iowrite16(0, &twi->fifo_ctl); + + /* Prime the pump */ + if (msg.olen) { + len = (msg.flags & I2C_M_COMBO) ? msg.olen : msg.olen + len; + iowrite16(*(msg.obuf++), &twi->xmt_data8); + --msg.olen; + } else if (!(msg.flags & I2C_M_READ) && msg.len) { + iowrite16(*(msg.buf++), &twi->xmt_data8); + --msg.len; + } + + /* clear int stat */ + iowrite16(-1, &twi->master_stat); + iowrite16(-1, &twi->int_stat); + iowrite16(0, &twi->int_mask); + + /* Master enable */ + ctl = ioread16(&twi->master_ctl); + ctl = (ctl & FAST) | (min(len, 0xff) << 6) | MEN | + ((msg.flags & I2C_M_READ) ? MDIR : 0); + iowrite16(ctl, &twi->master_ctl); + + /* Process the rest */ + ret = wait_for_completion(twi, &msg); + + clrbits_16(&twi->master_ctl, MEN); + clrbits_16(&twi->control, TWI_ENA); + setbits_16(&twi->control, TWI_ENA); + return ret; +} + +static int adi_i2c_read(struct twi_regs *twi, u8 chip, + u8 *offset, int olen, u8 *buffer, int len) +{ + return i2c_transfer(twi, chip, offset, olen, buffer, + len, olen ? I2C_M_COMBO : I2C_M_READ); +} + +static int adi_i2c_write(struct twi_regs *twi, u8 chip, + u8 *offset, int olen, u8 *buffer, int len) +{ + return i2c_transfer(twi, chip, offset, olen, buffer, len, 0); +} + +static int adi_i2c_set_bus_speed(struct udevice *bus, uint speed) +{ + struct adi_i2c_dev *dev = dev_get_priv(bus); + struct twi_regs *twi = dev->base; + u16 clkdiv = I2C_SPEED_TO_DUTY(speed); + + /* Set TWI interface clock */ + if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN) + return -1; + clkdiv = (clkdiv << 8) | (clkdiv & 0xff); + iowrite16(clkdiv, &twi->clkdiv); + + /* Don't turn it on */ + iowrite16(speed > 100000 ? FAST : 0, &twi->master_ctl); + + return 0; +} + +static int adi_i2c_of_to_plat(struct udevice *bus) +{ + struct adi_i2c_dev *dev = dev_get_priv(bus); + struct clk clock; + u32 ret; + + dev->base = map_sysmem(dev_read_addr(bus), sizeof(struct twi_regs)); + + if (!dev->base) + return -ENOMEM; + + dev->speed = dev_read_u32_default(bus, "clock-frequency", + I2C_SPEED_FAST_RATE); + + ret = clk_get_by_name(bus, "i2c", &clock); + if (ret < 0) + printf("%s: Can't get I2C clk: %d\n", __func__, ret); + else + dev->i2c_clk = clk_get_rate(&clock); + + return 0; +} + +static int adi_i2c_probe_chip(struct udevice *bus, u32 chip_addr, + u32 chip_flags) +{ + struct adi_i2c_dev *dev = dev_get_priv(bus); + u8 byte; + + return adi_i2c_read(dev->base, chip_addr, NULL, 0, &byte, 1); +} + +static int adi_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) +{ + struct adi_i2c_dev *dev = dev_get_priv(bus); + struct i2c_msg *dmsg, *omsg, dummy; + + memset(&dummy, 0, sizeof(struct i2c_msg)); + + /* + * We expect either two messages (one with an offset and one with the + * actual data) or one message (just data) + */ + if (nmsgs > 2 || nmsgs == 0) { + debug("%s: Only one or two messages are supported.", __func__); + return -EINVAL; + } + + omsg = nmsgs == 1 ? &dummy : msg; + dmsg = nmsgs == 1 ? msg : msg + 1; + + if (dmsg->flags & I2C_M_RD) + return adi_i2c_read(dev->base, dmsg->addr, omsg->buf, omsg->len, + dmsg->buf, dmsg->len); + else + return adi_i2c_write(dev->base, dmsg->addr, omsg->buf, omsg->len, + dmsg->buf, dmsg->len); +} + +int adi_i2c_probe(struct udevice *bus) +{ + struct adi_i2c_dev *dev = dev_get_priv(bus); + struct twi_regs *twi = dev->base; + + u16 prescale = ((dev->i2c_clk / 1000 / 1000 + 5) / 10) & 0x7F; + + /* Set TWI internal clock as 10MHz */ + iowrite16(prescale, &twi->control); + + /* Set TWI interface clock as specified */ + adi_i2c_set_bus_speed(bus, dev->speed); + + /* Enable it */ + iowrite16(TWI_ENA | prescale, &twi->control); + + return 0; +} + +static const struct dm_i2c_ops adi_i2c_ops = { + .xfer = adi_i2c_xfer, + .probe_chip = adi_i2c_probe_chip, + .set_bus_speed = adi_i2c_set_bus_speed, +}; + +static const struct udevice_id adi_i2c_ids[] = { + { .compatible = "adi-i2c", }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(i2c_adi) = { + .name = "i2c_adi", + .id = UCLASS_I2C, + .of_match = adi_i2c_ids, + .probe = adi_i2c_probe, + .of_to_plat = adi_i2c_of_to_plat, + .priv_auto = sizeof(struct adi_i2c_dev), + .ops = &adi_i2c_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c index 22f61d12d38..edcdeee1e9a 100644 --- a/drivers/led/led-uclass.c +++ b/drivers/led/led-uclass.c @@ -273,8 +273,12 @@ static const char *led_get_function_name(struct udevice *dev) /* Now try to detect function label name */ func = dev_read_string(dev, "function"); cp = dev_read_u32(dev, "color", &color); - // prevent coverity scan error CID 541279: (TAINTED_SCALAR) - if (color < LED_COLOR_ID_WHITE || color >= LED_COLOR_ID_MAX) + /* + * prevent coverity scan error CID 541279: (TAINTED_SCALAR) + * only check the upper bound. No need to check the lower bound + * as color is from type u32 and never can be lower than 0. + */ + if (color >= LED_COLOR_ID_MAX) cp = -EINVAL; if (cp == 0 || func) { diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 4827834b4aa..ab56bd3939f 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -292,6 +292,15 @@ config MMC_DW_ROCKCHIP SD 3.0, SDIO 3.0 and MMC 4.5 and supports common eMMC chips as well as removeable SD and micro-SD cards. +config MMC_SDHCI_ADI + bool "ADI SD/MMC controller support" + depends on ARCH_SC5XX + depends on DM_MMC && OF_CONTROL + depends on MMC_SDHCI && MMC_SDHCI_ADMA + help + This enables support for the SD/MMC controller included in some Analog + Devices SC5XX Socs. + config MMC_DW_SOCFPGA bool "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" depends on ARCH_SOCFPGA diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 90e76f90769..94ed28ead71 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_MMC_SDHCI_MV) += mv_sdhci.o obj-$(CONFIG_MMC_SDHCI_NPCM) += npcm_sdhci.o obj-$(CONFIG_MMC_SDHCI_PIC32) += pic32_sdhci.o obj-$(CONFIG_MMC_SDHCI_ROCKCHIP) += rockchip_sdhci.o +obj-$(CONFIG_MMC_SDHCI_ADI) += adi_sdhci.o obj-$(CONFIG_MMC_SDHCI_S5P) += s5p_sdhci.o obj-$(CONFIG_MMC_SDHCI_SNPS) += snps_sdhci.o obj-$(CONFIG_MMC_SDHCI_STI) += sti_sdhci.o diff --git a/drivers/mmc/adi_sdhci.c b/drivers/mmc/adi_sdhci.c new file mode 100644 index 00000000000..65a22cefb71 --- /dev/null +++ b/drivers/mmc/adi_sdhci.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * + * Based on Rockchip's sdhci.c file + */ + +#include <clk.h> +#include <dm.h> +#include <malloc.h> +#include <sdhci.h> +#include <asm/cache.h> + +/* 400KHz is max freq for card ID etc. Use that as min */ +#define EMMC_MIN_FREQ 400000 + +/* Check if an operation crossed a boundary of size ADMA_BOUNDARY_ALIGN */ +#define ADMA_BOUNDARY_ALGN SZ_128M +#define BOUNDARY_OK(addr, len) \ + (((addr) | (ADMA_BOUNDARY_ALGN - 1)) == (((addr) + (len) - 1) | \ + (ADMA_BOUNDARY_ALGN - 1))) + +/* We split a descriptor for every crossing of the ADMA alignment boundary, + * so we need an additional descriptor for every expected crossing. + * As I understand it, the max expected transaction size is: + * CONFIG_SYS_MMC_MAX_BLK_COUNT * MMC_MAX_BLOCK_LEN + * + * With the way the SDHCI-ADMA driver is implemented, if ADMA_MAX_LEN was a + * clean power of two, we'd only ever need +1 descriptor as the first + * descriptor that got split would then bring the remaining DMA + * destination addresses into alignment. Unfortunately, it's currently + * hardcoded to a non-power-of-two value. + * + * If that ever becomes parameterized, ADMA max length can be set to + * 0x10000, and set this to 1. + */ +#define ADMA_POTENTIAL_CROSSINGS \ + DIV_ROUND_UP((CONFIG_SYS_MMC_MAX_BLK_COUNT * MMC_MAX_BLOCK_LEN), \ + ADMA_BOUNDARY_ALGN) +/* +1 descriptor for each crossing. + */ +#define ADMA_TABLE_EXTRA_SZ (ADMA_POTENTIAL_CROSSINGS * ADMA_DESC_LEN) + +struct adi_sdhc_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +void adi_dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc, + dma_addr_t addr, int len, bool end) +{ + int tmplen, offset; + + if (likely(!len || BOUNDARY_OK(addr, len))) { + sdhci_adma_write_desc(host, desc, addr, len, end); + return; + } + + offset = addr & (ADMA_BOUNDARY_ALGN - 1); + tmplen = ADMA_BOUNDARY_ALGN - offset; + sdhci_adma_write_desc(host, desc, addr, tmplen, false); + + addr += tmplen; + len -= tmplen; + sdhci_adma_write_desc(host, desc, addr, len, end); +} + +struct sdhci_ops adi_dwcmshc_sdhci_ops = { + .adma_write_desc = adi_dwcmshc_adma_write_desc, +}; + +static int adi_dwcmshc_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct adi_sdhc_plat *plat = dev_get_plat(dev); + struct sdhci_host *host = dev_get_priv(dev); + int max_frequency, ret; + struct clk clk; + + max_frequency = dev_read_u32_default(dev, "max-frequency", 0); + ret = clk_get_by_index(dev, 0, &clk); + + host->quirks = 0; + host->max_clk = max_frequency; + /* + * The sdhci-driver only supports 4bit and 8bit, as sdhci_setup_cfg + * doesn't allow us to clear MMC_MODE_4BIT. Consequently, we don't + * check for other bus-width values. + */ + if (host->bus_width == 8) + host->host_caps |= MMC_MODE_8BIT; + + host->mmc = &plat->mmc; + host->mmc->priv = host; + host->mmc->dev = dev; + upriv->mmc = host->mmc; + + host->ops = &adi_dwcmshc_sdhci_ops; + host->adma_desc_table = memalign(ARCH_DMA_MINALIGN, + ADMA_TABLE_SZ + ADMA_TABLE_EXTRA_SZ); + host->adma_addr = virt_to_phys(host->adma_desc_table); + + ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ); + if (ret) + return ret; + + return sdhci_probe(dev); +} + +static int adi_dwcmshc_sdhci_of_to_plat(struct udevice *dev) +{ + struct sdhci_host *host = dev_get_priv(dev); + + host->name = dev->name; + host->ioaddr = dev_read_addr_ptr(dev); + host->bus_width = dev_read_u32_default(dev, "bus-width", 4); + + return 0; +} + +static int adi_sdhci_bind(struct udevice *dev) +{ + struct adi_sdhc_plat *plat = dev_get_plat(dev); + + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +static const struct udevice_id adi_dwcmshc_sdhci_ids[] = { + { .compatible = "adi,dwc-sdhci" }, + { } +}; + +U_BOOT_DRIVER(adi_dwcmshc_sdhci_drv) = { + .name = "adi_sdhci", + .id = UCLASS_MMC, + .of_match = adi_dwcmshc_sdhci_ids, + .of_to_plat = adi_dwcmshc_sdhci_of_to_plat, + .ops = &sdhci_ops, + .bind = adi_sdhci_bind, + .probe = adi_dwcmshc_sdhci_probe, + .priv_auto = sizeof(struct sdhci_host), + .plat_auto = sizeof(struct adi_sdhc_plat), +}; diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 88094b81e7a..3f8edeb5093 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -208,7 +208,7 @@ int mtd_parse_partitions(struct mtd_info *parent, const char **_mtdparts, { struct mtd_partition partition = {}, *parts; const char *mtdparts = *_mtdparts; - uint64_t cur_off = 0, cur_sz = 0; + uint64_t cur_off = 0; int nparts = 0; int ret, idx; u64 sz; @@ -237,8 +237,7 @@ int mtd_parse_partitions(struct mtd_info *parent, const char **_mtdparts, return ret; if (parts[idx].size == MTD_SIZE_REMAINING) - parts[idx].size = parent->size - cur_sz; - cur_sz += parts[idx].size; + parts[idx].size = parent->size - parts[idx].offset; sz = parts[idx].size; if (sz < parent->writesize || do_div(sz, parent->writesize)) { diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1563404ca17..3db784faedd 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -237,6 +237,13 @@ config DWC_ETH_QOS Of Service) IP block. The IP supports many options for bus type, clocking/reset structure, and feature list. +config DWC_ETH_QOS_ADI + bool "Synopsys DWC Ethernet QOS device support for ADI SC59x-64 parts" + depends on DWC_ETH_QOS + help + The Synopsis Designware Ethernet QoS IP block with the specific + configuration used in the ADI ADSP-SC59X 64 bit SoCs + config DWC_ETH_QOS_IMX bool "Synopsys DWC Ethernet QOS device support for IMX" depends on DWC_ETH_QOS @@ -852,6 +859,7 @@ config RENESAS_ETHER_SWITCH config RENESAS_RAVB bool "Renesas Ethernet AVB MAC" depends on RCAR_64 + select BITBANGMII select PHYLIB select PHY_ETHERNET_ID help diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 80d70212971..d919d437c08 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_DM_ETH_PHY) += eth-phy-uclass.o obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o +obj-$(CONFIG_DWC_ETH_QOS_ADI) += dwc_eth_qos_adi.o obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o obj-$(CONFIG_DWC_ETH_QOS_INTEL) += dwc_eth_qos_intel.o obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 5a6e89c0575..0f93c25e3fe 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -227,9 +227,9 @@ static int dw_dm_mdio_init(const char *name, void *priv) #endif #if IS_ENABLED(CONFIG_BITBANGMII) && IS_ENABLED(CONFIG_DM_GPIO) -static int dw_eth_bb_mdio_active(struct bb_miiphy_bus *bus) +static int dw_eth_bb_mdio_active(struct mii_dev *miidev) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; struct gpio_desc *desc = &priv->mdio_gpio; desc->flags = 0; @@ -238,9 +238,9 @@ static int dw_eth_bb_mdio_active(struct bb_miiphy_bus *bus) return 0; } -static int dw_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) +static int dw_eth_bb_mdio_tristate(struct mii_dev *miidev) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; struct gpio_desc *desc = &priv->mdio_gpio; desc->flags = 0; @@ -249,9 +249,9 @@ static int dw_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) return 0; } -static int dw_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v) +static int dw_eth_bb_set_mdio(struct mii_dev *miidev, int v) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; if (v) dm_gpio_set_value(&priv->mdio_gpio, 1); @@ -261,18 +261,18 @@ static int dw_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v) return 0; } -static int dw_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) +static int dw_eth_bb_get_mdio(struct mii_dev *miidev, int *v) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; *v = dm_gpio_get_value(&priv->mdio_gpio); return 0; } -static int dw_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v) +static int dw_eth_bb_set_mdc(struct mii_dev *miidev, int v) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; if (v) dm_gpio_set_value(&priv->mdc_gpio, 1); @@ -282,28 +282,48 @@ static int dw_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v) return 0; } -static int dw_eth_bb_delay(struct bb_miiphy_bus *bus) +static int dw_eth_bb_delay(struct mii_dev *miidev) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; udelay(priv->bb_delay); return 0; } +static const struct bb_miiphy_bus_ops dw_eth_bb_miiphy_bus_ops = { + .mdio_active = dw_eth_bb_mdio_active, + .mdio_tristate = dw_eth_bb_mdio_tristate, + .set_mdio = dw_eth_bb_set_mdio, + .get_mdio = dw_eth_bb_get_mdio, + .set_mdc = dw_eth_bb_set_mdc, + .delay = dw_eth_bb_delay, +}; + +static int dw_bb_miiphy_read(struct mii_dev *miidev, int addr, + int devad, int reg) +{ + return bb_miiphy_read(miidev, &dw_eth_bb_miiphy_bus_ops, + addr, devad, reg); +} + +static int dw_bb_miiphy_write(struct mii_dev *miidev, int addr, + int devad, int reg, u16 value) +{ + return bb_miiphy_write(miidev, &dw_eth_bb_miiphy_bus_ops, + addr, devad, reg, value); +} + static int dw_bb_mdio_init(const char *name, struct udevice *dev) { struct dw_eth_dev *dwpriv = dev_get_priv(dev); - struct bb_miiphy_bus *bb_miiphy = bb_miiphy_alloc(); - struct mii_dev *bus; + struct mii_dev *bus = mdio_alloc(); int ret; - if (!bb_miiphy) { + if (!bus) { printf("Failed to allocate MDIO bus\n"); return -ENOMEM; } - bus = &bb_miiphy->mii; - debug("\n%s: use bitbang mii..\n", dev->name); ret = gpio_request_by_name(dev, "snps,mdc-gpio", 0, &dwpriv->mdc_gpio, @@ -325,21 +345,13 @@ static int dw_bb_mdio_init(const char *name, struct udevice *dev) dwpriv->dev = dev; snprintf(bus->name, sizeof(bus->name), "%s", name); - bus->read = bb_miiphy_read; - bus->write = bb_miiphy_write; + bus->read = dw_bb_miiphy_read; + bus->write = dw_bb_miiphy_write; #if CONFIG_IS_ENABLED(DM_GPIO) bus->reset = dw_mdio_reset; #endif bus->priv = dwpriv; - /* Copy the bus accessors and private data */ - bb_miiphy->mdio_active = dw_eth_bb_mdio_active; - bb_miiphy->mdio_tristate = dw_eth_bb_mdio_tristate; - bb_miiphy->set_mdio = dw_eth_bb_set_mdio; - bb_miiphy->get_mdio = dw_eth_bb_get_mdio; - bb_miiphy->set_mdc = dw_eth_bb_set_mdc; - bb_miiphy->delay = dw_eth_bb_delay; - return mdio_register(bus); } #endif @@ -840,7 +852,6 @@ int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); struct dw_eth_dev *priv = dev_get_priv(dev); - bool __maybe_unused bbmiiphy = false; phys_addr_t iobase = pdata->iobase; void *ioaddr; int ret, err; @@ -932,8 +943,7 @@ int designware_eth_probe(struct udevice *dev) priv->max_speed = pdata->max_speed; #if IS_ENABLED(CONFIG_BITBANGMII) && IS_ENABLED(CONFIG_DM_GPIO) - bbmiiphy = dev_read_bool(dev, "snps,bitbang-mii"); - if (bbmiiphy) { + if (dev_read_bool(dev, "snps,bitbang-mii")) { ret = dw_bb_mdio_init(dev->name, dev); if (ret) { err = ret; @@ -963,12 +973,7 @@ int designware_eth_probe(struct udevice *dev) /* continue here for cleanup if no PHY found */ err = ret; mdio_unregister(priv->bus); -#if IS_ENABLED(CONFIG_BITBANGMII) && IS_ENABLED(CONFIG_DM_GPIO) - if (bbmiiphy) - bb_miiphy_free(container_of(priv->bus, struct bb_miiphy_bus, mii)); - else -#endif - mdio_free(priv->bus); + mdio_free(priv->bus); mdio_err: #ifdef CONFIG_CLK diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 2279481d935..b4ec3614696 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1632,6 +1632,12 @@ static const struct udevice_id eqos_ids[] = { .data = (ulong)&eqos_jh7110_config }, #endif +#if IS_ENABLED(CONFIG_DWC_ETH_QOS_ADI) + { + .compatible = "adi,sc59x-dwmac-eqos", + .data = (ulong)&eqos_adi_config + }, +#endif { } }; diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h index 123f98d5d53..403e8203974 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -87,6 +87,7 @@ struct eqos_mac_regs { #define EQOS_MAC_MDIO_ADDRESS_CR_MASK GENMASK(11, 8) #define EQOS_MAC_MDIO_ADDRESS_CR_100_150 1 #define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2 +#define EQOS_MAC_MDIO_ADDRESS_CR_150_250 4 #define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5 #define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4) #define EQOS_MAC_MDIO_ADDRESS_GOC_MASK GENMASK(3, 2) @@ -301,3 +302,4 @@ extern struct eqos_config eqos_qcom_config; extern struct eqos_config eqos_stm32mp13_config; extern struct eqos_config eqos_stm32mp15_config; extern struct eqos_config eqos_jh7110_config; +extern struct eqos_config eqos_adi_config; diff --git a/drivers/net/dwc_eth_qos_adi.c b/drivers/net/dwc_eth_qos_adi.c new file mode 100644 index 00000000000..0e6a901e303 --- /dev/null +++ b/drivers/net/dwc_eth_qos_adi.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/** + * (C) Copyright 2024 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Author: Greg Malysa <greg.malysa@timesys.com> + * Additional Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + */ + +#include <clk.h> +#include <dm.h> +#include <net.h> +#include <phy.h> +#include <reset.h> +#include <linux/io.h> + +#include <asm/arch-adi/sc5xx/sc5xx.h> + +#include "dwc_eth_qos.h" + +static int eqos_start_resets_adi(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + + /* + * Settings need to latch with the DMA reset below. Currently only + * rgmii is supported but other phy interfaces may be supported in + * the future + */ + sc5xx_enable_rgmii(); + setbits_32(&eqos->dma_regs->mode, EQOS_DMA_MODE_SWR); + + return 0; +} + +static int eqos_probe_resources_adi(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + phy_interface_t interface; + int ret; + + ret = eqos_get_base_addr_dt(dev); + if (ret) { + pr_err("eqos_get_base_addr_dt failed: %d\n", ret); + return ret; + } + + interface = eqos->config->interface(dev); + if (interface == PHY_INTERFACE_MODE_NA) { + pr_err("Invalid PHY interface\n"); + return -EINVAL; + } + + return 0; +} + +/** + * rgmii tx clock rate is set to 125 MHz regardless of phy mode, and + * by default the internal clock is always connected to 125 MHz. According + * to the HRM it is invalid for this clock to have any other speed, so + * the hardware won't work anyway if this is wrong. + */ +static ulong eqos_get_tick_clk_rate_adi(struct udevice *dev) +{ + return 125 * 1000000; +} + +static int eqos_get_enetaddr_adi(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + + return eth_env_get_enetaddr("ethaddr", pdata->enetaddr); +} + +static struct eqos_ops eqos_adi_ops = { + .eqos_inval_desc = eqos_inval_desc_generic, + .eqos_flush_desc = eqos_flush_desc_generic, + .eqos_inval_buffer = eqos_inval_buffer_generic, + .eqos_flush_buffer = eqos_flush_buffer_generic, + .eqos_probe_resources = eqos_probe_resources_adi, + .eqos_remove_resources = eqos_null_ops, + .eqos_start_resets = eqos_start_resets_adi, + .eqos_stop_resets = eqos_null_ops, + .eqos_start_clks = eqos_null_ops, + .eqos_stop_clks = eqos_null_ops, + .eqos_calibrate_pads = eqos_null_ops, + .eqos_disable_calibration = eqos_null_ops, + .eqos_set_tx_clk_speed = eqos_null_ops, + .eqos_get_enetaddr = eqos_get_enetaddr_adi, + .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_adi, +}; + +struct eqos_config __maybe_unused eqos_adi_config = { + .reg_access_always_ok = true, + .mdio_wait = 20, + .swr_wait = 50, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_150_250, + .axi_bus_width = EQOS_AXI_WIDTH_32, + .interface = dev_read_phy_mode, + .ops = &eqos_adi_ops, +}; diff --git a/drivers/net/phy/miiphybb.c b/drivers/net/phy/miiphybb.c index 553af2c1032..76463da7299 100644 --- a/drivers/net/phy/miiphybb.c +++ b/drivers/net/phy/miiphybb.c @@ -14,40 +14,16 @@ #include <ioports.h> #include <ppc_asm.tmpl> -#include <malloc.h> #include <miiphy.h> #include <asm/global_data.h> -static inline struct bb_miiphy_bus *bb_miiphy_getbus(struct mii_dev *miidev) -{ - return container_of(miidev, struct bb_miiphy_bus, mii); -} - -struct bb_miiphy_bus *bb_miiphy_alloc(void) -{ - struct bb_miiphy_bus *bus; - - bus = malloc(sizeof(*bus)); - if (!bus) - return bus; - - mdio_init(&bus->mii); - - return bus; -} - -void bb_miiphy_free(struct bb_miiphy_bus *bus) -{ - free(bus); -} - /***************************************************************************** * * Utility to send the preamble, address, and register (common to read * and write). */ -static void miiphy_pre(struct bb_miiphy_bus *bus, char read, - unsigned char addr, unsigned char reg) +static void miiphy_pre(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops, + char read, unsigned char addr, unsigned char reg) { int j; @@ -59,62 +35,62 @@ static void miiphy_pre(struct bb_miiphy_bus *bus, char read, * but it is safer and will be much more robust. */ - bus->mdio_active(bus); - bus->set_mdio(bus, 1); + ops->mdio_active(miidev); + ops->set_mdio(miidev, 1); for (j = 0; j < 32; j++) { - bus->set_mdc(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); } /* send the start bit (01) and the read opcode (10) or write (10) */ - bus->set_mdc(bus, 0); - bus->set_mdio(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 0); - bus->set_mdio(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 0); - bus->set_mdio(bus, read); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 0); - bus->set_mdio(bus, !read); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, read); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, !read); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); /* send the PHY address */ for (j = 0; j < 5; j++) { - bus->set_mdc(bus, 0); + ops->set_mdc(miidev, 0); if ((addr & 0x10) == 0) { - bus->set_mdio(bus, 0); + ops->set_mdio(miidev, 0); } else { - bus->set_mdio(bus, 1); + ops->set_mdio(miidev, 1); } - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); addr <<= 1; } /* send the register address */ for (j = 0; j < 5; j++) { - bus->set_mdc(bus, 0); + ops->set_mdc(miidev, 0); if ((reg & 0x10) == 0) { - bus->set_mdio(bus, 0); + ops->set_mdio(miidev, 0); } else { - bus->set_mdio(bus, 1); + ops->set_mdio(miidev, 1); } - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); reg <<= 1; } } @@ -126,62 +102,57 @@ static void miiphy_pre(struct bb_miiphy_bus *bus, char read, * Returns: * 0 on success */ -int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg) +int bb_miiphy_read(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops, + int addr, int devad, int reg) { unsigned short rdreg; /* register working value */ int v; int j; /* counter */ - struct bb_miiphy_bus *bus; - bus = bb_miiphy_getbus(miidev); - if (bus == NULL) { - return -1; - } - - miiphy_pre (bus, 1, addr, reg); + miiphy_pre(miidev, ops, 1, addr, reg); /* tri-state our MDIO I/O pin so we can read */ - bus->set_mdc(bus, 0); - bus->mdio_tristate(bus); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->mdio_tristate(miidev); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); /* check the turnaround bit: the PHY should be driving it to zero */ - bus->get_mdio(bus, &v); + ops->get_mdio(miidev, &v); if (v != 0) { /* puts ("PHY didn't drive TA low\n"); */ for (j = 0; j < 32; j++) { - bus->set_mdc(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); } /* There is no PHY, return */ return -1; } - bus->set_mdc(bus, 0); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->delay(miidev); /* read 16 bits of register data, MSB first */ rdreg = 0; for (j = 0; j < 16; j++) { - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 1); + ops->delay(miidev); rdreg <<= 1; - bus->get_mdio(bus, &v); + ops->get_mdio(miidev, &v); rdreg |= (v & 0x1); - bus->set_mdc(bus, 0); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->delay(miidev); } - bus->set_mdc(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); debug("%s[%s](0x%x) @ 0x%x = 0x%04x\n", __func__, miidev->name, reg, addr, rdreg); @@ -195,54 +166,47 @@ int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg) * Returns: * 0 on success */ -int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg, - u16 value) +int bb_miiphy_write(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops, + int addr, int devad, int reg, u16 value) { - struct bb_miiphy_bus *bus; int j; /* counter */ - bus = bb_miiphy_getbus(miidev); - if (bus == NULL) { - /* Bus not found! */ - return -1; - } - - miiphy_pre (bus, 0, addr, reg); + miiphy_pre(miidev, ops, 0, addr, reg); /* send the turnaround (10) */ - bus->set_mdc(bus, 0); - bus->set_mdio(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 0); - bus->set_mdio(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); /* write 16 bits of register data, MSB first */ for (j = 0; j < 16; j++) { - bus->set_mdc(bus, 0); + ops->set_mdc(miidev, 0); if ((value & 0x00008000) == 0) { - bus->set_mdio(bus, 0); + ops->set_mdio(miidev, 0); } else { - bus->set_mdio(bus, 1); + ops->set_mdio(miidev, 1); } - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); value <<= 1; } /* * Tri-state the MDIO line. */ - bus->mdio_tristate(bus); - bus->set_mdc(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->mdio_tristate(miidev); + ops->set_mdc(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); return 0; } diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c index cb727ae9bc1..c39bef17b79 100644 --- a/drivers/net/ravb.c +++ b/drivers/net/ravb.c @@ -354,8 +354,15 @@ static int ravb_mac_init(struct ravb_priv *eth) /* Disable MAC Interrupt */ writel(0, eth->iobase + RAVB_REG_ECSIPR); - /* Recv frame limit set register */ - writel(RFLR_RFL_MIN, eth->iobase + RAVB_REG_RFLR); + /* + * Set receive frame length + * + * The length set here describes the frame from the destination address + * up to and including the CRC data. However only the frame data, + * excluding the CRC, are transferred to memory. To allow for the + * largest frames add the CRC length to the maximum Rx descriptor size. + */ + writel(RFLR_RFL_MIN + ETH_FCS_LEN, eth->iobase + RAVB_REG_RFLR); return 0; } @@ -491,27 +498,27 @@ static void ravb_stop(struct udevice *dev) } /* Bitbang MDIO access */ -static int ravb_bb_mdio_active(struct bb_miiphy_bus *bus) +static int ravb_bb_mdio_active(struct mii_dev *miidev) { - struct ravb_priv *eth = bus->priv; + struct ravb_priv *eth = miidev->priv; setbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MMD); return 0; } -static int ravb_bb_mdio_tristate(struct bb_miiphy_bus *bus) +static int ravb_bb_mdio_tristate(struct mii_dev *miidev) { - struct ravb_priv *eth = bus->priv; + struct ravb_priv *eth = miidev->priv; clrbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MMD); return 0; } -static int ravb_bb_set_mdio(struct bb_miiphy_bus *bus, int v) +static int ravb_bb_set_mdio(struct mii_dev *miidev, int v) { - struct ravb_priv *eth = bus->priv; + struct ravb_priv *eth = miidev->priv; if (v) setbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MDO); @@ -521,18 +528,18 @@ static int ravb_bb_set_mdio(struct bb_miiphy_bus *bus, int v) return 0; } -static int ravb_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) +static int ravb_bb_get_mdio(struct mii_dev *miidev, int *v) { - struct ravb_priv *eth = bus->priv; + struct ravb_priv *eth = miidev->priv; *v = (readl(eth->iobase + RAVB_REG_PIR) & PIR_MDI) >> 3; return 0; } -static int ravb_bb_set_mdc(struct bb_miiphy_bus *bus, int v) +static int ravb_bb_set_mdc(struct mii_dev *miidev, int v) { - struct ravb_priv *eth = bus->priv; + struct ravb_priv *eth = miidev->priv; if (v) setbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MDC); @@ -542,18 +549,40 @@ static int ravb_bb_set_mdc(struct bb_miiphy_bus *bus, int v) return 0; } -static int ravb_bb_delay(struct bb_miiphy_bus *bus) +static int ravb_bb_delay(struct mii_dev *miidev) { udelay(10); return 0; } +static const struct bb_miiphy_bus_ops ravb_bb_miiphy_bus_ops = { + .mdio_active = ravb_bb_mdio_active, + .mdio_tristate = ravb_bb_mdio_tristate, + .set_mdio = ravb_bb_set_mdio, + .get_mdio = ravb_bb_get_mdio, + .set_mdc = ravb_bb_set_mdc, + .delay = ravb_bb_delay, +}; + +static int ravb_bb_miiphy_read(struct mii_dev *miidev, int addr, + int devad, int reg) +{ + return bb_miiphy_read(miidev, &ravb_bb_miiphy_bus_ops, + addr, devad, reg); +} + +static int ravb_bb_miiphy_write(struct mii_dev *miidev, int addr, + int devad, int reg, u16 value) +{ + return bb_miiphy_write(miidev, &ravb_bb_miiphy_bus_ops, + addr, devad, reg, value); +} + static int ravb_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); struct ravb_priv *eth = dev_get_priv(dev); - struct bb_miiphy_bus *bb_miiphy; struct mii_dev *mdiodev; void __iomem *iobase; int ret; @@ -565,32 +594,22 @@ static int ravb_probe(struct udevice *dev) if (ret < 0) goto err_mdio_alloc; - bb_miiphy = bb_miiphy_alloc(); - if (!bb_miiphy) { + mdiodev = mdio_alloc(); + if (!mdiodev) { ret = -ENOMEM; goto err_mdio_alloc; } - mdiodev = &bb_miiphy->mii; - - mdiodev->read = bb_miiphy_read; - mdiodev->write = bb_miiphy_write; + mdiodev->read = ravb_bb_miiphy_read; + mdiodev->write = ravb_bb_miiphy_write; + mdiodev->priv = eth; snprintf(mdiodev->name, sizeof(mdiodev->name), dev->name); - /* Copy the bus accessors and private data */ - bb_miiphy->mdio_active = ravb_bb_mdio_active; - bb_miiphy->mdio_tristate = ravb_bb_mdio_tristate; - bb_miiphy->set_mdio = ravb_bb_set_mdio; - bb_miiphy->get_mdio = ravb_bb_get_mdio; - bb_miiphy->set_mdc = ravb_bb_set_mdc; - bb_miiphy->delay = ravb_bb_delay; - bb_miiphy->priv = eth; - ret = mdio_register(mdiodev); if (ret < 0) goto err_mdio_register; - eth->bus = &bb_miiphy->mii; + eth->bus = mdiodev; /* Bring up PHY */ ret = clk_enable_bulk(ð->clks); @@ -610,7 +629,7 @@ static int ravb_probe(struct udevice *dev) err_mdio_reset: clk_release_bulk(ð->clks); err_mdio_register: - bb_miiphy_free(bb_miiphy); + mdio_free(mdiodev); err_mdio_alloc: unmap_physmem(eth->iobase, MAP_NOCACHE); return ret; diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 83e48609224..f695a3a41d2 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -644,9 +644,9 @@ static void sh_ether_stop(struct udevice *dev) } /******* for bb_miiphy *******/ -static int sh_eth_bb_mdio_active(struct bb_miiphy_bus *bus) +static int sh_eth_bb_mdio_active(struct mii_dev *miidev) { - struct sh_eth_dev *eth = bus->priv; + struct sh_eth_dev *eth = miidev->priv; struct sh_eth_info *port_info = ð->port_info[eth->port]; sh_eth_write(port_info, sh_eth_read(port_info, PIR) | PIR_MMD, PIR); @@ -654,9 +654,9 @@ static int sh_eth_bb_mdio_active(struct bb_miiphy_bus *bus) return 0; } -static int sh_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) +static int sh_eth_bb_mdio_tristate(struct mii_dev *miidev) { - struct sh_eth_dev *eth = bus->priv; + struct sh_eth_dev *eth = miidev->priv; struct sh_eth_info *port_info = ð->port_info[eth->port]; sh_eth_write(port_info, sh_eth_read(port_info, PIR) & ~PIR_MMD, PIR); @@ -664,9 +664,9 @@ static int sh_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) return 0; } -static int sh_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v) +static int sh_eth_bb_set_mdio(struct mii_dev *miidev, int v) { - struct sh_eth_dev *eth = bus->priv; + struct sh_eth_dev *eth = miidev->priv; struct sh_eth_info *port_info = ð->port_info[eth->port]; if (v) @@ -679,9 +679,9 @@ static int sh_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v) return 0; } -static int sh_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) +static int sh_eth_bb_get_mdio(struct mii_dev *miidev, int *v) { - struct sh_eth_dev *eth = bus->priv; + struct sh_eth_dev *eth = miidev->priv; struct sh_eth_info *port_info = ð->port_info[eth->port]; *v = (sh_eth_read(port_info, PIR) & PIR_MDI) >> 3; @@ -689,9 +689,9 @@ static int sh_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) return 0; } -static int sh_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v) +static int sh_eth_bb_set_mdc(struct mii_dev *miidev, int v) { - struct sh_eth_dev *eth = bus->priv; + struct sh_eth_dev *eth = miidev->priv; struct sh_eth_info *port_info = ð->port_info[eth->port]; if (v) @@ -704,19 +704,41 @@ static int sh_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v) return 0; } -static int sh_eth_bb_delay(struct bb_miiphy_bus *bus) +static int sh_eth_bb_delay(struct mii_dev *miidev) { udelay(10); return 0; } +static const struct bb_miiphy_bus_ops sh_ether_bb_miiphy_bus_ops = { + .mdio_active = sh_eth_bb_mdio_active, + .mdio_tristate = sh_eth_bb_mdio_tristate, + .set_mdio = sh_eth_bb_set_mdio, + .get_mdio = sh_eth_bb_get_mdio, + .set_mdc = sh_eth_bb_set_mdc, + .delay = sh_eth_bb_delay, +}; + +static int sh_eth_bb_miiphy_read(struct mii_dev *miidev, int addr, + int devad, int reg) +{ + return bb_miiphy_read(miidev, &sh_ether_bb_miiphy_bus_ops, + addr, devad, reg); +} + +static int sh_eth_bb_miiphy_write(struct mii_dev *miidev, int addr, + int devad, int reg, u16 value) +{ + return bb_miiphy_write(miidev, &sh_ether_bb_miiphy_bus_ops, + addr, devad, reg, value); +} + static int sh_ether_probe(struct udevice *udev) { struct eth_pdata *pdata = dev_get_plat(udev); struct sh_ether_priv *priv = dev_get_priv(udev); struct sh_eth_dev *eth = &priv->shdev; - struct bb_miiphy_bus *bb_miiphy; struct mii_dev *mdiodev; int ret; @@ -727,32 +749,22 @@ static int sh_ether_probe(struct udevice *udev) if (ret < 0) return ret; #endif - bb_miiphy = bb_miiphy_alloc(); - if (!bb_miiphy) { + mdiodev = mdio_alloc(); + if (!mdiodev) { ret = -ENOMEM; return ret; } - mdiodev = &bb_miiphy->mii; - - mdiodev->read = bb_miiphy_read; - mdiodev->write = bb_miiphy_write; + mdiodev->read = sh_eth_bb_miiphy_read; + mdiodev->write = sh_eth_bb_miiphy_write; + mdiodev->priv = eth; snprintf(mdiodev->name, sizeof(mdiodev->name), udev->name); - /* Copy the bus accessors and private data */ - bb_miiphy->mdio_active = sh_eth_bb_mdio_active; - bb_miiphy->mdio_tristate = sh_eth_bb_mdio_tristate; - bb_miiphy->set_mdio = sh_eth_bb_set_mdio; - bb_miiphy->get_mdio = sh_eth_bb_get_mdio; - bb_miiphy->set_mdc = sh_eth_bb_set_mdc; - bb_miiphy->delay = sh_eth_bb_delay; - bb_miiphy->priv = eth; - ret = mdio_register(mdiodev); if (ret < 0) goto err_mdio_register; - priv->bus = &bb_miiphy->mii; + priv->bus = mdiodev; eth->port = CFG_SH_ETHER_USE_PORT; eth->port_info[eth->port].phy_addr = CFG_SH_ETHER_PHY_ADDR; @@ -782,7 +794,7 @@ err_phy_config: clk_disable(&priv->clk); #endif err_mdio_register: - bb_miiphy_free(bb_miiphy); + mdio_free(mdiodev); return ret; } diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 6481ee24a60..bd4ebdd745a 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -278,6 +278,24 @@ static int tsec_send(struct udevice *dev, void *packet, int length) return result; } +static int tsec_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct tsec_private *priv = (struct tsec_private *)dev_get_priv(dev); + u16 status; + + out_be16(&priv->rxbd[priv->rx_idx].length, 0); + + status = RXBD_EMPTY; + /* Set the wrap bit if this is the last element in the list */ + if ((priv->rx_idx + 1) == PKTBUFSRX) + status |= RXBD_WRAP; + out_be16(&priv->rxbd[priv->rx_idx].status, status); + + priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX; + + return 0; +} + static int tsec_recv(struct udevice *dev, int flags, uchar **packetp) { struct tsec_private *priv = (struct tsec_private *)dev_get_priv(dev); @@ -296,6 +314,9 @@ static int tsec_recv(struct udevice *dev, int flags, uchar **packetp) ret = length - 4; } else { printf("Got error %x\n", (status & RXBD_STATS)); + + /* Rearm the packet buffer */ + tsec_free_pkt(dev, NULL, 0); } } @@ -307,24 +328,6 @@ static int tsec_recv(struct udevice *dev, int flags, uchar **packetp) return ret; } -static int tsec_free_pkt(struct udevice *dev, uchar *packet, int length) -{ - struct tsec_private *priv = (struct tsec_private *)dev_get_priv(dev); - u16 status; - - out_be16(&priv->rxbd[priv->rx_idx].length, 0); - - status = RXBD_EMPTY; - /* Set the wrap bit if this is the last element in the list */ - if ((priv->rx_idx + 1) == PKTBUFSRX) - status |= RXBD_WRAP; - out_be16(&priv->rxbd[priv->rx_idx].status, status); - - priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX; - - return 0; -} - static void tsec_halt(struct udevice *dev) { struct tsec_private *priv; diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 90f81886445..e68e31a8227 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -107,7 +107,8 @@ static void dm_pciauto_setup_device(struct udevice *dev, } if (prefetch && - (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH)) + (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH) && + (found_mem64 || prefetch->bus_lower < 0x100000000ULL)) bar_res = prefetch; else bar_res = mem; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 6ee7dc1cce8..687fb339ea0 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -178,6 +178,14 @@ config PINCTRL_APPLE both the GPIO definitions and pin control functions for each available multiplex function. +config PINCTRL_ADI + bool "ADI pinctrl driver" + depends on DM && ARCH_SC5XX + help + This driver enables pinctrl support on SC5xx processors. This + driver covers only the pin configuration functionality, and + GPIO functionality is contained in the separate GPIO driver. + config PINCTRL_AR933X bool "QCA/Athores ar933x pin control driver" depends on DM && SOC_AR933X diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 634047a91f4..6deb6aaf6eb 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -3,6 +3,7 @@ obj-y += pinctrl-uclass.o obj-$(CONFIG_$(XPL_)PINCTRL_GENERIC) += pinctrl-generic.o +obj-$(CONFIG_PINCTRL_ADI) += pinctrl-adi-adsp.o obj-$(CONFIG_PINCTRL_APPLE) += pinctrl-apple.o obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o @@ -15,7 +16,6 @@ obj-$(CONFIG_ARCH_MTMIPS) += mtmips/ obj-$(CONFIG_ARCH_NPCM) += nuvoton/ obj-$(CONFIG_PINCTRL_QCOM) += qcom/ obj-$(CONFIG_ARCH_RENESAS) += renesas/ -obj-$(CONFIG_ARCH_RZN1) += renesas/ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/ obj-$(CONFIG_$(XPL_)PINCTRL_TEGRA) += tegra/ diff --git a/drivers/pinctrl/pinctrl-adi-adsp.c b/drivers/pinctrl/pinctrl-adi-adsp.c new file mode 100644 index 00000000000..debf434212d --- /dev/null +++ b/drivers/pinctrl/pinctrl-adi-adsp.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Author: Greg Malysa <greg.malysa@timesys.com> + * Additional Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * + * dm pinctrl implementation for ADI ADSP SoCs + * + */ + +#include <dm.h> +#include <dm/pinctrl.h> +#include <dm/device_compat.h> +#include <linux/bitops.h> +#include <linux/io.h> + +#define ADSP_PORT_MMIO_SIZE 0x80 +#define ADSP_PORT_PIN_SIZE 16 + +#define ADSP_PORT_PORT_MUX_BITS 2 +#define ADSP_PORT_PORT_MUX_MASK 0x03 +#define ADSP_PINCTRL_FUNCTION_COUNT 4 + +#define ADSP_PORT_REG_FER 0x00 +#define ADSP_PORT_REG_FER_SET 0x04 +#define ADSP_PORT_REG_FER_CLEAR 0x08 +#define ADSP_PORT_REG_DATA 0x0c +#define ADSP_PORT_REG_DATA_SET 0x10 +#define ADSP_PORT_REG_DATA_CLEAR 0x14 +#define ADSP_PORT_REG_DIR 0x18 +#define ADSP_PORT_REG_DIR_SET 0x1c +#define ADSP_PORT_REG_DIR_CLEAR 0x20 +#define ADSP_PORT_REG_INEN 0x24 +#define ADSP_PORT_REG_INEN_SET 0x28 +#define ADSP_PORT_REG_INEN_CLEAR 0x2c +#define ADSP_PORT_REG_PORT_MUX 0x30 +#define ADSP_PORT_REG_DATA_TGL 0x34 +#define ADSP_PORT_REG_POLAR 0x38 +#define ADSP_PORT_REG_POLAR_SET 0x3c +#define ADSP_PORT_REG_POLAR_CLEAR 0x40 +#define ADSP_PORT_REG_LOCK 0x44 +#define ADSP_PORT_REG_TRIG_TGL 0x48 + +struct adsp_pinctrl_priv { + void __iomem *base; + int npins; + char pinbuf[16]; +}; + +static u32 get_port(unsigned int pin) +{ + return pin / ADSP_PORT_PIN_SIZE; +} + +static u32 get_offset(unsigned int pin) +{ + return pin % ADSP_PORT_PIN_SIZE; +} + +static int adsp_pinctrl_pinmux_set(struct udevice *udev, unsigned int pin, unsigned int func) +{ + struct adsp_pinctrl_priv *priv = dev_get_priv(udev); + void __iomem *portbase; + u32 port, offset; + u32 val; + + if (pin >= priv->npins) + return -ENODEV; + + if (func >= ADSP_PINCTRL_FUNCTION_COUNT) + return -EINVAL; + + port = get_port(pin); + offset = get_offset(pin); + portbase = priv->base + port * ADSP_PORT_MMIO_SIZE; + + val = ioread32(portbase + ADSP_PORT_REG_PORT_MUX); + val &= ~(ADSP_PORT_PORT_MUX_MASK << (ADSP_PORT_PORT_MUX_BITS * offset)); + val |= func << (ADSP_PORT_PORT_MUX_BITS * offset); + iowrite32(val, portbase + ADSP_PORT_REG_PORT_MUX); + + iowrite32(BIT(offset), portbase + ADSP_PORT_REG_FER_SET); + return 0; +} + +static int adsp_pinctrl_set_state(struct udevice *udev, struct udevice *config) +{ + const struct fdt_property *pinlist; + int length = 0; + int ret, i; + u32 pin, function; + + pinlist = dev_read_prop(config, "adi,pins", &length); + if (!pinlist) { + dev_err(udev, "missing adi,pins property in pinctrl config node\n"); + return -EINVAL; + } + + if (length % (sizeof(uint32_t) * 2)) { + dev_err(udev, "adi,pins property must be a multiple of two uint32_ts\n"); + return -EINVAL; + } + + for (i = 0; i < length / sizeof(uint32_t); i += 2) { + ret = dev_read_u32_index(config, "adi,pins", i, &pin); + if (ret) + return ret; + + ret = dev_read_u32_index(config, "adi,pins", i + 1, &function); + if (ret) + return ret; + + ret = adsp_pinctrl_pinmux_set(udev, pin, function); + if (ret) + return ret; + } + + return 0; +} + +const struct pinctrl_ops adsp_pinctrl_ops = { + .set_state = adsp_pinctrl_set_state, +}; + +static int adsp_pinctrl_probe(struct udevice *udev) +{ + struct adsp_pinctrl_priv *priv = dev_get_priv(udev); + + priv->base = dev_read_addr_ptr(udev); + priv->npins = dev_read_u32_default(udev, "adi,npins", 0); + + if (!priv->base) { + dev_err(udev, "Missing or invalid pinctrl base address\n"); + return -ENOENT; + } + + if (!priv->npins) { + dev_err(udev, "Missing adi,npins property!\n"); + return -ENOENT; + } + + return 0; +} + +static const struct udevice_id adsp_pinctrl_match[] = { + { .compatible = "adi,adsp-pinctrl" }, + { }, +}; + +U_BOOT_DRIVER(adi_adsp_pinctrl) = { + .name = "adi_adsp_pinctrl", + .id = UCLASS_PINCTRL, + .of_match = adsp_pinctrl_match, + .probe = adsp_pinctrl_probe, + .priv_auto = sizeof(struct adsp_pinctrl_priv), + .ops = &adsp_pinctrl_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c b/drivers/pinctrl/qcom/pinctrl-sm8250.c index cab42fa64ed..b21cdc4d24b 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8250.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c @@ -107,7 +107,7 @@ static unsigned int sm8250_get_function_mux(__maybe_unused unsigned int pin, uns static struct msm_pinctrl_data sm8250_data = { .pin_data = { .pin_offsets = sm8250_pin_offsets, - .pin_count = ARRAY_SIZE(sm8250_pin_offsets), + .pin_count = 184, .special_pins_start = 180, .special_pins_data = sm8250_special_pins_data, }, diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index ad7112a05e6..e6b957f5537 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -67,6 +67,58 @@ exit: kfree(drive_group); } +#ifdef TEGRA_PMX_SOC_HAS_MIPI_PAD_CTRL_GRPS +static void tegra_pinctrl_set_mipipad(struct udevice *config, int padcnt) +{ + struct pmux_mipipadctrlgrp_config *mipipad_group; + int i, ret, pad_id; + const char *function; + const char **pads; + + mipipad_group = kmalloc_array(padcnt, sizeof(*mipipad_group), GFP_KERNEL); + if (!mipipad_group) { + log_debug("%s: cannot allocate mipi pad group array\n", __func__); + return; + } + + /* decode function id and fill the first copy of pmux_mipipadctrlgrp_config */ + function = dev_read_string(config, "nvidia,function"); + if (function) + for (i = 0; i < PMUX_FUNC_COUNT; i++) + if (tegra_pinctrl_to_func[i]) + if (!strcmp(function, tegra_pinctrl_to_func[i])) + break; + + mipipad_group[0].func = i; + + for (i = 1; i < padcnt; i++) + memcpy(&mipipad_group[i], &mipipad_group[0], sizeof(mipipad_group[0])); + + ret = dev_read_string_list(config, "nvidia,pins", &pads); + if (ret < 0) { + log_debug("%s: could not parse property nvidia,pins\n", __func__); + goto exit; + } + + for (i = 0; i < padcnt; i++) { + for (pad_id = 0; pad_id < PMUX_MIPIPADCTRLGRP_COUNT; pad_id++) + if (tegra_pinctrl_to_mipipadgrp[pad_id]) + if (!strcmp(pads[i], tegra_pinctrl_to_mipipadgrp[pad_id])) { + mipipad_group[i].grp = pad_id; + break; + } + } + + pinmux_config_mipipadctrlgrp_table(mipipad_group, padcnt); + + free(pads); +exit: + kfree(mipipad_group); +} +#else +static void tegra_pinctrl_set_mipipad(struct udevice *config, int padcnt) { } +#endif + static void tegra_pinctrl_set_pin(struct udevice *config, int pincnt) { struct pmux_pingrp_config *pinmux_group; @@ -170,6 +222,9 @@ static int tegra_pinctrl_set_state(struct udevice *dev, struct udevice *config) if (!strncmp(name, "drive_", 6)) /* Drive node is detected */ tegra_pinctrl_set_drive(child, ret); + else if (!strncmp(name, "mipi_pad_ctrl_", 14)) + /* Handle T124 specific pinconfig */ + tegra_pinctrl_set_mipipad(child, ret); else /* Pin node is detected */ tegra_pinctrl_set_pin(child, ret); @@ -236,6 +291,7 @@ static int tegra_pinctrl_bind(struct udevice *dev) static const struct udevice_id tegra_pinctrl_ids[] = { { .compatible = "nvidia,tegra30-pinmux" }, { .compatible = "nvidia,tegra114-pinmux" }, + { .compatible = "nvidia,tegra124-pinmux" }, { }, }; diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c b/drivers/power/regulator/qcom-rpmh-regulator.c index 70df51b5fa4..cd2b1a654c1 100644 --- a/drivers/power/regulator/qcom-rpmh-regulator.c +++ b/drivers/power/regulator/qcom-rpmh-regulator.c @@ -481,6 +481,13 @@ static const struct rpmh_vreg_init_data pm8150_vreg_data[] = { static const struct rpmh_vreg_init_data pm8150l_vreg_data[] = { RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo_lv, "vdd-l1-l8"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l11"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l1-l8"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l9-l10"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l9-l10"), RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l7-l11"), {} }; diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 6e79868d0ef..de312656746 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -105,6 +105,14 @@ config PWM_TEGRA 32KHz clock is supported by the driver but the duty cycle is configurable. +config PWM_STM32 + bool "Enable support for STM32 PWM" + depends on DM_PWM && MFD_STM32_TIMERS + help + This enables PWM driver for STMicroelectronics STM32 pulse width + modulation. It uses STM32 timer devices that can have up to 4 output + channels, with complementary outputs and configurable polarity. + config PWM_SUNXI bool "Enable support for the Allwinner Sunxi PWM" depends on DM_PWM diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index e4d10c8dc3e..76305b93bc9 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -22,5 +22,6 @@ obj-$(CONFIG_PWM_ROCKCHIP) += rk_pwm.o obj-$(CONFIG_PWM_SANDBOX) += sandbox_pwm.o obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o obj-$(CONFIG_PWM_TEGRA) += tegra_pwm.o +obj-$(CONFIG_PWM_STM32) += pwm-stm32.o obj-$(CONFIG_PWM_SUNXI) += sunxi_pwm.o obj-$(CONFIG_PWM_TI_EHRPWM) += pwm-ti-ehrpwm.o diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c new file mode 100644 index 00000000000..5fa649b5903 --- /dev/null +++ b/drivers/pwm/pwm-stm32.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025, STMicroelectronics - All Rights Reserved + * Author: Cheick Traore <cheick.traore@foss.st.com> + * + * Originally based on the Linux kernel v6.10 drivers/pwm/pwm-stm32.c. + */ + +#include <div64.h> +#include <dm.h> +#include <pwm.h> +#include <asm/io.h> +#include <asm/arch/timers.h> +#include <dm/device_compat.h> +#include <linux/time.h> + +#define CCMR_CHANNEL_SHIFT 8 +#define CCMR_CHANNEL_MASK 0xFF + +struct stm32_pwm_priv { + bool have_complementary_output; + bool invert_polarity; +}; + +static u32 active_channels(struct stm32_timers_plat *plat) +{ + return readl(plat->base + TIM_CCER) & TIM_CCER_CCXE; +} + +static int stm32_pwm_set_config(struct udevice *dev, uint channel, + uint period_ns, uint duty_ns) +{ + struct stm32_timers_plat *plat = dev_get_plat(dev_get_parent(dev)); + struct stm32_timers_priv *priv = dev_get_priv(dev_get_parent(dev)); + unsigned long long prd, div, dty; + unsigned int prescaler = 0; + u32 ccmr, mask, shift; + + if (duty_ns > period_ns) + return -EINVAL; + + /* + * Period and prescaler values depends on clock rate + * First we need to find the minimal value for prescaler such that + * + * period_ns * clkrate + * ------------------------------ < max_arr + 1 + * NSEC_PER_SEC * (prescaler + 1) + * + * This equation is equivalent to + * + * period_ns * clkrate + * ---------------------------- < prescaler + 1 + * NSEC_PER_SEC * (max_arr + 1) + * + * Using integer division and knowing that the right hand side is + * integer, this is further equivalent to + * + * (period_ns * clkrate) // (NSEC_PER_SEC * (max_arr + 1)) ≤ prescaler + */ + + div = (unsigned long long)priv->rate * period_ns; + do_div(div, NSEC_PER_SEC); + prd = div; + + do_div(div, priv->max_arr + 1); + prescaler = div; + if (prescaler > MAX_TIM_PSC) + return -EINVAL; + + do_div(prd, prescaler + 1); + if (!prd) + return -EINVAL; + + /* + * All channels share the same prescaler and counter so when two + * channels are active at the same time we can't change them + */ + if (active_channels(plat) & ~(1 << channel * 4)) { + u32 psc, arr; + + psc = readl(plat->base + TIM_PSC); + arr = readl(plat->base + TIM_ARR); + if (psc != prescaler || arr != prd - 1) + return -EBUSY; + } + + writel(prescaler, plat->base + TIM_PSC); + writel(prd - 1, plat->base + TIM_ARR); + setbits_le32(plat->base + TIM_CR1, TIM_CR1_ARPE); + + /* Calculate the duty cycles */ + dty = prd * duty_ns; + do_div(dty, period_ns); + + writel(dty, plat->base + TIM_CCRx(channel + 1)); + + /* Configure output mode */ + shift = (channel & 0x1) * CCMR_CHANNEL_SHIFT; + ccmr = (TIM_CCMR_PE | TIM_CCMR_M1) << shift; + mask = CCMR_CHANNEL_MASK << shift; + if (channel < 2) + clrsetbits_le32(plat->base + TIM_CCMR1, mask, ccmr); + else + clrsetbits_le32(plat->base + TIM_CCMR2, mask, ccmr); + + setbits_le32(plat->base + TIM_BDTR, TIM_BDTR_MOE); + + return 0; +} + +static int stm32_pwm_set_enable(struct udevice *dev, uint channel, + bool enable) +{ + struct stm32_timers_plat *plat = dev_get_plat(dev_get_parent(dev)); + struct stm32_pwm_priv *priv = dev_get_priv(dev); + u32 mask; + + /* Enable channel */ + mask = TIM_CCER_CC1E << (channel * 4); + if (priv->have_complementary_output) + mask |= TIM_CCER_CC1NE << (channel * 4); + + if (enable) { + setbits_le32(plat->base + TIM_CCER, mask); + /* Make sure that registers are updated */ + setbits_le32(plat->base + TIM_EGR, TIM_EGR_UG); + /* Enable controller */ + setbits_le32(plat->base + TIM_CR1, TIM_CR1_CEN); + } else { + clrbits_le32(plat->base + TIM_CCER, mask); + /* When all channels are disabled, we can disable the controller */ + if (!active_channels(plat)) + clrbits_le32(plat->base + TIM_CR1, TIM_CR1_CEN); + } + + return 0; +} + +static int stm32_pwm_set_invert(struct udevice *dev, uint channel, + bool polarity) +{ + struct stm32_timers_plat *plat = dev_get_plat(dev_get_parent(dev)); + struct stm32_pwm_priv *priv = dev_get_priv(dev); + u32 mask; + + mask = TIM_CCER_CC1P << (channel * 4); + if (priv->have_complementary_output) + mask |= TIM_CCER_CC1NP << (channel * 4); + + clrsetbits_le32(plat->base + TIM_CCER, mask, polarity ? mask : 0); + + return 0; +} + +static void stm32_pwm_detect_complementary(struct udevice *dev) +{ + struct stm32_timers_plat *plat = dev_get_plat(dev_get_parent(dev)); + struct stm32_pwm_priv *priv = dev_get_priv(dev); + u32 ccer; + + /* + * If complementary bit doesn't exist writing 1 will have no + * effect so we can detect it. + */ + setbits_le32(plat->base + TIM_CCER, TIM_CCER_CC1NE); + ccer = readl(plat->base + TIM_CCER); + clrbits_le32(plat->base + TIM_CCER, TIM_CCER_CC1NE); + + priv->have_complementary_output = (ccer != 0); +} + +static int stm32_pwm_probe(struct udevice *dev) +{ + struct stm32_timers_priv *timer = dev_get_priv(dev_get_parent(dev)); + + if (timer->rate > 1000000000) { + dev_err(dev, "Clock freq too high (%lu)\n", timer->rate); + return -EINVAL; + } + + stm32_pwm_detect_complementary(dev); + + return 0; +} + +static const struct pwm_ops stm32_pwm_ops = { + .set_config = stm32_pwm_set_config, + .set_enable = stm32_pwm_set_enable, + .set_invert = stm32_pwm_set_invert, +}; + +static const struct udevice_id stm32_pwm_ids[] = { + { .compatible = "st,stm32-pwm" }, + { } +}; + +U_BOOT_DRIVER(stm32_pwm) = { + .name = "stm32_pwm", + .id = UCLASS_PWM, + .of_match = stm32_pwm_ids, + .ops = &stm32_pwm_ops, + .probe = stm32_pwm_probe, + .priv_auto = sizeof(struct stm32_pwm_priv), +}; diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 3d2831a3e36..a3ecea05e20 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -13,6 +13,7 @@ config REMOTEPROC depends on DM # Please keep the configuration alphabetically sorted. + config K3_SYSTEM_CONTROLLER bool "Support for TI' K3 System Controller" select REMOTEPROC @@ -22,6 +23,16 @@ config K3_SYSTEM_CONTROLLER help Say 'y' here to add support for TI' K3 System Controller. +config REMOTEPROC_ADI_SC5XX + bool "Support for ADI SC5xx SHARC cores" + select REMOTEPROC + depends on DM + depends on ARCH_SC5XX + depends on SYSCON + help + Say 'y' here to add support for loading code onto SHARC cores in + an ADSP-SC5xx SoC from Analog Devices + config REMOTEPROC_RENESAS_APMU bool "Support for Renesas R-Car Gen4 APMU start of CR52 processor" select REMOTEPROC diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index f81e5009c5e..bd94ea771be 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_$(XPL_)REMOTEPROC) += rproc-uclass.o rproc-elf-loader.o # Remote proc drivers - Please keep this list alphabetically sorted. obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o +obj-$(CONFIG_REMOTEPROC_ADI_SC5XX) += adi_sc5xx_rproc.o obj-$(CONFIG_REMOTEPROC_RENESAS_APMU) += renesas_apmu.o obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o diff --git a/drivers/remoteproc/adi_sc5xx_rproc.c b/drivers/remoteproc/adi_sc5xx_rproc.c new file mode 100644 index 00000000000..86acd1b98c7 --- /dev/null +++ b/drivers/remoteproc/adi_sc5xx_rproc.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * + * Analog Devices SC5xx remoteproc driver for loading code onto SHARC cores + */ + +#include <dm.h> +#include <regmap.h> +#include <remoteproc.h> +#include <syscon.h> +#include <dm/device_compat.h> +#include <linux/delay.h> +#include <linux/io.h> + +/* Register offsets */ +#ifdef CONFIG_SC58X +#define ADI_RCU_REG_CTL 0x00 +#define ADI_RCU_REG_STAT 0x04 +#define ADI_RCU_REG_CRCTL 0x08 +#define ADI_RCU_REG_CRSTAT 0x0c +#define ADI_RCU_REG_SIDIS 0x10 +#define ADI_RCU_REG_SISTAT 0x14 +#define ADI_RCU_REG_BCODE 0x1c +#define ADI_RCU_REG_SVECT0 0x20 +#define ADI_RCU_REG_SVECT1 0x24 +#define ADI_RCU_REG_SVECT2 0x28 +#define ADI_RCU_REG_MSG 0x60 +#define ADI_RCU_REG_MSG_SET 0x64 +#define ADI_RCU_REG_MSG_CLR 0x68 +#else +#define ADI_RCU_REG_CTL 0x00 +#define ADI_RCU_REG_STAT 0x04 +#define ADI_RCU_REG_CRCTL 0x08 +#define ADI_RCU_REG_CRSTAT 0x0c +#define ADI_RCU_REG_SRRQSTAT 0x18 +#define ADI_RCU_REG_SIDIS 0x1c +#define ADI_RCU_REG_SISTAT 0x20 +#define ADI_RCU_REG_SVECT_LCK 0x24 +#define ADI_RCU_REG_BCODE 0x28 +#define ADI_RCU_REG_SVECT0 0x2c +#define ADI_RCU_REG_SVECT1 0x30 +#define ADI_RCU_REG_SVECT2 0x34 +#define ADI_RCU_REG_MSG 0x6c +#define ADI_RCU_REG_MSG_SET 0x70 +#define ADI_RCU_REG_MSG_CLR 0x74 +#endif /* CONFIG_SC58X */ + +/* Register bit definitions */ +#define ADI_RCU_CTL_SYSRST BIT(0) + +/* Bit values for the RCU0_MSG register */ +#define RCU0_MSG_C0IDLE 0x00000100 /* Core 0 Idle */ +#define RCU0_MSG_C1IDLE 0x00000200 /* Core 1 Idle */ +#define RCU0_MSG_C2IDLE 0x00000400 /* Core 2 Idle */ +#define RCU0_MSG_CRR0 0x00001000 /* Core 0 reset request */ +#define RCU0_MSG_CRR1 0x00002000 /* Core 1 reset request */ +#define RCU0_MSG_CRR2 0x00004000 /* Core 2 reset request */ +#define RCU0_MSG_C1ACTIVATE 0x00080000 /* Core 1 Activated */ +#define RCU0_MSG_C2ACTIVATE 0x00100000 /* Core 2 Activated */ + +struct sc5xx_rproc_data { + /* Address to load to svect when rebooting core */ + u32 load_addr; + + /* RCU parameters */ + struct regmap *rcu; + u32 svect_offset; + u32 coreid; +}; + +struct block_code_flag { + u32 bcode:4, /* 0-3 */ + bflag_save:1, /* 4 */ + bflag_aux:1, /* 5 */ + breserved:1, /* 6 */ + bflag_forward:1, /* 7 */ + bflag_fill:1, /* 8 */ + bflag_quickboot:1, /* 9 */ + bflag_callback:1, /* 10 */ + bflag_init:1, /* 11 */ + bflag_ignore:1, /* 12 */ + bflag_indirect:1, /* 13 */ + bflag_first:1, /* 14 */ + bflag_final:1, /* 15 */ + bhdrchk:8, /* 16-23 */ + bhdrsign:8; /* 0xAD, 0xAC or 0xAB */ +}; + +struct ldr_hdr { + struct block_code_flag bcode_flag; + u32 target_addr; + u32 byte_count; + u32 argument; +}; + +static int is_final(struct ldr_hdr *hdr) +{ + return hdr->bcode_flag.bflag_final; +} + +static int is_empty(struct ldr_hdr *hdr) +{ + return hdr->bcode_flag.bflag_ignore || (hdr->byte_count == 0); +} + +static int adi_valid_firmware(struct ldr_hdr *adi_ldr_hdr) +{ + if (!adi_ldr_hdr->byte_count && + (adi_ldr_hdr->bcode_flag.bhdrsign == 0xAD || + adi_ldr_hdr->bcode_flag.bhdrsign == 0xAC || + adi_ldr_hdr->bcode_flag.bhdrsign == 0xAB)) + return 1; + + return 0; +} + +static int sharc_load(struct udevice *dev, ulong addr, ulong size) +{ + struct sc5xx_rproc_data *priv = dev_get_priv(dev); + size_t offset; + u8 *buf = (u8 *)addr; + struct ldr_hdr *ldr = (struct ldr_hdr *)addr; + struct ldr_hdr *block_hdr; + struct ldr_hdr *next_hdr; + + if (!adi_valid_firmware(ldr)) { + dev_err(dev, "Firmware at 0x%lx does not appear to be an LDR image\n", addr); + dev_err(dev, "Note: Signed firmware is not currently supported\n"); + return -EINVAL; + } + + do { + block_hdr = (struct ldr_hdr *)buf; + offset = sizeof(struct ldr_hdr) + (block_hdr->bcode_flag.bflag_fill ? + 0 : block_hdr->byte_count); + next_hdr = (struct ldr_hdr *)(buf + offset); + + if (block_hdr->bcode_flag.bflag_first) + priv->load_addr = (unsigned long)block_hdr->target_addr; + + if (!is_empty(block_hdr)) { + if (block_hdr->bcode_flag.bflag_fill) { + memset_io((void *)(phys_addr_t)block_hdr->target_addr, + block_hdr->argument, + block_hdr->byte_count); + } else { + memcpy_toio((void *)(phys_addr_t)block_hdr->target_addr, + buf + sizeof(struct ldr_hdr), + block_hdr->byte_count); + } + } + + if (is_final(block_hdr)) + break; + + buf += offset; + } while (1); + + return 0; +} + +static void sharc_reset(struct sc5xx_rproc_data *priv) +{ + u32 coreid = priv->coreid; + u32 val; + + /* First put core in reset. + * Clear CRSTAT bit for given coreid. + */ + regmap_write(priv->rcu, ADI_RCU_REG_CRSTAT, 1 << coreid); + + /* Set SIDIS to disable the system interface */ + regmap_read(priv->rcu, ADI_RCU_REG_SIDIS, &val); + regmap_write(priv->rcu, ADI_RCU_REG_SIDIS, val | (1 << (coreid - 1))); + + /* + * Wait for access to coreX have been disabled and all the pending + * transactions have completed + */ + udelay(50); + + /* Set CRCTL bit to put core in reset */ + regmap_read(priv->rcu, ADI_RCU_REG_CRCTL, &val); + regmap_write(priv->rcu, ADI_RCU_REG_CRCTL, val | (1 << coreid)); + + /* Poll until Core is in reset */ + while (!(regmap_read(priv->rcu, ADI_RCU_REG_CRSTAT, &val), val & (1 << coreid))) + ; + + /* Clear SIDIS to reenable the system interface */ + regmap_read(priv->rcu, ADI_RCU_REG_SIDIS, &val); + regmap_write(priv->rcu, ADI_RCU_REG_SIDIS, val & ~(1 << (coreid - 1))); + + udelay(50); + + /* Take Core out of reset */ + regmap_read(priv->rcu, ADI_RCU_REG_CRCTL, &val); + regmap_write(priv->rcu, ADI_RCU_REG_CRCTL, val & ~(1 << coreid)); + + /* Wait for done */ + udelay(50); +} + +static int sharc_start(struct udevice *dev) +{ + struct sc5xx_rproc_data *priv = dev_get_priv(dev); + + /* Write load address to appropriate SVECT for core */ + regmap_write(priv->rcu, priv->svect_offset, priv->load_addr); + + sharc_reset(priv); + + /* Clear the IDLE bit when start the SHARC core */ + regmap_write(priv->rcu, ADI_RCU_REG_MSG_CLR, RCU0_MSG_C0IDLE << priv->coreid); + + /* Notify CCES */ + regmap_write(priv->rcu, ADI_RCU_REG_MSG_SET, RCU0_MSG_C1ACTIVATE << (priv->coreid - 1)); + return 0; +} + +static const struct dm_rproc_ops sc5xx_ops = { + .load = sharc_load, + .start = sharc_start, +}; + +static int sc5xx_probe(struct udevice *dev) +{ + struct sc5xx_rproc_data *priv = dev_get_priv(dev); + u32 coreid; + + if (dev_read_u32(dev, "coreid", &coreid)) { + dev_err(dev, "Missing property coreid\n"); + return -ENOENT; + } + + priv->coreid = coreid; + switch (coreid) { + case 1: + priv->svect_offset = ADI_RCU_REG_SVECT1; + break; + case 2: + priv->svect_offset = ADI_RCU_REG_SVECT2; + break; + default: + dev_err(dev, "Invalid value %d for coreid, must be 1 or 2\n", coreid); + return -EINVAL; + } + + priv->rcu = syscon_regmap_lookup_by_phandle(dev, "adi,rcu"); + if (IS_ERR(priv->rcu)) + return PTR_ERR(priv->rcu); + + dev_err(dev, "sc5xx remoteproc core %d available\n", priv->coreid); + + return 0; +} + +static const struct udevice_id sc5xx_ids[] = { + { .compatible = "adi,sc5xx-rproc" }, + { } +}; + +U_BOOT_DRIVER(adi_sc5xx_rproc) = { + .name = "adi_sc5xx_rproc", + .of_match = sc5xx_ids, + .id = UCLASS_REMOTEPROC, + .ops = &sc5xx_ops, + .probe = sc5xx_probe, + .priv_auto = sizeof(struct sc5xx_rproc_data), + .flags = 0, +}; diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index ebe692a9963..2ef8ba20cf5 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -63,7 +63,4 @@ obj-$(CONFIG_XEN_SERIAL) += serial_xen.o obj-$(CONFIG_XTENSA_SEMIHOSTING_SERIAL) += serial_xtensa_semihosting.o obj-$(CONFIG_S5P4418_PL011_SERIAL) += serial_s5p4418_pl011.o -ifndef CONFIG_XPL_BUILD -obj-$(CONFIG_USB_TTY) += usbtty.o -endif obj-$(CONFIG_UART4_SERIAL) += serial_adi_uart4.o diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 0e267d097c5..4f7de3ea215 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -112,9 +112,9 @@ static void serial_out_dynamic(struct ns16550_plat *plat, u8 *addr, } else if (plat->reg_width == 4) { if (plat->flags & NS16550_FLAG_ENDIAN) { if (plat->flags & NS16550_FLAG_BE) - out_be32(addr, value); + out_be32((u32 *)addr, value); else - out_le32(addr, value); + out_le32((u32 *)addr, value); } else { writel(value, addr); } @@ -132,9 +132,9 @@ static int serial_in_dynamic(struct ns16550_plat *plat, u8 *addr) } else if (plat->reg_width == 4) { if (plat->flags & NS16550_FLAG_ENDIAN) { if (plat->flags & NS16550_FLAG_BE) - return in_be32(addr); + return in_be32((u32 *)addr); else - return in_le32(addr); + return in_le32((u32 *)addr); } else { return readl(addr); } @@ -294,13 +294,9 @@ void ns16550_putc(struct ns16550 *com_port, char c) #if !CONFIG_IS_ENABLED(NS16550_MIN_FUNCTIONS) char ns16550_getc(struct ns16550 *com_port) { - while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) { -#if !defined(CONFIG_XPL_BUILD) && defined(CONFIG_USB_TTY) - extern void usbtty_poll(void); - usbtty_poll(); -#endif + while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) schedule(); - } + return serial_in(&com_port->rbr); } diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c index 1ee58142b3f..1675a9cb9d1 100644 --- a/drivers/serial/serial_stm32.c +++ b/drivers/serial/serial_stm32.c @@ -299,13 +299,19 @@ static inline struct stm32_uart_info *_debug_uart_info(void) static inline void _debug_uart_init(void) { - void __iomem *base = (void __iomem *)CONFIG_VAL(DEBUG_UART_BASE); - struct stm32_uart_info *uart_info = _debug_uart_info(); + void __maybe_unused __iomem *base = (void __iomem *)CONFIG_VAL(DEBUG_UART_BASE); + struct stm32_uart_info *uart_info __maybe_unused = _debug_uart_info(); - _stm32_serial_init(base, uart_info); - _stm32_serial_setbrg(base, uart_info, - CONFIG_DEBUG_UART_CLOCK, - CONFIG_BAUDRATE); + /* + * debug_uart_init() is only usable when SPL_BUILD is enabled + * (STM32MP1 case only) + */ + if (IS_ENABLED(CONFIG_DEBUG_UART) && IS_ENABLED(CONFIG_SPL_BUILD)) { + _stm32_serial_init(base, uart_info); + _stm32_serial_setbrg(base, uart_info, + CONFIG_DEBUG_UART_CLOCK, + CONFIG_BAUDRATE); + } } static inline void _debug_uart_putc(int c) diff --git a/drivers/serial/usbtty.c b/drivers/serial/usbtty.c deleted file mode 100644 index b7d77fbb6a9..00000000000 --- a/drivers/serial/usbtty.c +++ /dev/null @@ -1,983 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * (C) Copyright 2006 - * Bryan O'Donoghue, bodonoghue@codehermit.ie - */ - -#include <config.h> -#include <circbuf.h> -#include <env.h> -#include <serial.h> -#include <stdio_dev.h> -#include <asm/unaligned.h> -#include "usbtty.h" -#include "usb_cdc_acm.h" -#include "usbdescriptors.h" - -#ifdef DEBUG -#define TTYDBG(fmt,args...)\ - serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args) -#else -#define TTYDBG(fmt,args...) do{}while(0) -#endif - -#if 1 -#define TTYERR(fmt,args...)\ - serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,\ - __LINE__,##args) -#else -#define TTYERR(fmt,args...) do{}while(0) -#endif - -/* - * Defines - */ -#define NUM_CONFIGS 1 -#define MAX_INTERFACES 2 -#define NUM_ENDPOINTS 3 -#define ACM_TX_ENDPOINT 3 -#define ACM_RX_ENDPOINT 2 -#define GSERIAL_TX_ENDPOINT 2 -#define GSERIAL_RX_ENDPOINT 1 -#define NUM_ACM_INTERFACES 2 -#define NUM_GSERIAL_INTERFACES 1 -#define CFG_USBD_DATA_INTERFACE_STR "Bulk Data Interface" -#define CFG_USBD_CTRL_INTERFACE_STR "Control Interface" - -/* - * Buffers to hold input and output data - */ -#define USBTTY_BUFFER_SIZE 2048 -static circbuf_t usbtty_input; -static circbuf_t usbtty_output; - -/* - * Instance variables - */ -static struct stdio_dev usbttydev; -static struct usb_device_instance device_instance[1]; -static struct usb_bus_instance bus_instance[1]; -static struct usb_configuration_instance config_instance[NUM_CONFIGS]; -static struct usb_interface_instance interface_instance[MAX_INTERFACES]; -static struct usb_alternate_instance alternate_instance[MAX_INTERFACES]; -/* one extra for control endpoint */ -static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS+1]; - -/* - * Global flag - */ -int usbtty_configured_flag = 0; - -/* - * Serial number - */ -static char serial_number[16]; - -/* - * Descriptors, Strings, Local variables. - */ - -/* defined and used by gadget/ep0.c */ -extern struct usb_string_descriptor **usb_strings; - -/* Indicies, References */ -static unsigned short rx_endpoint = 0; -static unsigned short tx_endpoint = 0; -static unsigned short interface_count = 0; -static struct usb_string_descriptor *usbtty_string_table[STR_COUNT]; - -/* USB Descriptor Strings */ -static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4}; -static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)]; -static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)]; -static u8 wstrSerial[2 + 2*(sizeof(serial_number) - 1)]; -static u8 wstrConfiguration[2 + 2*(sizeof(CFG_USBD_CONFIGURATION_STR)-1)]; -static u8 wstrDataInterface[2 + 2*(sizeof(CFG_USBD_DATA_INTERFACE_STR)-1)]; -static u8 wstrCtrlInterface[2 + 2*(sizeof(CFG_USBD_DATA_INTERFACE_STR)-1)]; - -/* Standard USB Data Structures */ -static struct usb_interface_descriptor interface_descriptors[MAX_INTERFACES]; -static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS]; -static struct usb_configuration_descriptor *configuration_descriptor = 0; -static struct usb_device_descriptor device_descriptor = { - .bLength = sizeof(struct usb_device_descriptor), - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = cpu_to_le16(USB_BCD_VERSION), - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE, - .idVendor = cpu_to_le16(CONFIG_USBD_VENDORID), - .bcdDevice = cpu_to_le16(USBTTY_BCD_DEVICE), - .iManufacturer = STR_MANUFACTURER, - .iProduct = STR_PRODUCT, - .iSerialNumber = STR_SERIAL, - .bNumConfigurations = NUM_CONFIGS -}; - -/* - * Static CDC ACM specific descriptors - */ - -struct acm_config_desc { - struct usb_configuration_descriptor configuration_desc; - - /* Master Interface */ - struct usb_interface_descriptor interface_desc; - - struct usb_class_header_function_descriptor usb_class_header; - struct usb_class_call_management_descriptor usb_class_call_mgt; - struct usb_class_abstract_control_descriptor usb_class_acm; - struct usb_class_union_function_descriptor usb_class_union; - struct usb_endpoint_descriptor notification_endpoint; - - /* Slave Interface */ - struct usb_interface_descriptor data_class_interface; - struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS-1]; -} __attribute__((packed)); - -static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = { - { - .configuration_desc ={ - .bLength = - sizeof(struct usb_configuration_descriptor), - .bDescriptorType = USB_DT_CONFIG, - .wTotalLength = - cpu_to_le16(sizeof(struct acm_config_desc)), - .bNumInterfaces = NUM_ACM_INTERFACES, - .bConfigurationValue = 1, - .iConfiguration = STR_CONFIG, - .bmAttributes = - BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED, - .bMaxPower = USBTTY_MAXPOWER - }, - /* Interface 1 */ - .interface_desc = { - .bLength = sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 0x01, - .bInterfaceClass = - COMMUNICATIONS_INTERFACE_CLASS_CONTROL, - .bInterfaceSubClass = COMMUNICATIONS_ACM_SUBCLASS, - .bInterfaceProtocol = COMMUNICATIONS_V25TER_PROTOCOL, - .iInterface = STR_CTRL_INTERFACE, - }, - .usb_class_header = { - .bFunctionLength = - sizeof(struct usb_class_header_function_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_ST_HEADER, - .bcdCDC = cpu_to_le16(110), - }, - .usb_class_call_mgt = { - .bFunctionLength = - sizeof(struct usb_class_call_management_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_ST_CMF, - .bmCapabilities = 0x00, - .bDataInterface = 0x01, - }, - .usb_class_acm = { - .bFunctionLength = - sizeof(struct usb_class_abstract_control_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_ST_ACMF, - .bmCapabilities = 0x00, - }, - .usb_class_union = { - .bFunctionLength = - sizeof(struct usb_class_union_function_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_ST_UF, - .bMasterInterface = 0x00, - .bSlaveInterface0 = 0x01, - }, - .notification_endpoint = { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize - = cpu_to_le16(CFG_USBD_SERIAL_INT_PKTSIZE), - .bInterval = 0xFF, - }, - - /* Interface 2 */ - .data_class_interface = { - .bLength = - sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0x01, - .bAlternateSetting = 0x00, - .bNumEndpoints = 0x02, - .bInterfaceClass = - COMMUNICATIONS_INTERFACE_CLASS_DATA, - .bInterfaceSubClass = DATA_INTERFACE_SUBCLASS_NONE, - .bInterfaceProtocol = DATA_INTERFACE_PROTOCOL_NONE, - .iInterface = STR_DATA_INTERFACE, - }, - .data_endpoints = { - { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT, - .bmAttributes = - USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = - cpu_to_le16(CFG_USBD_SERIAL_BULK_PKTSIZE), - .bInterval = 0xFF, - }, - { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN, - .bmAttributes = - USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = - cpu_to_le16(CFG_USBD_SERIAL_BULK_PKTSIZE), - .bInterval = 0xFF, - }, - }, - }, -}; - -static struct rs232_emu rs232_desc={ - .dter = 115200, - .stop_bits = 0x00, - .parity = 0x00, - .data_bits = 0x08 -}; - -/* - * Static Generic Serial specific data - */ - -struct gserial_config_desc { - - struct usb_configuration_descriptor configuration_desc; - struct usb_interface_descriptor interface_desc[NUM_GSERIAL_INTERFACES]; - struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS]; - -} __attribute__((packed)); - -static struct gserial_config_desc -gserial_configuration_descriptors[NUM_CONFIGS] ={ - { - .configuration_desc ={ - .bLength = sizeof(struct usb_configuration_descriptor), - .bDescriptorType = USB_DT_CONFIG, - .wTotalLength = - cpu_to_le16(sizeof(struct gserial_config_desc)), - .bNumInterfaces = NUM_GSERIAL_INTERFACES, - .bConfigurationValue = 1, - .iConfiguration = STR_CONFIG, - .bmAttributes = - BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED, - .bMaxPower = USBTTY_MAXPOWER - }, - .interface_desc = { - { - .bLength = - sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = NUM_ENDPOINTS, - .bInterfaceClass = - COMMUNICATIONS_INTERFACE_CLASS_VENDOR, - .bInterfaceSubClass = - COMMUNICATIONS_NO_SUBCLASS, - .bInterfaceProtocol = - COMMUNICATIONS_NO_PROTOCOL, - .iInterface = STR_DATA_INTERFACE - }, - }, - .data_endpoints = { - { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = - cpu_to_le16(CFG_USBD_SERIAL_OUT_PKTSIZE), - .bInterval= 0xFF, - }, - { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = - cpu_to_le16(CFG_USBD_SERIAL_IN_PKTSIZE), - .bInterval = 0xFF, - }, - { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = - cpu_to_le16(CFG_USBD_SERIAL_INT_PKTSIZE), - .bInterval = 0xFF, - }, - }, - }, -}; - -/* - * Static Function Prototypes - */ - -static void usbtty_init_strings (void); -static void usbtty_init_instances (void); -static void usbtty_init_endpoints (void); -static void usbtty_init_terminal_type(short type); -static void usbtty_event_handler (struct usb_device_instance *device, - usb_device_event_t event, int data); -static int usbtty_cdc_setup(struct usb_device_request *request, - struct urb *urb); -static int usbtty_configured (void); -static int write_buffer (circbuf_t * buf); -static int fill_buffer (circbuf_t * buf); - -void usbtty_poll (void); - -/* utility function for converting char* to wide string used by USB */ -static void str2wide (char *str, u16 * wide) -{ - int i; - for (i = 0; i < strlen (str) && str[i]; i++){ - #if defined(__LITTLE_ENDIAN) - wide[i] = (u16) str[i]; - #elif defined(__BIG_ENDIAN) - wide[i] = ((u16)(str[i])<<8); - #else - #error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined" - #endif - } -} - -/* - * Test whether a character is in the RX buffer - */ - -int usbtty_tstc(struct stdio_dev *dev) -{ - struct usb_endpoint_instance *endpoint = - &endpoint_instance[rx_endpoint]; - - /* If no input data exists, allow more RX to be accepted */ - if(usbtty_input.size <= 0){ - udc_unset_nak(endpoint->endpoint_address&0x03); - } - - usbtty_poll (); - return (usbtty_input.size > 0); -} - -/* - * Read a single byte from the usb client port. Returns 1 on success, 0 - * otherwise. When the function is succesfull, the character read is - * written into its argument c. - */ - -int usbtty_getc(struct stdio_dev *dev) -{ - char c; - struct usb_endpoint_instance *endpoint = - &endpoint_instance[rx_endpoint]; - - while (usbtty_input.size <= 0) { - udc_unset_nak(endpoint->endpoint_address&0x03); - usbtty_poll (); - } - - buf_pop (&usbtty_input, &c, 1); - udc_set_nak(endpoint->endpoint_address&0x03); - - return c; -} - -/* - * Output a single byte to the usb client port. - */ -void usbtty_putc(struct stdio_dev *dev, const char c) -{ - if (!usbtty_configured ()) - return; - - /* If \n, also do \r */ - if (c == '\n') - buf_push (&usbtty_output, "\r", 1); - - buf_push(&usbtty_output, &c, 1); - - /* Poll at end to handle new data... */ - if ((usbtty_output.size + 2) >= usbtty_output.totalsize) { - usbtty_poll (); - } -} - -/* usbtty_puts() helper function for finding the next '\n' in a string */ -static int next_nl_pos (const char *s) -{ - int i; - - for (i = 0; s[i] != '\0'; i++) { - if (s[i] == '\n') - return i; - } - return i; -} - -/* - * Output a string to the usb client port - implementing flow control - */ - -static void __usbtty_puts (const char *str, int len) -{ - int maxlen = usbtty_output.totalsize; - int space, n; - - /* break str into chunks < buffer size, if needed */ - while (len > 0) { - usbtty_poll (); - - space = maxlen - usbtty_output.size; - /* Empty buffer here, if needed, to ensure space... */ - if (space) { - write_buffer (&usbtty_output); - - n = min(space, min(len, maxlen)); - buf_push (&usbtty_output, str, n); - - str += n; - len -= n; - } - } -} - -void usbtty_puts(struct stdio_dev *dev, const char *str) -{ - int n; - int len; - - if (!usbtty_configured ()) - return; - - len = strlen (str); - /* add '\r' for each '\n' */ - while (len > 0) { - n = next_nl_pos (str); - - if (str[n] == '\n') { - __usbtty_puts(str, n); - __usbtty_puts("\r\n", 2); - str += (n + 1); - len -= (n + 1); - } else { - /* No \n found. All done. */ - __usbtty_puts (str, n); - break; - } - } - - /* Poll at end to handle new data... */ - usbtty_poll (); -} - -/* - * Initialize the usb client port. - * - */ -int drv_usbtty_init (void) -{ - int rc; - char * sn; - char * tt; - int snlen; - - /* Get serial number */ - sn = env_get("serial#"); - if (!sn) - sn = "000000000000"; - snlen = strlen(sn); - if (snlen > sizeof(serial_number) - 1) { - printf ("Warning: serial number %s is too long (%d > %lu)\n", - sn, snlen, (ulong)(sizeof(serial_number) - 1)); - snlen = sizeof(serial_number) - 1; - } - memcpy (serial_number, sn, snlen); - serial_number[snlen] = '\0'; - - /* Decide on which type of UDC device to be. - */ - tt = env_get("usbtty"); - if (!tt) - tt = "generic"; - usbtty_init_terminal_type(strcmp(tt,"cdc_acm")); - - /* prepare buffers... */ - buf_init (&usbtty_input, USBTTY_BUFFER_SIZE); - buf_init (&usbtty_output, USBTTY_BUFFER_SIZE); - - /* Now, set up USB controller and infrastructure */ - udc_init (); /* Basic USB initialization */ - - usbtty_init_strings (); - usbtty_init_instances (); - - usbtty_init_endpoints (); - - udc_startup_events (device_instance);/* Enable dev, init udc pointers */ - udc_connect (); /* Enable pullup for host detection */ - - /* Device initialization */ - memset (&usbttydev, 0, sizeof (usbttydev)); - - strcpy (usbttydev.name, "usbtty"); - usbttydev.ext = 0; /* No extensions */ - usbttydev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT; - usbttydev.tstc = usbtty_tstc; /* 'tstc' function */ - usbttydev.getc = usbtty_getc; /* 'getc' function */ - usbttydev.putc = usbtty_putc; /* 'putc' function */ - usbttydev.puts = usbtty_puts; /* 'puts' function */ - - rc = stdio_register (&usbttydev); - - return (rc == 0) ? 1 : rc; -} - -static void usbtty_init_strings (void) -{ - struct usb_string_descriptor *string; - - usbtty_string_table[STR_LANG] = - (struct usb_string_descriptor*)wstrLang; - - string = (struct usb_string_descriptor *) wstrManufacturer; - string->bLength = sizeof(wstrManufacturer); - string->bDescriptorType = USB_DT_STRING; - str2wide (CONFIG_USBD_MANUFACTURER, string->wData); - usbtty_string_table[STR_MANUFACTURER]=string; - - string = (struct usb_string_descriptor *) wstrProduct; - string->bLength = sizeof(wstrProduct); - string->bDescriptorType = USB_DT_STRING; - str2wide (CONFIG_USBD_PRODUCT_NAME, string->wData); - usbtty_string_table[STR_PRODUCT]=string; - - string = (struct usb_string_descriptor *) wstrSerial; - string->bLength = sizeof(serial_number); - string->bDescriptorType = USB_DT_STRING; - str2wide (serial_number, string->wData); - usbtty_string_table[STR_SERIAL]=string; - - string = (struct usb_string_descriptor *) wstrConfiguration; - string->bLength = sizeof(wstrConfiguration); - string->bDescriptorType = USB_DT_STRING; - str2wide (CFG_USBD_CONFIGURATION_STR, string->wData); - usbtty_string_table[STR_CONFIG]=string; - - string = (struct usb_string_descriptor *) wstrDataInterface; - string->bLength = sizeof(wstrDataInterface); - string->bDescriptorType = USB_DT_STRING; - str2wide (CFG_USBD_DATA_INTERFACE_STR, string->wData); - usbtty_string_table[STR_DATA_INTERFACE]=string; - - string = (struct usb_string_descriptor *) wstrCtrlInterface; - string->bLength = sizeof(wstrCtrlInterface); - string->bDescriptorType = USB_DT_STRING; - str2wide (CFG_USBD_CTRL_INTERFACE_STR, string->wData); - usbtty_string_table[STR_CTRL_INTERFACE]=string; - - /* Now, initialize the string table for ep0 handling */ - usb_strings = usbtty_string_table; -} - -#define init_wMaxPacketSize(x) le16_to_cpu(get_unaligned(\ - &ep_descriptor_ptrs[(x) - 1]->wMaxPacketSize)); - -static void usbtty_init_instances (void) -{ - int i; - - /* initialize device instance */ - memset (device_instance, 0, sizeof (struct usb_device_instance)); - device_instance->device_state = STATE_INIT; - device_instance->device_descriptor = &device_descriptor; - device_instance->event = usbtty_event_handler; - device_instance->cdc_recv_setup = usbtty_cdc_setup; - device_instance->bus = bus_instance; - device_instance->configurations = NUM_CONFIGS; - device_instance->configuration_instance_array = config_instance; - - /* initialize bus instance */ - memset (bus_instance, 0, sizeof (struct usb_bus_instance)); - bus_instance->device = device_instance; - bus_instance->endpoint_array = endpoint_instance; - bus_instance->max_endpoints = 1; - bus_instance->maxpacketsize = 64; - bus_instance->serial_number_str = serial_number; - - /* configuration instance */ - memset (config_instance, 0, - sizeof (struct usb_configuration_instance)); - config_instance->interfaces = interface_count; - config_instance->configuration_descriptor = configuration_descriptor; - config_instance->interface_instance_array = interface_instance; - - /* interface instance */ - memset (interface_instance, 0, - sizeof (struct usb_interface_instance)); - interface_instance->alternates = 1; - interface_instance->alternates_instance_array = alternate_instance; - - /* alternates instance */ - memset (alternate_instance, 0, - sizeof (struct usb_alternate_instance)); - alternate_instance->interface_descriptor = interface_descriptors; - alternate_instance->endpoints = NUM_ENDPOINTS; - alternate_instance->endpoints_descriptor_array = ep_descriptor_ptrs; - - /* endpoint instances */ - memset (&endpoint_instance[0], 0, - sizeof (struct usb_endpoint_instance)); - endpoint_instance[0].endpoint_address = 0; - endpoint_instance[0].rcv_packetSize = EP0_MAX_PACKET_SIZE; - endpoint_instance[0].rcv_attributes = USB_ENDPOINT_XFER_CONTROL; - endpoint_instance[0].tx_packetSize = EP0_MAX_PACKET_SIZE; - endpoint_instance[0].tx_attributes = USB_ENDPOINT_XFER_CONTROL; - udc_setup_ep (device_instance, 0, &endpoint_instance[0]); - - for (i = 1; i <= NUM_ENDPOINTS; i++) { - memset (&endpoint_instance[i], 0, - sizeof (struct usb_endpoint_instance)); - - endpoint_instance[i].endpoint_address = - ep_descriptor_ptrs[i - 1]->bEndpointAddress; - - endpoint_instance[i].rcv_attributes = - ep_descriptor_ptrs[i - 1]->bmAttributes; - - endpoint_instance[i].rcv_packetSize = init_wMaxPacketSize(i); - - endpoint_instance[i].tx_attributes = - ep_descriptor_ptrs[i - 1]->bmAttributes; - - endpoint_instance[i].tx_packetSize = init_wMaxPacketSize(i); - - endpoint_instance[i].tx_attributes = - ep_descriptor_ptrs[i - 1]->bmAttributes; - - urb_link_init (&endpoint_instance[i].rcv); - urb_link_init (&endpoint_instance[i].rdy); - urb_link_init (&endpoint_instance[i].tx); - urb_link_init (&endpoint_instance[i].done); - - if (endpoint_instance[i].endpoint_address & USB_DIR_IN) - endpoint_instance[i].tx_urb = - usbd_alloc_urb (device_instance, - &endpoint_instance[i]); - else - endpoint_instance[i].rcv_urb = - usbd_alloc_urb (device_instance, - &endpoint_instance[i]); - } -} - -static void usbtty_init_endpoints (void) -{ - int i; - - bus_instance->max_endpoints = NUM_ENDPOINTS + 1; - for (i = 1; i <= NUM_ENDPOINTS; i++) { - udc_setup_ep (device_instance, i, &endpoint_instance[i]); - } -} - -/* usbtty_init_terminal_type - * - * Do some late binding for our device type. - */ -static void usbtty_init_terminal_type(short type) -{ - switch(type){ - /* CDC ACM */ - case 0: - /* Assign endpoint descriptors */ - ep_descriptor_ptrs[0] = - &acm_configuration_descriptors[0].notification_endpoint; - ep_descriptor_ptrs[1] = - &acm_configuration_descriptors[0].data_endpoints[0]; - ep_descriptor_ptrs[2] = - &acm_configuration_descriptors[0].data_endpoints[1]; - - /* Enumerate Device Descriptor */ - device_descriptor.bDeviceClass = - COMMUNICATIONS_DEVICE_CLASS; - device_descriptor.idProduct = - cpu_to_le16(CONFIG_USBD_PRODUCTID_CDCACM); - - /* Assign endpoint indices */ - tx_endpoint = ACM_TX_ENDPOINT; - rx_endpoint = ACM_RX_ENDPOINT; - - /* Configuration Descriptor */ - configuration_descriptor = - (struct usb_configuration_descriptor*) - &acm_configuration_descriptors; - - /* Interface count */ - interface_count = NUM_ACM_INTERFACES; - break; - - /* BULK IN/OUT & Default */ - case 1: - default: - /* Assign endpoint descriptors */ - ep_descriptor_ptrs[0] = - &gserial_configuration_descriptors[0].data_endpoints[0]; - ep_descriptor_ptrs[1] = - &gserial_configuration_descriptors[0].data_endpoints[1]; - ep_descriptor_ptrs[2] = - &gserial_configuration_descriptors[0].data_endpoints[2]; - - /* Enumerate Device Descriptor */ - device_descriptor.bDeviceClass = 0xFF; - device_descriptor.idProduct = - cpu_to_le16(CONFIG_USBD_PRODUCTID_GSERIAL); - /* Assign endpoint indices */ - tx_endpoint = GSERIAL_TX_ENDPOINT; - rx_endpoint = GSERIAL_RX_ENDPOINT; - - /* Configuration Descriptor */ - configuration_descriptor = - (struct usb_configuration_descriptor*) - &gserial_configuration_descriptors; - - /* Interface count */ - interface_count = NUM_GSERIAL_INTERFACES; - break; - } -} - -/******************************************************************************/ - -static struct urb *next_urb (struct usb_device_instance *device, - struct usb_endpoint_instance *endpoint) -{ - struct urb *current_urb = NULL; - int space; - - /* If there's a queue, then we should add to the last urb */ - if (!endpoint->tx_queue) { - current_urb = endpoint->tx_urb; - } else { - /* Last urb from tx chain */ - current_urb = - p2surround (struct urb, link, endpoint->tx.prev); - } - - /* Make sure this one has enough room */ - space = current_urb->buffer_length - current_urb->actual_length; - if (space > 0) { - return current_urb; - } else { /* No space here */ - /* First look at done list */ - current_urb = first_urb_detached (&endpoint->done); - if (!current_urb) { - current_urb = usbd_alloc_urb (device, endpoint); - } - - urb_append (&endpoint->tx, current_urb); - endpoint->tx_queue++; - } - return current_urb; -} - -static int write_buffer (circbuf_t * buf) -{ - if (!usbtty_configured ()) { - return 0; - } - - struct usb_endpoint_instance *endpoint = - &endpoint_instance[tx_endpoint]; - struct urb *current_urb = NULL; - - /* TX data still exists - send it now - */ - if(endpoint->sent < endpoint->tx_urb->actual_length){ - if(udc_endpoint_write (endpoint)){ - /* Write pre-empted by RX */ - return -1; - } - } - - if (buf->size) { - char *dest; - - int space_avail; - int popnum, popped; - int total = 0; - - /* Break buffer into urb sized pieces, - * and link each to the endpoint - */ - while (buf->size > 0) { - - current_urb = next_urb (device_instance, endpoint); - - dest = (char*)current_urb->buffer + - current_urb->actual_length; - - space_avail = - current_urb->buffer_length - - current_urb->actual_length; - popnum = min(space_avail, (int)buf->size); - if (popnum == 0) - break; - - popped = buf_pop (buf, dest, popnum); - if (popped == 0) - break; - current_urb->actual_length += popped; - total += popped; - - /* If endpoint->last == 0, then transfers have - * not started on this endpoint - */ - if (endpoint->last == 0) { - if(udc_endpoint_write (endpoint)){ - /* Write pre-empted by RX */ - return -1; - } - } - - }/* end while */ - return total; - } - - return 0; -} - -static int fill_buffer (circbuf_t * buf) -{ - struct usb_endpoint_instance *endpoint = - &endpoint_instance[rx_endpoint]; - - if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) { - unsigned int nb = 0; - char *src = (char *) endpoint->rcv_urb->buffer; - unsigned int rx_avail = buf->totalsize - buf->size; - - if(rx_avail >= endpoint->rcv_urb->actual_length){ - - nb = endpoint->rcv_urb->actual_length; - buf_push (buf, src, nb); - endpoint->rcv_urb->actual_length = 0; - - } - return nb; - } - return 0; -} - -static int usbtty_configured (void) -{ - return usbtty_configured_flag; -} - -/******************************************************************************/ - -static void usbtty_event_handler (struct usb_device_instance *device, - usb_device_event_t event, int data) -{ - switch (event) { - case DEVICE_RESET: - case DEVICE_BUS_INACTIVE: - usbtty_configured_flag = 0; - break; - case DEVICE_CONFIGURED: - usbtty_configured_flag = 1; - break; - - case DEVICE_ADDRESS_ASSIGNED: - usbtty_init_endpoints (); - - default: - break; - } -} - -/******************************************************************************/ - -int usbtty_cdc_setup(struct usb_device_request *request, struct urb *urb) -{ - switch (request->bRequest){ - - case ACM_SET_CONTROL_LINE_STATE: /* Implies DTE ready */ - break; - case ACM_SEND_ENCAPSULATED_COMMAND : /* Required */ - break; - case ACM_SET_LINE_ENCODING : /* DTE stop/parity bits - * per character */ - break; - case ACM_GET_ENCAPSULATED_RESPONSE : /* request response */ - break; - case ACM_GET_LINE_ENCODING : /* request DTE rate, - * stop/parity bits */ - memcpy (urb->buffer , &rs232_desc, sizeof(rs232_desc)); - urb->actual_length = sizeof(rs232_desc); - - break; - default: - return 1; - } - return 0; -} - -/******************************************************************************/ - -/* - * Since interrupt handling has not yet been implemented, we use this function - * to handle polling. This is called by the tstc,getc,putc,puts routines to - * update the USB state. - */ -void usbtty_poll (void) -{ - /* New interrupts? */ - udc_irq(); - - /* Write any output data to host buffer - * (do this before checking interrupts to avoid missing one) - */ - if (usbtty_configured ()) { - write_buffer (&usbtty_output); - } - - /* New interrupts? */ - udc_irq(); - - /* Check for new data from host.. - * (do this after checking interrupts to get latest data) - */ - if (usbtty_configured ()) { - fill_buffer (&usbtty_input); - } - - /* New interrupts? */ - udc_irq(); - -} diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h deleted file mode 100644 index b176a7961b8..00000000000 --- a/drivers/serial/usbtty.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * (C) Copyright 2006 - * Bryan O'Donoghue, bodonoghue@codehermit.ie, CodeHermit - */ - -#ifndef __USB_TTY_H__ -#define __USB_TTY_H__ - -#include <usbdevice.h> -#if defined(CONFIG_PPC) -#include <usb/mpc8xx_udc.h> -#elif defined(CONFIG_CI_UDC) -#include <usb/ci_udc.h> -#endif - -#include <usb/udc.h> -#include <version.h> - -#ifndef CFG_USBD_CONFIGURATION_STR -#define CFG_USBD_CONFIGURATION_STR "TTY via USB" -#endif - -#define CFG_USBD_SERIAL_OUT_ENDPOINT UDC_OUT_ENDPOINT -#define CFG_USBD_SERIAL_OUT_PKTSIZE UDC_OUT_PACKET_SIZE -#define CFG_USBD_SERIAL_IN_ENDPOINT UDC_IN_ENDPOINT -#define CFG_USBD_SERIAL_IN_PKTSIZE UDC_IN_PACKET_SIZE -#define CFG_USBD_SERIAL_INT_ENDPOINT UDC_INT_ENDPOINT -#define CFG_USBD_SERIAL_INT_PKTSIZE UDC_INT_PACKET_SIZE -#define CFG_USBD_SERIAL_BULK_PKTSIZE UDC_BULK_PACKET_SIZE - -#define USBTTY_DEVICE_CLASS COMMUNICATIONS_DEVICE_CLASS - -#define USBTTY_BCD_DEVICE 0x00 -#define USBTTY_MAXPOWER 0x00 - -#define STR_LANG 0x00 -#define STR_MANUFACTURER 0x01 -#define STR_PRODUCT 0x02 -#define STR_SERIAL 0x03 -#define STR_CONFIG 0x04 -#define STR_DATA_INTERFACE 0x05 -#define STR_CTRL_INTERFACE 0x06 -#define STR_COUNT 0x07 - -#endif diff --git a/drivers/soc/soc_amd_versal2.c b/drivers/soc/soc_amd_versal2.c index 66bcb22b4fa..8507da0bd22 100644 --- a/drivers/soc/soc_amd_versal2.c +++ b/drivers/soc/soc_amd_versal2.c @@ -35,7 +35,9 @@ static int soc_amd_versal2_get_revision(struct udevice *dev, char *buf, int size { struct soc_amd_versal2_priv *priv = dev_get_priv(dev); - return snprintf(buf, size, "v%d", priv->revision); + return snprintf(buf, size, "v%d.%d", + (u32)FIELD_GET(PS_VERSION_MAJOR, priv->revision), + (u32)FIELD_GET(PS_VERSION_MINOR, priv->revision)); } static const struct soc_ops soc_amd_versal2_ops = { diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a916b711ba8..f475f341c9c 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -52,6 +52,13 @@ config SPI_DIRMAP if DM_SPI +config ADI_SPI3 + bool "Enable ADI SPI Driver" + depends on ARCH_SC5XX + help + Enable the ADI (Analog Devices) SPI controller driver. This + driver enables the support for SC5XX spi controller. + config ALTERA_SPI bool "Altera SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 7051e2a00c6..21895d46429 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -19,6 +19,7 @@ obj-y += spi.o obj-$(CONFIG_SPI_MEM) += spi-mem-nodm.o endif +obj-$(CONFIG_ADI_SPI3) += adi_spi3.o obj-$(CONFIG_ALTERA_SPI) += altera_spi.o obj-$(CONFIG_APPLE_SPI) += apple_spi.o obj-$(CONFIG_ATH79_SPI) += ath79_spi.o diff --git a/drivers/spi/adi_spi3.c b/drivers/spi/adi_spi3.c new file mode 100644 index 00000000000..2125d25561a --- /dev/null +++ b/drivers/spi/adi_spi3.c @@ -0,0 +1,679 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Converted to driver model by Nathan Barrett-Morrison + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * Contact: Ian Roberts <ian.roberts@timesys.com> + * Contact: Piotr Wojtaszczyk <piotr.wojtaszczyk@timesys.com> + * + */ + +#include <clk.h> +#include <dm.h> +#include <mapmem.h> +#include <spi.h> +#include <spi-mem.h> +#include <dm/device_compat.h> +#include <linux/io.h> + +#define SPI_IDLE_VAL 0xff + +#define MAX_CTRL_CS 7 + +/* SPI_CONTROL */ +#define SPI_CTL_EN 0x00000001 /* Enable */ +#define SPI_CTL_MSTR 0x00000002 /* Master/Slave */ +#define SPI_CTL_PSSE 0x00000004 /* controls modf error in master mode */ +#define SPI_CTL_ODM 0x00000008 /* Open Drain Mode */ +#define SPI_CTL_CPHA 0x00000010 /* Clock Phase */ +#define SPI_CTL_CPOL 0x00000020 /* Clock Polarity */ +#define SPI_CTL_ASSEL 0x00000040 /* Slave Select Pin Control */ +#define SPI_CTL_SELST 0x00000080 /* Slave Select Polarity in transfers */ +#define SPI_CTL_EMISO 0x00000100 /*Enable MISO */ +#define SPI_CTL_SIZE 0x00000600 /*Word Transfer Size */ +#define SPI_CTL_SIZE08 0x00000000 /*SIZE: 8 bits */ +#define SPI_CTL_SIZE16 0x00000200 /*SIZE: 16 bits */ +#define SPI_CTL_SIZE32 0x00000400 /*SIZE: 32 bits */ +#define SPI_CTL_LSBF 0x00001000 /*LSB First */ +#define SPI_CTL_FCEN 0x00002000 /*Flow-Control Enable */ +#define SPI_CTL_FCCH 0x00004000 /*Flow-Control Channel Selection */ +#define SPI_CTL_FCPL 0x00008000 /*Flow-Control Polarity */ +#define SPI_CTL_FCWM 0x00030000 /*Flow-Control Water-Mark */ +#define SPI_CTL_FIFO0 0x00000000 /*FCWM: Tx empty or Rx Full */ +#define SPI_CTL_FIFO1 0x00010000 /*FCWM: Tx empty or Rx full (>=75%) */ +#define SPI_CTL_FIFO2 0x00020000 /*FCWM: Tx empty or Rx full (>=50%) */ +#define SPI_CTL_FMODE 0x00040000 /*Fast-mode Enable */ +#define SPI_CTL_MIOM 0x00300000 /*Multiple I/O Mode */ +#define SPI_CTL_MIO_DIS 0x00000000 /*MIOM: Disable */ +#define SPI_CTL_MIO_DUAL 0x00100000 /*MIOM: Enable DIOM (Dual I/O Mode) */ +#define SPI_CTL_MIO_QUAD 0x00200000 /*MIOM: Enable QUAD (Quad SPI Mode) */ +#define SPI_CTL_SOSI 0x00400000 /*Start on MOSI */ +#define SPI_CTL_MMWEM 0x40000000 /*Start on MMWEM */ +#define SPI_CTL_MMSE 0x80000000 /*Start on MMSE */ +/* SPI_RX_CONTROL */ +#define SPI_RXCTL_REN 0x00000001 /*Receive Channel Enable */ +#define SPI_RXCTL_RTI 0x00000004 /*Receive Transfer Initiate */ +#define SPI_RXCTL_RWCEN 0x00000008 /*Receive Word Counter Enable */ +#define SPI_RXCTL_RDR 0x00000070 /*Receive Data Request */ +#define SPI_RXCTL_RDR_DIS 0x00000000 /*RDR: Disabled */ +#define SPI_RXCTL_RDR_NE 0x00000010 /*RDR: RFIFO not empty */ +#define SPI_RXCTL_RDR_25 0x00000020 /*RDR: RFIFO 25% full */ +#define SPI_RXCTL_RDR_50 0x00000030 /*RDR: RFIFO 50% full */ +#define SPI_RXCTL_RDR_75 0x00000040 /*RDR: RFIFO 75% full */ +#define SPI_RXCTL_RDR_FULL 0x00000050 /*RDR: RFIFO full */ +#define SPI_RXCTL_RDO 0x00000100 /*Receive Data Over-Run */ +#define SPI_RXCTL_RRWM 0x00003000 /*FIFO Regular Water-Mark */ +#define SPI_RXCTL_RWM_0 0x00000000 /*RRWM: RFIFO Empty */ +#define SPI_RXCTL_RWM_25 0x00001000 /*RRWM: RFIFO 25% full */ +#define SPI_RXCTL_RWM_50 0x00002000 /*RRWM: RFIFO 50% full */ +#define SPI_RXCTL_RWM_75 0x00003000 /*RRWM: RFIFO 75% full */ +#define SPI_RXCTL_RUWM 0x00070000 /*FIFO Urgent Water-Mark */ +#define SPI_RXCTL_UWM_DIS 0x00000000 /*RUWM: Disabled */ +#define SPI_RXCTL_UWM_25 0x00010000 /*RUWM: RFIFO 25% full */ +#define SPI_RXCTL_UWM_50 0x00020000 /*RUWM: RFIFO 50% full */ +#define SPI_RXCTL_UWM_75 0x00030000 /*RUWM: RFIFO 75% full */ +#define SPI_RXCTL_UWM_FULL 0x00040000 /*RUWM: RFIFO full */ +/* SPI_TX_CONTROL */ +#define SPI_TXCTL_TEN 0x00000001 /*Transmit Channel Enable */ +#define SPI_TXCTL_TTI 0x00000004 /*Transmit Transfer Initiate */ +#define SPI_TXCTL_TWCEN 0x00000008 /*Transmit Word Counter Enable */ +#define SPI_TXCTL_TDR 0x00000070 /*Transmit Data Request */ +#define SPI_TXCTL_TDR_DIS 0x00000000 /*TDR: Disabled */ +#define SPI_TXCTL_TDR_NF 0x00000010 /*TDR: TFIFO not full */ +#define SPI_TXCTL_TDR_25 0x00000020 /*TDR: TFIFO 25% empty */ +#define SPI_TXCTL_TDR_50 0x00000030 /*TDR: TFIFO 50% empty */ +#define SPI_TXCTL_TDR_75 0x00000040 /*TDR: TFIFO 75% empty */ +#define SPI_TXCTL_TDR_EMPTY 0x00000050 /*TDR: TFIFO empty */ +#define SPI_TXCTL_TDU 0x00000100 /*Transmit Data Under-Run */ +#define SPI_TXCTL_TRWM 0x00003000 /*FIFO Regular Water-Mark */ +#define SPI_TXCTL_RWM_FULL 0x00000000 /*TRWM: TFIFO full */ +#define SPI_TXCTL_RWM_25 0x00001000 /*TRWM: TFIFO 25% empty */ +#define SPI_TXCTL_RWM_50 0x00002000 /*TRWM: TFIFO 50% empty */ +#define SPI_TXCTL_RWM_75 0x00003000 /*TRWM: TFIFO 75% empty */ +#define SPI_TXCTL_TUWM 0x00070000 /*FIFO Urgent Water-Mark */ +#define SPI_TXCTL_UWM_DIS 0x00000000 /*TUWM: Disabled */ +#define SPI_TXCTL_UWM_25 0x00010000 /*TUWM: TFIFO 25% empty */ +#define SPI_TXCTL_UWM_50 0x00020000 /*TUWM: TFIFO 50% empty */ +#define SPI_TXCTL_UWM_75 0x00030000 /*TUWM: TFIFO 75% empty */ +#define SPI_TXCTL_UWM_EMPTY 0x00040000 /*TUWM: TFIFO empty */ +/* SPI_CLOCK */ +#define SPI_CLK_BAUD 0x0000FFFF /*Baud Rate */ +/* SPI_DELAY */ +#define SPI_DLY_STOP 0x000000FF /*Transfer delay time */ +#define SPI_DLY_LEADX 0x00000100 /*Extended (1 SCK) LEAD Control */ +#define SPI_DLY_LAGX 0x00000200 /*Extended (1 SCK) LAG control */ +/* SPI_SSEL */ +#define SPI_SLVSEL_SSE1 0x00000002 /*SPISSEL1 Enable */ +#define SPI_SLVSEL_SSE2 0x00000004 /*SPISSEL2 Enable */ +#define SPI_SLVSEL_SSE3 0x00000008 /*SPISSEL3 Enable */ +#define SPI_SLVSEL_SSE4 0x00000010 /*SPISSEL4 Enable */ +#define SPI_SLVSEL_SSE5 0x00000020 /*SPISSEL5 Enable */ +#define SPI_SLVSEL_SSE6 0x00000040 /*SPISSEL6 Enable */ +#define SPI_SLVSEL_SSE7 0x00000080 /*SPISSEL7 Enable */ +#define SPI_SLVSEL_SSEL1 0x00000200 /*SPISSEL1 Value */ +#define SPI_SLVSEL_SSEL2 0x00000400 /*SPISSEL2 Value */ +#define SPI_SLVSEL_SSEL3 0x00000800 /*SPISSEL3 Value */ +#define SPI_SLVSEL_SSEL4 0x00001000 /*SPISSEL4 Value */ +#define SPI_SLVSEL_SSEL5 0x00002000 /*SPISSEL5 Value */ +#define SPI_SLVSEL_SSEL6 0x00004000 /*SPISSEL6 Value */ +#define SPI_SLVSEL_SSEL7 0x00008000 /*SPISSEL7 Value */ +/* SPI_RWC */ +#define SPI_RWC_VALUE 0x0000FFFF /*Received Word-Count */ +/* SPI_RWCR */ +#define SPI_RWCR_VALUE 0x0000FFFF /*Received Word-Count Reload */ +/* SPI_TWC */ +#define SPI_TWC_VALUE 0x0000FFFF /*Transmitted Word-Count */ +/* SPI_TWCR */ +#define SPI_TWCR_VALUE 0x0000FFFF /*Transmitted Word-Count Reload */ +/* SPI_IMASK */ +#define SPI_IMSK_RUWM 0x00000002 /*Receive Water-Mark Interrupt Mask */ +#define SPI_IMSK_TUWM 0x00000004 /*Transmit Water-Mark Interrupt Mask */ +#define SPI_IMSK_ROM 0x00000010 /*Receive Over-Run Interrupt Mask */ +#define SPI_IMSK_TUM 0x00000020 /*Transmit Under-Run Interrupt Mask */ +#define SPI_IMSK_TCM 0x00000040 /*Transmit Collision Interrupt Mask */ +#define SPI_IMSK_MFM 0x00000080 /*Mode Fault Interrupt Mask */ +#define SPI_IMSK_RSM 0x00000100 /*Receive Start Interrupt Mask */ +#define SPI_IMSK_TSM 0x00000200 /*Transmit Start Interrupt Mask */ +#define SPI_IMSK_RFM 0x00000400 /*Receive Finish Interrupt Mask */ +#define SPI_IMSK_TFM 0x00000800 /*Transmit Finish Interrupt Mask */ +/* SPI_IMASKCL */ +#define SPI_IMSK_CLR_RUW 0x00000002 /*Receive Water-Mark Interrupt Mask */ +#define SPI_IMSK_CLR_TUWM 0x00000004 /*Transmit Water-Mark Interrupt Mask */ +#define SPI_IMSK_CLR_ROM 0x00000010 /*Receive Over-Run Interrupt Mask */ +#define SPI_IMSK_CLR_TUM 0x00000020 /*Transmit Under-Run Interrupt Mask */ +#define SPI_IMSK_CLR_TCM 0x00000040 /*Transmit Collision Interrupt Mask */ +#define SPI_IMSK_CLR_MFM 0x00000080 /*Mode Fault Interrupt Mask */ +#define SPI_IMSK_CLR_RSM 0x00000100 /*Receive Start Interrupt Mask */ +#define SPI_IMSK_CLR_TSM 0x00000200 /*Transmit Start Interrupt Mask */ +#define SPI_IMSK_CLR_RFM 0x00000400 /*Receive Finish Interrupt Mask */ +#define SPI_IMSK_CLR_TFM 0x00000800 /*Transmit Finish Interrupt Mask */ +/* SPI_IMASKST */ +#define SPI_IMSK_SET_RUWM 0x00000002 /*Receive Water-Mark Interrupt Mask */ +#define SPI_IMSK_SET_TUWM 0x00000004 /*Transmit Water-Mark Interrupt Mask */ +#define SPI_IMSK_SET_ROM 0x00000010 /*Receive Over-Run Interrupt Mask */ +#define SPI_IMSK_SET_TUM 0x00000020 /*Transmit Under-Run Interrupt Mask */ +#define SPI_IMSK_SET_TCM 0x00000040 /*Transmit Collision Interrupt Mask */ +#define SPI_IMSK_SET_MFM 0x00000080 /*Mode Fault Interrupt Mask */ +#define SPI_IMSK_SET_RSM 0x00000100 /*Receive Start Interrupt Mask */ +#define SPI_IMSK_SET_TSM 0x00000200 /*Transmit Start Interrupt Mask */ +#define SPI_IMSK_SET_RFM 0x00000400 /*Receive Finish Interrupt Mask */ +#define SPI_IMSK_SET_TFM 0x00000800 /*Transmit Finish Interrupt Mask */ +/* SPI_STATUS */ +#define SPI_STAT_SPIF 0x00000001 /*SPI Finished */ +#define SPI_STAT_RUWM 0x00000002 /*Receive Water-Mark Breached */ +#define SPI_STAT_TUWM 0x00000004 /*Transmit Water-Mark Breached */ +#define SPI_STAT_ROE 0x00000010 /*Receive Over-Run Indication */ +#define SPI_STAT_TUE 0x00000020 /*Transmit Under-Run Indication */ +#define SPI_STAT_TCE 0x00000040 /*Transmit Collision Indication */ +#define SPI_STAT_MODF 0x00000080 /*Mode Fault Indication */ +#define SPI_STAT_RS 0x00000100 /*Receive Start Indication */ +#define SPI_STAT_TS 0x00000200 /*Transmit Start Indication */ +#define SPI_STAT_RF 0x00000400 /*Receive Finish Indication */ +#define SPI_STAT_TF 0x00000800 /*Transmit Finish Indication */ +#define SPI_STAT_RFS 0x00007000 /*SPI_RFIFO status */ +#define SPI_STAT_RFIFO_EMPTY 0x00000000 /*RFS: RFIFO Empty */ +#define SPI_STAT_RFIFO_25 0x00001000 /*RFS: RFIFO 25% Full */ +#define SPI_STAT_RFIFO_50 0x00002000 /*RFS: RFIFO 50% Full */ +#define SPI_STAT_RFIFO_75 0x00003000 /*RFS: RFIFO 75% Full */ +#define SPI_STAT_RFIFO_FULL 0x00004000 /*RFS: RFIFO Full */ +#define SPI_STAT_TFS 0x00070000 /*SPI_TFIFO status */ +#define SPI_STAT_TFIFO_FULL 0x00000000 /*TFS: TFIFO full */ +#define SPI_STAT_TFIFO_25 0x00010000 /*TFS: TFIFO 25% empty */ +#define SPI_STAT_TFIFO_50 0x00020000 /*TFS: TFIFO 50% empty */ +#define SPI_STAT_TFIFO_75 0x00030000 /*TFS: TFIFO 75% empty */ +#define SPI_STAT_TFIFO_EMPTY 0x00040000 /*TFS: TFIFO empty */ +#define SPI_STAT_FCS 0x00100000 /*Flow-Control Stall Indication */ +#define SPI_STAT_RFE 0x00400000 /*SPI_RFIFO Empty */ +#define SPI_STAT_TFF 0x00800000 /*SPI_TFIFO Full */ +/* SPI_ILAT */ +#define SPI_ILAT_RUWMI 0x00000002 /*Receive Water Mark Interrupt */ +#define SPI_ILAT_TUWMI 0x00000004 /*Transmit Water Mark Interrupt */ +#define SPI_ILAT_ROI 0x00000010 /*Receive Over-Run Indication */ +#define SPI_ILAT_TUI 0x00000020 /*Transmit Under-Run Indication */ +#define SPI_ILAT_TCI 0x00000040 /*Transmit Collision Indication */ +#define SPI_ILAT_MFI 0x00000080 /*Mode Fault Indication */ +#define SPI_ILAT_RSI 0x00000100 /*Receive Start Indication */ +#define SPI_ILAT_TSI 0x00000200 /*Transmit Start Indication */ +#define SPI_ILAT_RFI 0x00000400 /*Receive Finish Indication */ +#define SPI_ILAT_TFI 0x00000800 /*Transmit Finish Indication */ +/* SPI_ILATCL */ +#define SPI_ILAT_CLR_RUWMI 0x00000002 /*Receive Water Mark Interrupt */ +#define SPI_ILAT_CLR_TUWMI 0x00000004 /*Transmit Water Mark Interrupt */ +#define SPI_ILAT_CLR_ROI 0x00000010 /*Receive Over-Run Indication */ +#define SPI_ILAT_CLR_TUI 0x00000020 /*Transmit Under-Run Indication */ +#define SPI_ILAT_CLR_TCI 0x00000040 /*Transmit Collision Indication */ +#define SPI_ILAT_CLR_MFI 0x00000080 /*Mode Fault Indication */ +#define SPI_ILAT_CLR_RSI 0x00000100 /*Receive Start Indication */ +#define SPI_ILAT_CLR_TSI 0x00000200 /*Transmit Start Indication */ +#define SPI_ILAT_CLR_RFI 0x00000400 /*Receive Finish Indication */ +#define SPI_ILAT_CLR_TFI 0x00000800 /*Transmit Finish Indication */ +/* SPI_MMRDH */ +#define SPI_MMRDH_MERGE 0x04000000 /*Merge Enable */ +#define SPI_MMRDH_DMY_SZ 0x00007000 /*Bytes of Dummy */ +#define SPI_MMRDH_ADDR_PINS 0x00000800 /*Pins used for Address */ +#define SPI_MMRDH_ADDR_SZ 0x00000700 /*Bytes of Read Address */ +#define SPI_MMRDH_OPCODE 0x000000FF /*Read Opcode */ + +#define SPI_MMRDH_TRIDMY_OFF 24 /*Bytes of Dummy offset */ +#define SPI_MMRDH_DMY_SZ_OFF 12 /*Bytes of Dummy offset */ +#define SPI_MMRDH_ADDR_SZ_OFF 8 /*Bytes of Read Address offset */ + +#define BIT_SSEL_VAL(x) ((1 << 8) << (x)) /* Slave Select input value bit */ +#define BIT_SSEL_EN(x) (1 << (x)) /* Slave Select enable bit*/ + +struct adi_spi_regs { + u32 revid; + u32 control; + u32 rx_control; + u32 tx_control; + u32 clock; + u32 delay; + u32 ssel; + u32 rwc; + u32 rwcr; + u32 twc; + u32 twcr; + u32 reserved0; + u32 emask; + u32 emaskcl; + u32 emaskst; + u32 reserved1; + u32 status; + u32 elat; + u32 elatcl; + u32 reserved2; + u32 rfifo; + u32 reserved3; + u32 tfifo; + u32 reserved4; + u32 mmrdh; + u32 mmtop; +}; + +struct adi_spi_platdata { + u32 max_hz; + u32 bus_num; + struct adi_spi_regs __iomem *regs; +}; + +struct adi_spi_priv { + u32 control; + u32 clock; + u32 bus_num; + u32 max_cs; + struct adi_spi_regs __iomem *regs; +}; + +/** + * By convention, this driver uses the same CS numbering that is used with the SSEL bit + * definitions (both here and in the TRM on which this is based), which are 1-indexed not + * 0-indexed. The valid CS range is therefore [1,max_cs], in contrast with other drivers + * where it is [0,max_cs-1]. + */ +static int adi_spi_cs_info(struct udevice *bus, uint cs, + struct spi_cs_info *info) +{ + struct adi_spi_priv *priv = dev_get_priv(bus); + + if (cs == 0 || cs > priv->max_cs) { + dev_err(bus, "invalid chipselect %u\n", cs); + return -EINVAL; + } + + return 0; +} + +static int adi_spi_of_to_plat(struct udevice *bus) +{ + struct adi_spi_platdata *plat = dev_get_plat(bus); + fdt_addr_t addr; + + plat->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 500000); + plat->bus_num = dev_read_u32_default(bus, "bus-num", 0); + addr = dev_read_addr(bus); + + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->regs = map_sysmem(addr, sizeof(*plat->regs)); + + return 0; +} + +static int adi_spi_probe(struct udevice *bus) +{ + struct adi_spi_platdata *plat = dev_get_plat(bus); + struct adi_spi_priv *priv = dev_get_priv(bus); + + priv->bus_num = plat->bus_num; + priv->regs = plat->regs; + priv->max_cs = dev_read_u32_default(bus, "num-cs", MAX_CTRL_CS); + + iowrite32(0x0, &plat->regs->control); + iowrite32(0x0, &plat->regs->rx_control); + iowrite32(0x0, &plat->regs->tx_control); + + return 0; +} + +static int adi_spi_remove(struct udevice *dev) +{ + return -ENODEV; +} + +static int adi_spi_claim_bus(struct udevice *dev) +{ + struct adi_spi_priv *priv; + struct udevice *bus = dev->parent; + + priv = dev_get_priv(bus); + + debug("%s: control:%i clock:%i\n", + __func__, priv->control, priv->clock); + + iowrite32(priv->control, &priv->regs->control); + iowrite32(priv->clock, &priv->regs->clock); + iowrite32(0x0, &priv->regs->delay); + + return 0; +} + +static int adi_spi_release_bus(struct udevice *dev) +{ + struct adi_spi_priv *priv; + struct udevice *bus = dev->parent; + + priv = dev_get_priv(bus); + + debug("%s: control:%i clock:%i\n", + __func__, priv->control, priv->clock); + + iowrite32(0x0, &priv->regs->rx_control); + iowrite32(0x0, &priv->regs->tx_control); + iowrite32(0x0, &priv->regs->control); + + return 0; +} + +void adi_spi_enable_ssel(struct adi_spi_priv *priv, int cs) +{ + setbits_32(&priv->regs->ssel, BIT_SSEL_EN(cs)); +} + +void adi_spi_set_ssel(struct adi_spi_priv *priv, int cs, int high) +{ + if (high) + setbits_32(&priv->regs->ssel, BIT_SSEL_VAL(cs)); + else + clrbits_32(&priv->regs->ssel, BIT_SSEL_VAL(cs)); +} + +void adi_spi_cs_activate(struct adi_spi_priv *priv, struct dm_spi_slave_plat *slave_plat) +{ + bool high = slave_plat->mode & SPI_CS_HIGH; + + adi_spi_set_ssel(priv, slave_plat->cs[0], high); + adi_spi_enable_ssel(priv, slave_plat->cs[0]); +} + +void adi_spi_cs_deactivate(struct adi_spi_priv *priv, struct dm_spi_slave_plat *slave_plat) +{ + bool high = slave_plat->mode & SPI_CS_HIGH; + + /* invert CS for matching SSEL to deactivate */ + adi_spi_set_ssel(priv, slave_plat->cs[0], !high); +} + +static void discard_rx_fifo_contents(struct adi_spi_regs *regs) +{ + while (!(ioread32(®s->status) & SPI_STAT_RFE)) + ioread32(®s->rfifo); +} + +static int adi_spi_fifo_mio_xfer(struct adi_spi_priv *priv, const u8 *tx, u8 *rx, + uint bytes, uint32_t mio_mode) +{ + u8 value; + + /* switch current SPI transfer to mio SPI mode */ + clrsetbits_32(&priv->regs->control, SPI_CTL_SOSI, mio_mode); + /* + * Data can only be transferred in one direction in multi-io SPI + * modes, trigger the transfer in respective direction. + */ + if (rx) { + iowrite32(0x0, &priv->regs->tx_control); + iowrite32(SPI_RXCTL_REN | SPI_RXCTL_RTI, &priv->regs->rx_control); + + while (bytes--) { + while (ioread32(&priv->regs->status) & + SPI_STAT_RFE) + if (ctrlc()) + return -1; + value = ioread32(&priv->regs->rfifo); + *rx++ = value; + } + } else if (tx) { + iowrite32(0x0, &priv->regs->rx_control); + iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI, &priv->regs->tx_control); + + while (bytes--) { + value = *tx++; + iowrite32(value, &priv->regs->tfifo); + while (ioread32(&priv->regs->status) & + SPI_STAT_TFF) + if (ctrlc()) + return -1; + } + + /* Wait till the tfifo is empty */ + while ((ioread32(&priv->regs->status) & SPI_STAT_TFS) != SPI_STAT_TFIFO_EMPTY) + if (ctrlc()) + return -1; + } else { + return -1; + } + return 0; +} + +static int adi_spi_fifo_1x_xfer(struct adi_spi_priv *priv, const u8 *tx, u8 *rx, + uint bytes) +{ + u8 value; + + /* + * Set current SPI transfer in normal mode and trigger + * the bi-direction transfer by tx write operation. + */ + iowrite32(priv->control, &priv->regs->control); + iowrite32(SPI_RXCTL_REN, &priv->regs->rx_control); + iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI, &priv->regs->tx_control); + + while (bytes--) { + value = (tx ? *tx++ : SPI_IDLE_VAL); + debug("%s: tx:%x ", __func__, value); + iowrite32(value, &priv->regs->tfifo); + while (ioread32(&priv->regs->status) & SPI_STAT_RFE) + if (ctrlc()) + return -1; + value = ioread32(&priv->regs->rfifo); + if (rx) + *rx++ = value; + debug("rx:%x\n", value); + } + return 0; +} + +static int adi_spi_fifo_xfer(struct adi_spi_priv *priv, int buswidth, + const u8 *tx, u8 *rx, uint bytes) +{ + switch (buswidth) { + case 1: + return adi_spi_fifo_1x_xfer(priv, tx, rx, bytes); + case 2: + return adi_spi_fifo_mio_xfer(priv, tx, rx, bytes, SPI_CTL_MIO_DUAL); + case 4: + return adi_spi_fifo_mio_xfer(priv, tx, rx, bytes, SPI_CTL_MIO_QUAD); + default: + return -ENOTSUPP; + } +} + +static int adi_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct udevice *bus = dev->parent; + struct adi_spi_priv *priv = dev_get_priv(bus); + struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); + + const u8 *tx = dout; + u8 *rx = din; + uint bytes = bitlen / 8; + int ret = 0; + + debug("%s: bus_num:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__, + priv->bus_num, slave_plat->cs[0], bitlen, bytes, flags); + + if (flags & SPI_XFER_BEGIN) + adi_spi_cs_activate(priv, slave_plat); + + if (bitlen == 0) + goto done; + + /* we can only do 8 bit transfers */ + if (bitlen % 8) { + flags |= SPI_XFER_END; + goto done; + } + + /* Discard invalid rx data and empty rfifo */ + discard_rx_fifo_contents(priv->regs); + + ret = adi_spi_fifo_1x_xfer(priv, tx, rx, bytes); + + done: + if (flags & SPI_XFER_END) + adi_spi_cs_deactivate(priv, slave_plat); + + return ret; +} + +static int adi_spi_set_speed(struct udevice *bus, uint speed) +{ + struct adi_spi_platdata *plat = dev_get_plat(bus); + struct adi_spi_priv *priv = dev_get_priv(bus); + int ret; + u32 clock, spi_base_clk; + struct clk spi_clk; + + ret = clk_get_by_name(bus, "spi", &spi_clk); + if (ret < 0) { + dev_err(bus, "Can't get SPI clk: %d\n", ret); + return ret; + } + spi_base_clk = clk_get_rate(&spi_clk); + + if (speed > plat->max_hz) + speed = plat->max_hz; + + if (speed > spi_base_clk) + return -ENODEV; + + clock = spi_base_clk / speed; + if (clock) + clock--; + + priv->clock = clock; + + debug("%s: priv->clock: %x, speed: %x, get_spi_clk(): %x\n", + __func__, clock, speed, spi_base_clk); + + return 0; +} + +static int adi_spi_set_mode(struct udevice *bus, uint mode) +{ + struct adi_spi_priv *priv = dev_get_priv(bus); + u32 reg; + + reg = SPI_CTL_EN | SPI_CTL_MSTR; + if (mode & SPI_CPHA) + reg |= SPI_CTL_CPHA; + if (mode & SPI_CPOL) + reg |= SPI_CTL_CPOL; + if (mode & SPI_LSB_FIRST) + reg |= SPI_CTL_LSBF; + reg &= ~SPI_CTL_ASSEL; + + priv->control = reg; + + debug("%s: control=%d, cs_pol=%d\n", __func__, reg, mode & SPI_CS_HIGH ? 1 : 0); + + return 0; +} + +/** + * U-boot's version of spi-mem does not support mixed bus-width + * commands nor anything more than 1x mode. + * Using a custom exec_op implementation, we can support it. + */ +static int adi_spi_mem_exec_op(struct spi_slave *slave, + const struct spi_mem_op *op) +{ + int rv = 0; + struct udevice *bus = slave->dev->parent; + struct adi_spi_priv *priv = dev_get_priv(bus); + struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(slave->dev); + u8 tmpbuf[64]; + int i; + + if ((op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes) > + sizeof(tmpbuf)) + return -ENOMEM; + + for (i = 0; i < op->cmd.nbytes; i++) + tmpbuf[i] = op->cmd.opcode >> + (8 * (op->cmd.nbytes - i - 1)); + for (i = 0; i < op->addr.nbytes; i++) + tmpbuf[i + op->cmd.nbytes] = op->addr.val >> + (8 * (op->addr.nbytes - i - 1)); + memset(tmpbuf + op->addr.nbytes + op->cmd.nbytes, 0xff, + op->dummy.nbytes); + + adi_spi_cs_activate(priv, slave_plat); + discard_rx_fifo_contents(priv->regs); + + if (op->cmd.nbytes) { + rv = adi_spi_fifo_xfer(priv, op->cmd.buswidth, + tmpbuf, NULL, op->cmd.nbytes); + if (rv != 0) + goto cleanup; + } + + if (op->addr.nbytes) { + rv = adi_spi_fifo_xfer(priv, op->addr.buswidth, + tmpbuf + op->cmd.nbytes, NULL, + op->addr.nbytes); + if (rv != 0) + goto cleanup; + } + + if (op->dummy.nbytes) { + rv = adi_spi_fifo_xfer(priv, op->dummy.buswidth, + tmpbuf + op->cmd.nbytes + + op->addr.nbytes, + NULL, op->dummy.nbytes); + if (rv != 0) + goto cleanup; + } + + if (op->data.dir == SPI_MEM_DATA_IN) + rv = adi_spi_fifo_xfer(priv, op->data.buswidth, + NULL, op->data.buf.in, + op->data.nbytes); + else if (op->data.dir == SPI_MEM_DATA_OUT) + rv = adi_spi_fifo_xfer(priv, op->data.buswidth, + op->data.buf.out, NULL, + op->data.nbytes); + +cleanup: + adi_spi_cs_deactivate(priv, slave_plat); + return rv; +} + +static const struct spi_controller_mem_ops adi_spi_mem_ops = { + .exec_op = adi_spi_mem_exec_op, +}; + +static const struct dm_spi_ops adi_spi_ops = { + .claim_bus = adi_spi_claim_bus, + .release_bus = adi_spi_release_bus, + .xfer = adi_spi_xfer, + .set_speed = adi_spi_set_speed, + .set_mode = adi_spi_set_mode, + .cs_info = adi_spi_cs_info, + .mem_ops = &adi_spi_mem_ops, +}; + +static const struct udevice_id adi_spi_ids[] = { + { .compatible = "adi,spi3" }, + { } +}; + +U_BOOT_DRIVER(adi_spi3) = { + .name = "adi_spi3", + .id = UCLASS_SPI, + .of_match = adi_spi_ids, + .ops = &adi_spi_ops, + .of_to_plat = adi_spi_of_to_plat, + .probe = adi_spi_probe, + .remove = adi_spi_remove, + .plat_auto = sizeof(struct adi_spi_platdata), + .priv_auto = sizeof(struct adi_spi_priv), + .per_child_auto = sizeof(struct spi_slave), +}; diff --git a/drivers/sysinfo/Kconfig b/drivers/sysinfo/Kconfig index 2030e4babc9..df83df69ffb 100644 --- a/drivers/sysinfo/Kconfig +++ b/drivers/sysinfo/Kconfig @@ -31,6 +31,13 @@ config SYSINFO_RCAR3 help Support querying SoC version information for Renesas R-Car Gen3. +config SYSINFO_IOT2050 + bool "Enable sysinfo driver for the Siemens IOT2050" + depends on TARGET_IOT2050_A53 + default y if TARGET_IOT2050_A53 + help + Support querying device information for Siemens IOT2050. + config SYSINFO_SANDBOX bool "Enable sysinfo driver for the Sandbox board" help diff --git a/drivers/sysinfo/Makefile b/drivers/sysinfo/Makefile index 680dde77fe8..26ca3150999 100644 --- a/drivers/sysinfo/Makefile +++ b/drivers/sysinfo/Makefile @@ -5,6 +5,7 @@ obj-y += sysinfo-uclass.o obj-$(CONFIG_SYSINFO_GAZERBEAM) += gazerbeam.o obj-$(CONFIG_SYSINFO_GPIO) += gpio.o +obj-$(CONFIG_SYSINFO_IOT2050) += iot2050.o obj-$(CONFIG_SYSINFO_RCAR3) += rcar3.o obj-$(CONFIG_SYSINFO_SANDBOX) += sandbox.o obj-$(CONFIG_SYSINFO_SMBIOS) += smbios.o diff --git a/drivers/sysinfo/iot2050.c b/drivers/sysinfo/iot2050.c new file mode 100644 index 00000000000..579a9f4711d --- /dev/null +++ b/drivers/sysinfo/iot2050.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Siemens AG, 2025 + */ + +#include <dm.h> +#include <sysinfo.h> +#include <net.h> +#include <u-boot/uuid.h> +#include <asm/arch/hardware.h> + +#include "iot2050.h" + +#define IOT2050_INFO_MAGIC 0x20502050 + +#define IOT2050_UUID_STR_LEN (32) + +struct iot2050_info { + u32 magic; + u16 size; + char name[20 + 1]; + char serial[16 + 1]; + char mlfb[18 + 1]; + char uuid[IOT2050_UUID_STR_LEN + 1]; + char a5e[18 + 1]; + u8 mac_addr_cnt; + u8 mac_addr[8][ARP_HLEN]; + char seboot_version[40 + 1]; + u8 padding[3]; + u32 ddr_size_mb; +} __packed; + +/** + * struct sysinfo_iot2050_priv - sysinfo private data + * @info: iot2050 board info + */ +struct sysinfo_iot2050_priv { + struct iot2050_info *info; + u8 uuid_smbios[16]; +}; + +static int sysinfo_iot2050_detect(struct udevice *dev) +{ + struct sysinfo_iot2050_priv *priv = dev_get_priv(dev); + + if (!priv->info || priv->info->magic != IOT2050_INFO_MAGIC) + return -EFAULT; + + return 0; +} + +static int sysinfo_iot2050_get_str(struct udevice *dev, int id, size_t size, + char *val) +{ + struct sysinfo_iot2050_priv *priv = dev_get_priv(dev); + + switch (id) { + case BOARD_NAME: + case SYSID_SM_BASEBOARD_VERSION: + strlcpy(val, priv->info->name, size); + break; + case SYSID_SM_SYSTEM_SERIAL: + strlcpy(val, priv->info->serial, size); + break; + case BOARD_MLFB: + case SYSID_SM_SYSTEM_VERSION: + strlcpy(val, priv->info->mlfb, size); + break; + case BOARD_UUID: + strlcpy(val, priv->info->uuid, size); + break; + case BOARD_A5E: + case SYSID_SM_BASEBOARD_PRODUCT: + strlcpy(val, priv->info->a5e, size); + break; + case BOARD_SEBOOT_VER: + case SYSID_PRIOR_STAGE_VERSION: + strlcpy(val, priv->info->seboot_version, size); + break; + default: + return -EINVAL; + }; + + val[size - 1] = '\0'; + return 0; +} + +static int sysinfo_iot2050_get_int(struct udevice *dev, int id, int *val) +{ + struct sysinfo_iot2050_priv *priv = dev_get_priv(dev); + + switch (id) { + case SYSID_BOARD_RAM_SIZE_MB: + *val = priv->info->ddr_size_mb; + return 0; + default: + return -EINVAL; + }; +} + +static int sysinfo_iot2050_get_data(struct udevice *dev, int id, void **data, + size_t *size) +{ + struct sysinfo_iot2050_priv *priv = dev_get_priv(dev); + + switch (id) { + case SYSID_SM_SYSTEM_UUID: + *data = priv->uuid_smbios; + *size = 16; + return 0; + default: + return -EINVAL; + }; +} + +static int sysinfo_iot2050_get_item_count(struct udevice *dev, int id) +{ + struct sysinfo_iot2050_priv *priv = dev_get_priv(dev); + + switch (id) { + case SYSID_BOARD_MAC_ADDR: + return priv->info->mac_addr_cnt; + default: + return -EINVAL; + }; +} + +static int sysinfo_iot2050_get_data_by_index(struct udevice *dev, int id, + int index, void **data, + size_t *size) +{ + struct sysinfo_iot2050_priv *priv = dev_get_priv(dev); + + switch (id) { + case SYSID_BOARD_MAC_ADDR: + if (index >= priv->info->mac_addr_cnt) + return -EINVAL; + *data = priv->info->mac_addr[index]; + *size = ARP_HLEN; + return 0; + default: + return -EINVAL; + }; +} + +static const struct sysinfo_ops sysinfo_iot2050_ops = { + .detect = sysinfo_iot2050_detect, + .get_str = sysinfo_iot2050_get_str, + .get_int = sysinfo_iot2050_get_int, + .get_data = sysinfo_iot2050_get_data, + .get_item_count = sysinfo_iot2050_get_item_count, + .get_data_by_index = sysinfo_iot2050_get_data_by_index, +}; + +/** + * @brief Convert the IOT2050 UUID string to the SMBIOS format + * + * @param uuid_raw The IOT2050 UUID string parsed from the eeprom + * @param uuid_smbios The buffer to hold the SMBIOS formatted UUID + */ +static void sysinfo_iot2050_convert_uuid(const char *uuid_iot2050, + u8 *uuid_smbios) +{ + char uuid_rfc4122_str[IOT2050_UUID_STR_LEN + 4 + 1] = {0}; + char *tmp = uuid_rfc4122_str; + + for (int i = 0; i < 16; i++) { + memcpy(tmp, uuid_iot2050 + i * 2, 2); + tmp += 2; + if (i == 3 || i == 5 || i == 7 || i == 9) + *tmp++ = '-'; + } + uuid_str_to_bin(uuid_rfc4122_str, uuid_smbios, UUID_STR_FORMAT_GUID); +} + +static int sysinfo_iot2050_probe(struct udevice *dev) +{ + struct sysinfo_iot2050_priv *priv = dev_get_priv(dev); + unsigned long offset; + + offset = dev_read_u32_default(dev, "offset", + TI_SRAM_SCRATCH_BOARD_EEPROM_START); + priv->info = (struct iot2050_info *)offset; + + sysinfo_iot2050_convert_uuid(priv->info->uuid, priv->uuid_smbios); + + return 0; +} + +static const struct udevice_id sysinfo_iot2050_ids[] = { + { .compatible = "siemens,sysinfo-iot2050" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sysinfo_iot2050) = { + .name = "sysinfo_iot2050", + .id = UCLASS_SYSINFO, + .of_match = sysinfo_iot2050_ids, + .ops = &sysinfo_iot2050_ops, + .priv_auto = sizeof(struct sysinfo_iot2050_priv), + .probe = sysinfo_iot2050_probe, +}; diff --git a/drivers/sysinfo/iot2050.h b/drivers/sysinfo/iot2050.h new file mode 100644 index 00000000000..657221db096 --- /dev/null +++ b/drivers/sysinfo/iot2050.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Siemens AG, 2025 + */ + +#include <sysinfo.h> + +enum sysinfo_id_iot2050 { + BOARD_MLFB = SYSID_USER, + BOARD_A5E, + BOARD_NAME, + BOARD_UUID, + BOARD_SEBOOT_VER, +}; diff --git a/drivers/sysinfo/sysinfo-uclass.c b/drivers/sysinfo/sysinfo-uclass.c index 3c0cd51273e..f04998ef8bb 100644 --- a/drivers/sysinfo/sysinfo-uclass.c +++ b/drivers/sysinfo/sysinfo-uclass.c @@ -119,6 +119,35 @@ int sysinfo_get_data(struct udevice *dev, int id, void **data, size_t *size) return ops->get_data(dev, id, data, size); } +int sysinfo_get_item_count(struct udevice *dev, int id) +{ + struct sysinfo_priv *priv = dev_get_uclass_priv(dev); + struct sysinfo_ops *ops = sysinfo_get_ops(dev); + + if (!priv->detected) + return -EPERM; + + if (!ops->get_item_count) + return -ENOSYS; + + return ops->get_item_count(dev, id); +} + +int sysinfo_get_data_by_index(struct udevice *dev, int id, int index, + void **data, size_t *size) +{ + struct sysinfo_priv *priv = dev_get_uclass_priv(dev); + struct sysinfo_ops *ops = sysinfo_get_ops(dev); + + if (!priv->detected) + return -EPERM; + + if (!ops->get_data_by_index) + return -ENOSYS; + + return ops->get_data_by_index(dev, id, index, data, size); +} + UCLASS_DRIVER(sysinfo) = { .id = UCLASS_SYSINFO, .name = "sysinfo", diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 4bda224ff1a..db5f8895a33 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -35,7 +35,3 @@ endif endif obj-$(CONFIG_CI_UDC) += ci_udc.o - -# Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE -# This is really only N900 and USBTTY now. -obj-$(CONFIG_USB_DEVICE) += core.o ep0.o diff --git a/drivers/usb/gadget/core.c b/drivers/usb/gadget/core.c deleted file mode 100644 index bcb1ad3082c..00000000000 --- a/drivers/usb/gadget/core.c +++ /dev/null @@ -1,621 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * Based on - * linux/drivers/usbd/usbd.c.c - USB Device Core Layer - * - * Copyright (c) 2000, 2001, 2002 Lineo - * Copyright (c) 2001 Hewlett Packard - * - * By: - * Stuart Lynne <sl@lineo.com>, - * Tom Rushworth <tbr@lineo.com>, - * Bruce Balden <balden@lineo.com> - */ - -#include <log.h> -#include <malloc.h> -#include <serial.h> -#include <usbdevice.h> - -#define MAX_INTERFACES 2 - -int maxstrings = 20; - -/* Global variables ************************************************************************** */ - -struct usb_string_descriptor **usb_strings; - -int usb_devices; - -extern struct usb_function_driver ep0_driver; - -int registered_functions; -int registered_devices; - -__maybe_unused static char *usbd_device_events[] = { - "DEVICE_UNKNOWN", - "DEVICE_INIT", - "DEVICE_CREATE", - "DEVICE_HUB_CONFIGURED", - "DEVICE_RESET", - "DEVICE_ADDRESS_ASSIGNED", - "DEVICE_CONFIGURED", - "DEVICE_SET_INTERFACE", - "DEVICE_SET_FEATURE", - "DEVICE_CLEAR_FEATURE", - "DEVICE_DE_CONFIGURED", - "DEVICE_BUS_INACTIVE", - "DEVICE_BUS_ACTIVITY", - "DEVICE_POWER_INTERRUPTION", - "DEVICE_HUB_RESET", - "DEVICE_DESTROY", - "DEVICE_FUNCTION_PRIVATE", -}; - -__maybe_unused static char *usbd_device_status[] = { - "USBD_OPENING", - "USBD_OK", - "USBD_SUSPENDED", - "USBD_CLOSING", -}; - -#define USBD_DEVICE_STATUS(x) (((unsigned int)x <= USBD_CLOSING) ? usbd_device_status[x] : "UNKNOWN") - -/* Descriptor support functions ************************************************************** */ - -/** - * usbd_get_string - find and return a string descriptor - * @index: string index to return - * - * Find an indexed string and return a pointer to a it. - */ -struct usb_string_descriptor *usbd_get_string (__u8 index) -{ - if (index >= maxstrings) { - return NULL; - } - return usb_strings[index]; -} - -/* Access to device descriptor functions ***************************************************** */ - -/* * - * usbd_device_configuration_instance - find a configuration instance for this device - * @device: - * @configuration: index to configuration, 0 - N-1 - * - * Get specifed device configuration. Index should be bConfigurationValue-1. - */ -static struct usb_configuration_instance *usbd_device_configuration_instance (struct usb_device_instance *device, - unsigned int port, unsigned int configuration) -{ - if (configuration >= device->configurations) - return NULL; - - return device->configuration_instance_array + configuration; -} - -/* * - * usbd_device_interface_instance - * @device: - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * - * Return the specified interface descriptor for the specified device. - */ -struct usb_interface_instance *usbd_device_interface_instance (struct usb_device_instance *device, int port, int configuration, int interface) -{ - struct usb_configuration_instance *configuration_instance; - - if ((configuration_instance = usbd_device_configuration_instance (device, port, configuration)) == NULL) { - return NULL; - } - if (interface >= configuration_instance->interfaces) { - return NULL; - } - return configuration_instance->interface_instance_array + interface; -} - -/* * - * usbd_device_alternate_descriptor_list - * @device: - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: alternate setting - * - * Return the specified alternate descriptor for the specified device. - */ -struct usb_alternate_instance *usbd_device_alternate_instance (struct usb_device_instance *device, int port, int configuration, int interface, int alternate) -{ - struct usb_interface_instance *interface_instance; - - if ((interface_instance = usbd_device_interface_instance (device, port, configuration, interface)) == NULL) { - return NULL; - } - - if (alternate >= interface_instance->alternates) { - return NULL; - } - - return interface_instance->alternates_instance_array + alternate; -} - -/* * - * usbd_device_device_descriptor - * @device: which device - * @configuration: index to configuration, 0 - N-1 - * @port: which port - * - * Return the specified configuration descriptor for the specified device. - */ -struct usb_device_descriptor *usbd_device_device_descriptor (struct usb_device_instance *device, int port) -{ - return (device->device_descriptor); -} - -/** - * usbd_device_configuration_descriptor - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * - * Return the specified configuration descriptor for the specified device. - */ -struct usb_configuration_descriptor *usbd_device_configuration_descriptor (struct - usb_device_instance - *device, int port, int configuration) -{ - struct usb_configuration_instance *configuration_instance; - if (!(configuration_instance = usbd_device_configuration_instance (device, port, configuration))) { - return NULL; - } - return (configuration_instance->configuration_descriptor); -} - -/** - * usbd_device_interface_descriptor - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: alternate setting - * - * Return the specified interface descriptor for the specified device. - */ -struct usb_interface_descriptor *usbd_device_interface_descriptor (struct usb_device_instance - *device, int port, int configuration, int interface, int alternate) -{ - struct usb_interface_instance *interface_instance; - if (!(interface_instance = usbd_device_interface_instance (device, port, configuration, interface))) { - return NULL; - } - if ((alternate < 0) || (alternate >= interface_instance->alternates)) { - return NULL; - } - return (interface_instance->alternates_instance_array[alternate].interface_descriptor); -} - -/** - * usbd_device_endpoint_descriptor_index - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: index setting - * @index: which index - * - * Return the specified endpoint descriptor for the specified device. - */ -struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor_index (struct usb_device_instance - *device, int port, int configuration, int interface, int alternate, int index) -{ - struct usb_alternate_instance *alternate_instance; - - if (!(alternate_instance = usbd_device_alternate_instance (device, port, configuration, interface, alternate))) { - return NULL; - } - if (index >= alternate_instance->endpoints) { - return NULL; - } - return *(alternate_instance->endpoints_descriptor_array + index); -} - -/** - * usbd_device_endpoint_transfersize - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @index: which index - * - * Return the specified endpoint transfer size; - */ -int usbd_device_endpoint_transfersize (struct usb_device_instance *device, int port, int configuration, int interface, int alternate, int index) -{ - struct usb_alternate_instance *alternate_instance; - - if (!(alternate_instance = usbd_device_alternate_instance (device, port, configuration, interface, alternate))) { - return 0; - } - if (index >= alternate_instance->endpoints) { - return 0; - } - return *(alternate_instance->endpoint_transfersize_array + index); -} - -/** - * usbd_device_endpoint_descriptor - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: alternate setting - * @endpoint: which endpoint - * - * Return the specified endpoint descriptor for the specified device. - */ -struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor (struct usb_device_instance *device, int port, int configuration, int interface, int alternate, int endpoint) -{ - struct usb_endpoint_descriptor *endpoint_descriptor; - int i; - - for (i = 0; !(endpoint_descriptor = usbd_device_endpoint_descriptor_index (device, port, configuration, interface, alternate, i)); i++) { - if (endpoint_descriptor->bEndpointAddress == endpoint) { - return endpoint_descriptor; - } - } - return NULL; -} - -/** - * usbd_endpoint_halted - * @device: point to struct usb_device_instance - * @endpoint: endpoint to check - * - * Return non-zero if endpoint is halted. - */ -int usbd_endpoint_halted (struct usb_device_instance *device, int endpoint) -{ - return (device->status == USB_STATUS_HALT); -} - -/** - * usbd_rcv_complete - complete a receive - * @endpoint: - * @len: - * @urb_bad: - * - * Called from rcv interrupt to complete. - */ -void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad) -{ - if (endpoint) { - struct urb *rcv_urb; - - /*usbdbg("len: %d urb: %p\n", len, endpoint->rcv_urb); */ - - /* if we had an urb then update actual_length, dispatch if neccessary */ - if ((rcv_urb = endpoint->rcv_urb)) { - - /*usbdbg("actual: %d buffer: %d\n", */ - /*rcv_urb->actual_length, rcv_urb->buffer_length); */ - - /* check the urb is ok, are we adding data less than the packetsize */ - if (!urb_bad && (len <= endpoint->rcv_packetSize)) { - /*usbdbg("updating actual_length by %d\n",len); */ - - /* increment the received data size */ - rcv_urb->actual_length += len; - - } else { - usberr(" RECV_ERROR actual: %d buffer: %d urb_bad: %d\n", - rcv_urb->actual_length, rcv_urb->buffer_length, urb_bad); - - rcv_urb->actual_length = 0; - rcv_urb->status = RECV_ERROR; - } - } else { - usberr("no rcv_urb!"); - } - } else { - usberr("no endpoint!"); - } - -} - -/** - * usbd_tx_complete - complete a transmit - * @endpoint: - * @resetart: - * - * Called from tx interrupt to complete. - */ -void usbd_tx_complete (struct usb_endpoint_instance *endpoint) -{ - if (endpoint) { - struct urb *tx_urb; - - /* if we have a tx_urb advance or reset, finish if complete */ - if ((tx_urb = endpoint->tx_urb)) { - int sent = endpoint->last; - endpoint->sent += sent; - endpoint->last -= sent; - - if( (endpoint->tx_urb->actual_length - endpoint->sent) <= 0 ) { - tx_urb->actual_length = 0; - endpoint->sent = 0; - endpoint->last = 0; - - /* Remove from active, save for re-use */ - urb_detach(tx_urb); - urb_append(&endpoint->done, tx_urb); - /*usbdbg("done->next %p, tx_urb %p, done %p", */ - /* endpoint->done.next, tx_urb, &endpoint->done); */ - - endpoint->tx_urb = first_urb_detached(&endpoint->tx); - if( endpoint->tx_urb ) { - endpoint->tx_queue--; - usbdbg("got urb from tx list"); - } - if( !endpoint->tx_urb ) { - /*usbdbg("taking urb from done list"); */ - endpoint->tx_urb = first_urb_detached(&endpoint->done); - } - if( !endpoint->tx_urb ) { - usbdbg("allocating new urb for tx_urb"); - endpoint->tx_urb = usbd_alloc_urb(tx_urb->device, endpoint); - } - } - } - } -} - -/* URB linked list functions ***************************************************** */ - -/* - * Initialize an urb_link to be a single element list. - * If the urb_link is being used as a distinguished list head - * the list is empty when the head is the only link in the list. - */ -void urb_link_init (urb_link * ul) -{ - if (ul) { - ul->prev = ul->next = ul; - } -} - -/* - * Detach an urb_link from a list, and set it - * up as a single element list, so no dangling - * pointers can be followed, and so it can be - * joined to another list if so desired. - */ -void urb_detach (struct urb *urb) -{ - if (urb) { - urb_link *ul = &urb->link; - ul->next->prev = ul->prev; - ul->prev->next = ul->next; - urb_link_init (ul); - } -} - -/* - * Return the first urb_link in a list with a distinguished - * head "hd", or NULL if the list is empty. This will also - * work as a predicate, returning NULL if empty, and non-NULL - * otherwise. - */ -urb_link *first_urb_link (urb_link * hd) -{ - urb_link *nx; - if (NULL != hd && NULL != (nx = hd->next) && nx != hd) { - /* There is at least one element in the list */ - /* (besides the distinguished head). */ - return (nx); - } - /* The list is empty */ - return (NULL); -} - -/* - * Return the first urb in a list with a distinguished - * head "hd", or NULL if the list is empty. - */ -struct urb *first_urb (urb_link * hd) -{ - urb_link *nx; - if (NULL == (nx = first_urb_link (hd))) { - /* The list is empty */ - return (NULL); - } - return (p2surround (struct urb, link, nx)); -} - -/* - * Detach and return the first urb in a list with a distinguished - * head "hd", or NULL if the list is empty. - * - */ -struct urb *first_urb_detached (urb_link * hd) -{ - struct urb *urb; - if ((urb = first_urb (hd))) { - urb_detach (urb); - } - return urb; -} - -/* - * Append an urb_link (or a whole list of - * urb_links) to the tail of another list - * of urb_links. - */ -void urb_append (urb_link * hd, struct urb *urb) -{ - if (hd && urb) { - urb_link *new = &urb->link; - - /* This allows the new urb to be a list of urbs, */ - /* with new pointing at the first, but the link */ - /* must be initialized. */ - /* Order is important here... */ - urb_link *pul = hd->prev; - new->prev->next = hd; - hd->prev = new->prev; - new->prev = pul; - pul->next = new; - } -} - -/* URB create/destroy functions ***************************************************** */ - -/** - * usbd_alloc_urb - allocate an URB appropriate for specified endpoint - * @device: device instance - * @endpoint: endpoint - * - * Allocate an urb structure. The usb device urb structure is used to - * contain all data associated with a transfer, including a setup packet for - * control transfers. - * - * NOTE: endpoint_address MUST contain a direction flag. - */ -struct urb *usbd_alloc_urb (struct usb_device_instance *device, - struct usb_endpoint_instance *endpoint) -{ - struct urb *urb; - - if (!(urb = (struct urb *) malloc (sizeof (struct urb)))) { - usberr (" F A T A L: malloc(%zu) FAILED!!!!", - sizeof (struct urb)); - return NULL; - } - - /* Fill in known fields */ - memset (urb, 0, sizeof (struct urb)); - urb->endpoint = endpoint; - urb->device = device; - urb->buffer = (u8 *) urb->buffer_data; - urb->buffer_length = sizeof (urb->buffer_data); - - urb_link_init (&urb->link); - - return urb; -} - -/** - * usbd_dealloc_urb - deallocate an URB and associated buffer - * @urb: pointer to an urb structure - * - * Deallocate an urb structure and associated data. - */ -void usbd_dealloc_urb (struct urb *urb) -{ - if (urb) { - free (urb); - } -} - -/* Event signaling functions ***************************************************** */ - -/** - * usbd_device_event - called to respond to various usb events - * @device: pointer to struct device - * @event: event to respond to - * - * Used by a Bus driver to indicate an event. - */ -void usbd_device_event_irq (struct usb_device_instance *device, usb_device_event_t event, int data) -{ - usb_device_state_t state; - - if (!device || !device->bus) { - usberr("(%p,%d) NULL device or device->bus", device, event); - return; - } - - state = device->device_state; - - usbinfo("%s", usbd_device_events[event]); - - switch (event) { - case DEVICE_UNKNOWN: - break; - case DEVICE_INIT: - device->device_state = STATE_INIT; - break; - - case DEVICE_CREATE: - device->device_state = STATE_ATTACHED; - break; - - case DEVICE_HUB_CONFIGURED: - device->device_state = STATE_POWERED; - break; - - case DEVICE_RESET: - device->device_state = STATE_DEFAULT; - device->address = 0; - break; - - case DEVICE_ADDRESS_ASSIGNED: - device->device_state = STATE_ADDRESSED; - break; - - case DEVICE_CONFIGURED: - device->device_state = STATE_CONFIGURED; - break; - - case DEVICE_DE_CONFIGURED: - device->device_state = STATE_ADDRESSED; - break; - - case DEVICE_BUS_INACTIVE: - if (device->status != USBD_CLOSING) { - device->status = USBD_SUSPENDED; - } - break; - case DEVICE_BUS_ACTIVITY: - if (device->status != USBD_CLOSING) { - device->status = USBD_OK; - } - break; - - case DEVICE_SET_INTERFACE: - break; - case DEVICE_SET_FEATURE: - break; - case DEVICE_CLEAR_FEATURE: - break; - - case DEVICE_POWER_INTERRUPTION: - device->device_state = STATE_POWERED; - break; - case DEVICE_HUB_RESET: - device->device_state = STATE_ATTACHED; - break; - case DEVICE_DESTROY: - device->device_state = STATE_UNKNOWN; - break; - - case DEVICE_FUNCTION_PRIVATE: - break; - - default: - usbdbg("event %d - not handled",event); - break; - } - debug("%s event: %d oldstate: %d newstate: %d status: %d address: %d", - device->name, event, state, - device->device_state, device->status, device->address); - - /* tell the bus interface driver */ - if( device->event ) { - /* usbdbg("calling device->event"); */ - device->event(device, event, data); - } -} diff --git a/drivers/usb/gadget/ep0.c b/drivers/usb/gadget/ep0.c deleted file mode 100644 index 8c7fc17c2ea..00000000000 --- a/drivers/usb/gadget/ep0.c +++ /dev/null @@ -1,619 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * (C) Copyright 2006 - * Bryan O'Donoghue, deckard@CodeHermit.ie - * - * Based on - * linux/drivers/usbd/ep0.c - * - * Copyright (c) 2000, 2001, 2002 Lineo - * Copyright (c) 2001 Hewlett Packard - * - * By: - * Stuart Lynne <sl@lineo.com>, - * Tom Rushworth <tbr@lineo.com>, - * Bruce Balden <balden@lineo.com> - */ - -/* - * This is the builtin ep0 control function. It implements all required functionality - * for responding to control requests (SETUP packets). - * - * XXX - * - * Currently we do not pass any SETUP packets (or other) to the configured - * function driver. This may need to change. - * - * XXX - * - * As alluded to above, a simple callback cdc_recv_setup has been implemented - * in the usb_device data structure to facilicate passing - * Common Device Class packets to a function driver. - * - * XXX - */ - -#include <serial.h> -#include <usbdevice.h> - -#if 0 -#define dbg_ep0(lvl,fmt,args...) serial_printf("[%s] %s:%d: "fmt"\n",__FILE__,__FUNCTION__,__LINE__,##args) -#else -#define dbg_ep0(lvl,fmt,args...) -#endif - -__maybe_unused static char *usbd_device_descriptors[] = { - "UNKNOWN", /* 0 */ - "DEVICE", /* 1 */ - "CONFIG", /* 2 */ - "STRING", /* 3 */ - "INTERFACE", /* 4 */ - "ENDPOINT", /* 5 */ - "DEVICE QUALIFIER", /* 6 */ - "OTHER SPEED", /* 7 */ - "INTERFACE POWER", /* 8 */ -}; - -#define USBD_DEVICE_DESCRIPTORS(x) (((unsigned int)x <= USB_DESCRIPTOR_TYPE_INTERFACE_POWER) ? \ - usbd_device_descriptors[x] : "UNKNOWN") - -__maybe_unused static char *usbd_device_states[] = { - "STATE_INIT", - "STATE_CREATED", - "STATE_ATTACHED", - "STATE_POWERED", - "STATE_DEFAULT", - "STATE_ADDRESSED", - "STATE_CONFIGURED", - "STATE_UNKNOWN", -}; - -#define USBD_DEVICE_STATE(x) (((unsigned int)x <= STATE_UNKNOWN) ? usbd_device_states[x] : "UNKNOWN") - -__maybe_unused static char *usbd_device_requests[] = { - "GET STATUS", /* 0 */ - "CLEAR FEATURE", /* 1 */ - "RESERVED", /* 2 */ - "SET FEATURE", /* 3 */ - "RESERVED", /* 4 */ - "SET ADDRESS", /* 5 */ - "GET DESCRIPTOR", /* 6 */ - "SET DESCRIPTOR", /* 7 */ - "GET CONFIGURATION", /* 8 */ - "SET CONFIGURATION", /* 9 */ - "GET INTERFACE", /* 10 */ - "SET INTERFACE", /* 11 */ - "SYNC FRAME", /* 12 */ -}; - -#define USBD_DEVICE_REQUESTS(x) (((unsigned int)x <= USB_REQ_SYNCH_FRAME) ? usbd_device_requests[x] : "UNKNOWN") - -/* EP0 Configuration Set ********************************************************************* */ - -/** - * ep0_get_status - fill in URB data with appropriate status - * @device: - * @urb: - * @index: - * @requesttype: - * - */ -static int ep0_get_status (struct usb_device_instance *device, - struct urb *urb, int index, int requesttype) -{ - char *cp; - - urb->actual_length = 2; - cp = (char*)urb->buffer; - cp[0] = cp[1] = 0; - - switch (requesttype) { - case USB_REQ_RECIPIENT_DEVICE: - cp[0] = USB_STATUS_SELFPOWERED; - break; - case USB_REQ_RECIPIENT_INTERFACE: - break; - case USB_REQ_RECIPIENT_ENDPOINT: - cp[0] = usbd_endpoint_halted (device, index); - break; - case USB_REQ_RECIPIENT_OTHER: - urb->actual_length = 0; - default: - break; - } - dbg_ep0 (2, "%02x %02x", cp[0], cp[1]); - return 0; -} - -/** - * ep0_get_one - * @device: - * @urb: - * @result: - * - * Set a single byte value in the urb send buffer. Return non-zero to signal - * a request error. - */ -static int ep0_get_one (struct usb_device_instance *device, struct urb *urb, - __u8 result) -{ - urb->actual_length = 1; /* XXX 2? */ - ((char *) urb->buffer)[0] = result; - return 0; -} - -/** - * copy_config - * @urb: pointer to urb - * @data: pointer to configuration data - * @length: length of data - * - * Copy configuration data to urb transfer buffer if there is room for it. - */ -void copy_config (struct urb *urb, void *data, int max_length, - int max_buf) -{ - int available; - int length; - - /*dbg_ep0(3, "-> actual: %d buf: %d max_buf: %d max_length: %d data: %p", */ - /* urb->actual_length, urb->buffer_length, max_buf, max_length, data); */ - - if (!data) { - dbg_ep0 (1, "data is NULL"); - return; - } - length = max_length; - - if (length > max_length) { - dbg_ep0 (1, "length: %d >= max_length: %d", length, - max_length); - return; - } - /*dbg_ep0(1, " actual: %d buf: %d max_buf: %d max_length: %d length: %d", */ - /* urb->actual_length, urb->buffer_length, max_buf, max_length, length); */ - - if ((available = - /*urb->buffer_length */ max_buf - urb->actual_length) <= 0) { - return; - } - /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */ - /* urb->actual_length, urb->buffer_length, max_buf, length, available); */ - - if (length > available) { - length = available; - } - /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */ - /* urb->actual_length, urb->buffer_length, max_buf, length, available); */ - - memcpy (urb->buffer + urb->actual_length, data, length); - urb->actual_length += length; - - dbg_ep0 (3, - "copy_config: <- actual: %d buf: %d max_buf: %d max_length: %d available: %d", - urb->actual_length, urb->buffer_length, max_buf, max_length, - available); -} - -/** - * ep0_get_descriptor - * @device: - * @urb: - * @max: - * @descriptor_type: - * @index: - * - * Called by ep0_rx_process for a get descriptor device command. Determine what - * descriptor is being requested, copy to send buffer. Return zero if ok to send, - * return non-zero to signal a request error. - */ -static int ep0_get_descriptor (struct usb_device_instance *device, - struct urb *urb, int max, int descriptor_type, - int index) -{ - int port = 0; /* XXX compound device */ - - /*dbg_ep0(3, "max: %x type: %x index: %x", max, descriptor_type, index); */ - - if (!urb || !urb->buffer || !urb->buffer_length - || (urb->buffer_length < 255)) { - dbg_ep0 (2, "invalid urb %p", urb); - return -1L; - } - - /* setup tx urb */ - urb->actual_length = 0; - - dbg_ep0 (2, "%s", USBD_DEVICE_DESCRIPTORS (descriptor_type)); - - switch (descriptor_type) { - case USB_DESCRIPTOR_TYPE_DEVICE: - { - struct usb_device_descriptor *device_descriptor; - if (! - (device_descriptor = - usbd_device_device_descriptor (device, port))) { - return -1; - } - /* copy descriptor for this device */ - copy_config (urb, device_descriptor, - sizeof (struct usb_device_descriptor), - max); - - /* correct the correct control endpoint 0 max packet size into the descriptor */ - device_descriptor = - (struct usb_device_descriptor *) urb->buffer; - - } - dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length); - break; - - case USB_DESCRIPTOR_TYPE_CONFIGURATION: - { - struct usb_configuration_descriptor - *configuration_descriptor; - struct usb_device_descriptor *device_descriptor; - if (! - (device_descriptor = - usbd_device_device_descriptor (device, port))) { - return -1; - } - /*dbg_ep0(2, "%d %d", index, device_descriptor->bNumConfigurations); */ - if (index >= device_descriptor->bNumConfigurations) { - dbg_ep0 (0, "index too large: %d >= %d", index, - device_descriptor-> - bNumConfigurations); - return -1; - } - - if (! - (configuration_descriptor = - usbd_device_configuration_descriptor (device, - port, - index))) { - dbg_ep0 (0, - "usbd_device_configuration_descriptor failed: %d", - index); - return -1; - } - dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength)); - copy_config (urb, configuration_descriptor, - - cpu_to_le16(configuration_descriptor->wTotalLength), - max); - } - - break; - - case USB_DESCRIPTOR_TYPE_STRING: - { - struct usb_string_descriptor *string_descriptor; - if (!(string_descriptor = usbd_get_string (index))) { - dbg_ep0(0, "Invalid string index %d\n", index); - return -1; - } - dbg_ep0(3, "string_descriptor: %p length %d", string_descriptor, string_descriptor->bLength); - copy_config (urb, string_descriptor, string_descriptor->bLength, max); - } - break; - case USB_DESCRIPTOR_TYPE_INTERFACE: - dbg_ep0(2, "USB_DESCRIPTOR_TYPE_INTERFACE - error not implemented\n"); - return -1; - case USB_DESCRIPTOR_TYPE_ENDPOINT: - dbg_ep0(2, "USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n"); - return -1; - case USB_DESCRIPTOR_TYPE_HID: - { - dbg_ep0(2, "USB_DESCRIPTOR_TYPE_HID - error not implemented\n"); - return -1; /* unsupported at this time */ -#if 0 - int bNumInterface = - le16_to_cpu (urb->device_request.wIndex); - int bAlternateSetting = 0; - int class = 0; - struct usb_class_descriptor *class_descriptor; - - if (!(class_descriptor = - usbd_device_class_descriptor_index (device, - port, 0, - bNumInterface, - bAlternateSetting, - class)) - || class_descriptor->descriptor.hid.bDescriptorType != USB_DT_HID) { - dbg_ep0 (3, "[%d] interface is not HID", - bNumInterface); - return -1; - } - /* copy descriptor for this class */ - copy_config (urb, class_descriptor, - class_descriptor->descriptor.hid.bLength, - max); -#endif - } - break; - case USB_DESCRIPTOR_TYPE_REPORT: - { - dbg_ep0(2, "USB_DESCRIPTOR_TYPE_REPORT - error not implemented\n"); - return -1; /* unsupported at this time */ -#if 0 - int bNumInterface = - le16_to_cpu (urb->device_request.wIndex); - int bAlternateSetting = 0; - int class = 0; - struct usb_class_report_descriptor *report_descriptor; - - if (!(report_descriptor = - usbd_device_class_report_descriptor_index - (device, port, 0, bNumInterface, - bAlternateSetting, class)) - || report_descriptor->bDescriptorType != - USB_DT_REPORT) { - dbg_ep0 (3, "[%d] descriptor is not REPORT", - bNumInterface); - return -1; - } - /* copy report descriptor for this class */ - /*copy_config(urb, &report_descriptor->bData[0], report_descriptor->wLength, max); */ - if (max - urb->actual_length > 0) { - int length = - min(report_descriptor->wLength, - max - urb->actual_length); - memcpy (urb->buffer + urb->actual_length, - &report_descriptor->bData[0], length); - urb->actual_length += length; - } -#endif - } - break; - case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: - return -1; - - default: - return -1; - } - - dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d tx_packetSize: %2d", - urb->buffer, urb->buffer_length, urb->actual_length, - device->bus->endpoint_array[0].tx_packetSize); -/* - if ((urb->actual_length < max) && !(urb->actual_length % device->bus->endpoint_array[0].tx_packetSize)) { - dbg_ep0(0, "adding null byte"); - urb->buffer[urb->actual_length++] = 0; - dbg_ep0(0, "urb: buffer_length: %2d actual_length: %2d packet size: %2d", - urb->buffer_length, urb->actual_length device->bus->endpoint_array[0].tx_packetSize); - } -*/ - return 0; - -} - -/** - * ep0_recv_setup - called to indicate URB has been received - * @urb: pointer to struct urb - * - * Check if this is a setup packet, process the device request, put results - * back into the urb and return zero or non-zero to indicate success (DATA) - * or failure (STALL). - * - */ -int ep0_recv_setup (struct urb *urb) -{ - /*struct usb_device_request *request = urb->buffer; */ - /*struct usb_device_instance *device = urb->device; */ - - struct usb_device_request *request; - struct usb_device_instance *device; - int address; - - dbg_ep0 (0, "entering ep0_recv_setup()"); - if (!urb || !urb->device) { - dbg_ep0 (3, "invalid URB %p", urb); - return -1; - } - - request = &urb->device_request; - device = urb->device; - - dbg_ep0 (3, "urb: %p device: %p", urb, urb->device); - - /*dbg_ep0(2, "- - - - - - - - - -"); */ - - dbg_ep0 (2, - "bmRequestType:%02x bRequest:%02x wValue:%04x wIndex:%04x wLength:%04x %s", - request->bmRequestType, request->bRequest, - le16_to_cpu (request->wValue), le16_to_cpu (request->wIndex), - le16_to_cpu (request->wLength), - USBD_DEVICE_REQUESTS (request->bRequest)); - - /* handle USB Standard Request (c.f. USB Spec table 9-2) */ - if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) { - if(device->device_state <= STATE_CONFIGURED){ - /* Attempt to handle a CDC specific request if we are - * in the configured state. - */ - return device->cdc_recv_setup(request,urb); - } - dbg_ep0 (1, "non standard request: %x", - request->bmRequestType & USB_REQ_TYPE_MASK); - return -1; /* Stall here */ - } - - switch (device->device_state) { - case STATE_CREATED: - case STATE_ATTACHED: - case STATE_POWERED: - /* It actually is important to allow requests in these states, - * Windows will request descriptors before assigning an - * address to the client. - */ - - /*dbg_ep0 (1, "request %s not allowed in this state: %s", */ - /* USBD_DEVICE_REQUESTS(request->bRequest), */ - /* usbd_device_states[device->device_state]); */ - /*return -1; */ - break; - - case STATE_INIT: - case STATE_DEFAULT: - switch (request->bRequest) { - case USB_REQ_GET_STATUS: - case USB_REQ_GET_INTERFACE: - case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - case USB_REQ_SET_DESCRIPTOR: - /* case USB_REQ_SET_CONFIGURATION: */ - case USB_REQ_SET_INTERFACE: - dbg_ep0 (1, - "request %s not allowed in DEFAULT state: %s", - USBD_DEVICE_REQUESTS (request->bRequest), - usbd_device_states[device->device_state]); - return -1; - - case USB_REQ_SET_CONFIGURATION: - case USB_REQ_SET_ADDRESS: - case USB_REQ_GET_DESCRIPTOR: - case USB_REQ_GET_CONFIGURATION: - break; - } - case STATE_ADDRESSED: - case STATE_CONFIGURED: - break; - case STATE_UNKNOWN: - dbg_ep0 (1, "request %s not allowed in UNKNOWN state: %s", - USBD_DEVICE_REQUESTS (request->bRequest), - usbd_device_states[device->device_state]); - return -1; - } - - /* handle all requests that return data (direction bit set on bm RequestType) */ - if ((request->bmRequestType & USB_REQ_DIRECTION_MASK)) { - - dbg_ep0 (3, "Device-to-Host"); - - switch (request->bRequest) { - - case USB_REQ_GET_STATUS: - return ep0_get_status (device, urb, request->wIndex, - request->bmRequestType & - USB_REQ_RECIPIENT_MASK); - - case USB_REQ_GET_DESCRIPTOR: - return ep0_get_descriptor (device, urb, - le16_to_cpu (request->wLength), - le16_to_cpu (request->wValue) >> 8, - le16_to_cpu (request->wValue) & 0xff); - - case USB_REQ_GET_CONFIGURATION: - dbg_ep0(2, "get config %d\n", device->configuration); - return ep0_get_one (device, urb, - device->configuration); - - case USB_REQ_GET_INTERFACE: - return ep0_get_one (device, urb, device->alternate); - - case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ - return -1; - - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - case USB_REQ_SET_ADDRESS: - case USB_REQ_SET_DESCRIPTOR: - case USB_REQ_SET_CONFIGURATION: - case USB_REQ_SET_INTERFACE: - return -1; - } - } - /* handle the requests that do not return data */ - else { - - /*dbg_ep0(3, "Host-to-Device"); */ - switch (request->bRequest) { - - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - dbg_ep0 (0, "Host-to-Device"); - switch (request-> - bmRequestType & USB_REQ_RECIPIENT_MASK) { - case USB_REQ_RECIPIENT_DEVICE: - /* XXX DEVICE_REMOTE_WAKEUP or TEST_MODE would be added here */ - /* XXX fall through for now as we do not support either */ - case USB_REQ_RECIPIENT_INTERFACE: - case USB_REQ_RECIPIENT_OTHER: - dbg_ep0 (0, "request %s not", - USBD_DEVICE_REQUESTS (request->bRequest)); - default: - return -1; - - case USB_REQ_RECIPIENT_ENDPOINT: - dbg_ep0 (0, "ENDPOINT: %x", le16_to_cpu (request->wValue)); - if (le16_to_cpu (request->wValue) == USB_ENDPOINT_HALT) { - /*return usbd_device_feature (device, le16_to_cpu (request->wIndex), */ - /* request->bRequest == USB_REQ_SET_FEATURE); */ - /* NEED TO IMPLEMENT THIS!!! */ - return -1; - } else { - dbg_ep0 (1, "request %s bad wValue: %04x", - USBD_DEVICE_REQUESTS - (request->bRequest), - le16_to_cpu (request->wValue)); - return -1; - } - } - - case USB_REQ_SET_ADDRESS: - /* check if this is a re-address, reset first if it is (this shouldn't be possible) */ - if (device->device_state != STATE_DEFAULT) { - dbg_ep0 (1, "set_address: %02x state: %s", - le16_to_cpu (request->wValue), - usbd_device_states[device->device_state]); - return -1; - } - address = le16_to_cpu (request->wValue); - if ((address & 0x7f) != address) { - dbg_ep0 (1, "invalid address %04x %04x", - address, address & 0x7f); - return -1; - } - device->address = address; - - /*dbg_ep0(2, "address: %d %d %d", */ - /* request->wValue, le16_to_cpu(request->wValue), device->address); */ - - return 0; - - case USB_REQ_SET_DESCRIPTOR: /* XXX should we support this? */ - dbg_ep0 (0, "set descriptor: NOT SUPPORTED"); - return -1; - - case USB_REQ_SET_CONFIGURATION: - /* c.f. 9.4.7 - the top half of wValue is reserved */ - device->configuration = le16_to_cpu(request->wValue) & 0xff; - - /* reset interface and alternate settings */ - device->interface = device->alternate = 0; - - /*dbg_ep0(2, "set configuration: %d", device->configuration); */ - /*dbg_ep0(2, "DEVICE_CONFIGURED.. event?\n"); */ - return 0; - - case USB_REQ_SET_INTERFACE: - device->interface = le16_to_cpu (request->wIndex); - device->alternate = le16_to_cpu (request->wValue); - /*dbg_ep0(2, "set interface: %d alternate: %d", device->interface, device->alternate); */ - dbg_ep0(2, "DEVICE_SET_INTERFACE.. event?\n"); - return 0; - - case USB_REQ_GET_STATUS: - case USB_REQ_GET_DESCRIPTOR: - case USB_REQ_GET_CONFIGURATION: - case USB_REQ_GET_INTERFACE: - case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ - return -1; - } - } - return -1; -} diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig index c52afd41a75..ad9072a5327 100644 --- a/drivers/usb/musb-new/Kconfig +++ b/drivers/usb/musb-new/Kconfig @@ -22,6 +22,13 @@ config USB_MUSB_GADGET Enables the MUSB USB dual-role controller in gadget mode. if USB_MUSB_HOST || USB_MUSB_GADGET +config USB_MUSB_SC5XX + bool "Analog Devices MUSB support" + depends on (SC57X || SC58X) + help + Say y here to enable support for the USB controller on + ADI SC57X/SC58X processors. + config USB_MUSB_DA8XX bool "Enable DA8xx MUSB Controller" depends on ARCH_DAVINCI diff --git a/drivers/usb/musb-new/Makefile b/drivers/usb/musb-new/Makefile index 396ff02654b..6638772daca 100644 --- a/drivers/usb/musb-new/Makefile +++ b/drivers/usb/musb-new/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_USB_MUSB_PIC32) += pic32.o obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o obj-$(CONFIG_USB_MUSB_TI) += ti-musb.o obj-$(CONFIG_USB_MUSB_UX500) += ux500.o +obj-$(CONFIG_USB_MUSB_SC5XX) += sc5xx.o ccflags-y := $(call cc-option,-Wno-unused-variable) \ $(call cc-option,-Wno-unused-but-set-variable) \ diff --git a/drivers/usb/musb-new/sc5xx.c b/drivers/usb/musb-new/sc5xx.c new file mode 100644 index 00000000000..16201480b43 --- /dev/null +++ b/drivers/usb/musb-new/sc5xx.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * ADI SC5XX MUSB "glue layer" + * + * Written and/or maintained by Timesys Corporation + * + * Loosely ported from Linux driver: + * Author: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * + */ + +#include <dm.h> +#include <dm/device_compat.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <linux/usb/musb.h> +#include "linux-compat.h" +#include "musb_core.h" +#include "musb_uboot.h" + +#define MUSB_SOFTRST 0x7f +#define MUSB_SOFTRST_NRST BIT(0) +#define MUSB_SOFTRST_NRSTX BIT(1) + +#define REG_USB_VBUS_CTL 0x380 +#define REG_USB_ID_CTL 0x382 +#define REG_USB_PHY_CTL 0x394 +#define REG_USB_PLL_OSC 0x398 +#define REG_USB_UTMI_CTL 0x39c + +/* controller data */ +struct sc5xx_musb_data { + struct musb_host_data mdata; + struct device dev; +}; + +#define to_sc5xx_musb_data(d) \ + container_of(d, struct sc5xx_musb_data, dev) + +static void sc5xx_musb_disable(struct musb *musb) +{ + /* no way to shut the controller */ +} + +static int sc5xx_musb_enable(struct musb *musb) +{ + /* soft reset by NRSTx */ + musb_writeb(musb->mregs, MUSB_SOFTRST, MUSB_SOFTRST_NRSTX); + /* set mode */ + musb_platform_set_mode(musb, musb->board_mode); + + return 0; +} + +static irqreturn_t sc5xx_interrupt(int irq, void *hci) +{ + struct musb *musb = hci; + irqreturn_t ret = IRQ_NONE; + u8 devctl; + + musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); + musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); + musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); + + if (musb->int_usb & MUSB_INTR_VBUSERROR) { + musb->int_usb &= ~MUSB_INTR_VBUSERROR; + devctl = musb_readw(musb->mregs, MUSB_DEVCTL); + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + } + if (musb->int_usb || musb->int_tx || musb->int_rx) { + musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); + musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); + musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); + ret = musb_interrupt(musb); + } + + if (musb->int_usb & MUSB_INTR_DISCONNECT && is_host_active(musb)) + musb_writeb(musb->mregs, REG_USB_VBUS_CTL, 0x0); + + return ret; +} + +static int sc5xx_musb_set_mode(struct musb *musb, u8 mode) +{ + struct device *dev = musb->controller; + struct sc5xx_musb_data *pdata = to_sc5xx_musb_data(dev); + + switch (mode) { + case MUSB_HOST: + musb_writeb(musb->mregs, REG_USB_ID_CTL, 0x1); + break; + case MUSB_PERIPHERAL: + musb_writeb(musb->mregs, REG_USB_ID_CTL, 0x3); + break; + case MUSB_OTG: + musb_writeb(musb->mregs, REG_USB_ID_CTL, 0x0); + break; + default: + dev_err(dev, "unsupported mode %d\n", mode); + return -EINVAL; + } + + return 0; +} + +static int sc5xx_musb_init(struct musb *musb) +{ + struct sc5xx_musb_data *pdata = to_sc5xx_musb_data(musb->controller); + + musb->isr = sc5xx_interrupt; + + musb_writel(musb->mregs, REG_USB_PLL_OSC, 20 << 1); + musb_writeb(musb->mregs, REG_USB_VBUS_CTL, 0x0); + musb_writeb(musb->mregs, REG_USB_PHY_CTL, 0x80); + musb_writel(musb->mregs, REG_USB_UTMI_CTL, + 0x40 | musb_readl(musb->mregs, REG_USB_UTMI_CTL)); + + return 0; +} + +const struct musb_platform_ops sc5xx_musb_ops = { + .init = sc5xx_musb_init, + .set_mode = sc5xx_musb_set_mode, + .disable = sc5xx_musb_disable, + .enable = sc5xx_musb_enable, +}; + +static struct musb_hdrc_config sc5xx_musb_config = { + .multipoint = 1, + .dyn_fifo = 1, + .num_eps = 16, + .ram_bits = 12, +}; + +/* has one MUSB controller which can be host or gadget */ +static struct musb_hdrc_platform_data sc5xx_musb_plat = { + .mode = MUSB_HOST, + .config = &sc5xx_musb_config, + .power = 100, + .platform_ops = &sc5xx_musb_ops, +}; + +static int musb_usb_probe(struct udevice *dev) +{ + struct usb_bus_priv *priv = dev_get_uclass_priv(dev); + struct sc5xx_musb_data *pdata = dev_get_priv(dev); + struct musb_host_data *mdata = &pdata->mdata; + void __iomem *mregs; + int ret; + + priv->desc_before_addr = true; + + mregs = dev_remap_addr(dev); + if (!mregs) + return -EINVAL; + + /* init controller */ + if (IS_ENABLED(CONFIG_USB_MUSB_HOST)) { + mdata->host = musb_init_controller(&sc5xx_musb_plat, + &pdata->dev, mregs); + if (!mdata->host) + return -EIO; + + ret = musb_lowlevel_init(mdata); + } else { + sc5xx_musb_plat.mode = MUSB_PERIPHERAL; + mdata->host = musb_register(&sc5xx_musb_plat, &pdata->dev, mregs); + if (!mdata->host) + return -EIO; + } + return ret; +} + +static int musb_usb_remove(struct udevice *dev) +{ + struct sc5xx_musb_data *pdata = dev_get_priv(dev); + + musb_stop(pdata->mdata.host); + + return 0; +} + +static const struct udevice_id sc5xx_musb_ids[] = { + { .compatible = "adi,sc5xx-musb" }, + { } +}; + +U_BOOT_DRIVER(usb_musb) = { + .name = "sc5xx-musb", + .id = UCLASS_USB, + .of_match = sc5xx_musb_ids, + .probe = musb_usb_probe, + .remove = musb_usb_remove, +#ifdef CONFIG_USB_MUSB_HOST + .ops = &musb_usb_ops, +#endif + .plat_auto = sizeof(struct usb_plat), + .priv_auto = sizeof(struct sc5xx_musb_data), +}; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3c3cebaacd0..b1ef73f3e5c 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -599,6 +599,15 @@ config VIDEO_LCD_SAMSUNG_LTL106HL02 LCD module found in Microsoft Surface 2. The panel has a FullHD resolution (1920x1080). +config VIDEO_LCD_SHARP_LQ079L1SX01 + tristate "Sharp LQ079L1SX01 1536x2048 DSI video mode panel" + depends on PANEL && BACKLIGHT + select VIDEO_MIPI_DSI + help + Say Y here if you want to enable support for Sharp LQ079L1SX01 + LCD module found in Xiaomi Mi Pad tablet. The panel has a QXGA + resolution (1536x2048). + config VIDEO_LCD_SHARP_LQ101R1SX01 tristate "Sharp LQ101R1SX01 2560x1600 DSI video mode panel" depends on PANEL && BACKLIGHT @@ -743,6 +752,16 @@ config BACKLIGHT_LM3533 LM3533 Lighting Power chip. Only Bank A is supported as for now. Supported backlight level range is from 2 to 255 with step of 1. +config BACKLIGHT_LP855x + bool "Backlight Driver for LP855x" + depends on BACKLIGHT + select DM_I2C + help + Say Y to enable the backlight driver for National Semiconductor / TI + LP8550/1/2/3/5/6/7 LED Backlight Driver. Only register driven mode is + supported for now, PWM mode can be added if there will be any need in + it. Supported backlight level range is from 0 to 255 with step of 1. + source "drivers/video/ti/Kconfig" source "drivers/video/exynos/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 5a00438ce06..6073bc5234a 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_$(PHASE_)BMP) += bmp.o endif obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_backlight.o +obj-$(CONFIG_BACKLIGHT_LP855x) += lp855x_backlight.o obj-${CONFIG_EXYNOS_FB} += exynos/ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ obj-${CONFIG_VIDEO_STM32} += stm32/ @@ -64,6 +65,7 @@ obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R69328) += renesas-r69328.o obj-$(CONFIG_VIDEO_LCD_SAMSUNG_LTL106HL02) += samsung-ltl106hl02.o +obj-$(CONFIG_VIDEO_LCD_SHARP_LQ079L1SX01) += sharp-lq079l1sx01.o obj-$(CONFIG_VIDEO_LCD_SHARP_LQ101R1SX01) += sharp-lq101r1sx01.o obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index ab917273720..21c5a043e02 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -59,3 +59,10 @@ config VIDEO_BRIDGE_TOSHIBA_TC358768 help Toshiba TC358768AXBG/TC358778XBG DSI bridge chip driver. Found in Asus Transformer Infinity TF700T. + +config VIDEO_BRIDGE_LVDS_CODEC + bool "Transparent LVDS encoders and decoders support" + depends on VIDEO_BRIDGE && PANEL && DM_GPIO + help + Support for transparent LVDS encoders and decoders that don't + require any configuration. diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile index 58697e3cbe9..63dc6e62c49 100644 --- a/drivers/video/bridge/Makefile +++ b/drivers/video/bridge/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o obj-$(CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825) += ssd2825.o obj-$(CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768) += tc358768.o +obj-$(CONFIG_VIDEO_BRIDGE_LVDS_CODEC) += lvds-codec.o diff --git a/drivers/video/bridge/lvds-codec.c b/drivers/video/bridge/lvds-codec.c new file mode 100644 index 00000000000..6cd8368a39e --- /dev/null +++ b/drivers/video/bridge/lvds-codec.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com> + * Loosely based on Linux lvds-codec.c driver + */ + +#include <dm.h> +#include <dm/ofnode_graph.h> +#include <log.h> +#include <panel.h> +#include <video_bridge.h> +#include <asm/gpio.h> +#include <power/regulator.h> + +struct lvds_codec_priv { + struct udevice *panel; + struct display_timing timing; + + struct gpio_desc powerdown_gpio; + struct udevice *power; +}; + +static int lvds_codec_attach(struct udevice *dev) +{ + struct lvds_codec_priv *priv = dev_get_priv(dev); + + regulator_set_enable_if_allowed(priv->power, 1); + dm_gpio_set_value(&priv->powerdown_gpio, 0); + + return panel_enable_backlight(priv->panel); +} + +static int lvds_codec_set_panel(struct udevice *dev, int percent) +{ + struct lvds_codec_priv *priv = dev_get_priv(dev); + + return panel_set_backlight(priv->panel, percent); +} + +static int lvds_codec_panel_timings(struct udevice *dev, + struct display_timing *timing) +{ + struct lvds_codec_priv *priv = dev_get_priv(dev); + + memcpy(timing, &priv->timing, sizeof(*timing)); + + return 0; +} + +/* Function is purely for sandbox testing */ +static int lvds_codec_read_edid(struct udevice *dev, u8 *buf, int buf_size) +{ + return 0; +} + +static int lvds_codec_get_panel(struct udevice *dev) +{ + struct lvds_codec_priv *priv = dev_get_priv(dev); + int i, ret; + + u32 num = ofnode_graph_get_port_count(dev_ofnode(dev)); + + for (i = 0; i < num; i++) { + ofnode remote = ofnode_graph_get_remote_node(dev_ofnode(dev), i, -1); + + ret = uclass_get_device_by_of_offset(UCLASS_PANEL, + ofnode_to_offset(remote), + &priv->panel); + if (!ret) + return 0; + } + + /* If this point is reached, no panels were found */ + return -ENODEV; +} + +static int lvds_codec_probe(struct udevice *dev) +{ + struct lvds_codec_priv *priv = dev_get_priv(dev); + int ret; + + ret = lvds_codec_get_panel(dev); + if (ret) { + log_debug("%s: cannot get panel: ret=%d\n", __func__, ret); + return log_ret(ret); + } + + panel_get_display_timing(priv->panel, &priv->timing); + + ret = gpio_request_by_name(dev, "powerdown-gpios", 0, + &priv->powerdown_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: could not get powerdown-gpios (%d)\n", __func__, ret); + if (ret != -ENOENT) + return log_ret(ret); + } + + ret = device_get_supply_regulator(dev, "power-supply", &priv->power); + if (ret) { + log_debug("%s: power regulator error: %d\n", __func__, ret); + if (ret != -ENOENT) + return log_ret(ret); + } + + return 0; +} + +static const struct video_bridge_ops lvds_codec_ops = { + .attach = lvds_codec_attach, + .set_backlight = lvds_codec_set_panel, + .get_display_timing = lvds_codec_panel_timings, + .read_edid = lvds_codec_read_edid, +}; + +static const struct udevice_id lvds_codec_ids[] = { + { .compatible = "lvds-decoder" }, + { .compatible = "lvds-encoder" }, + { } +}; + +U_BOOT_DRIVER(lvds_codec) = { + .name = "lvds_codec", + .id = UCLASS_VIDEO_BRIDGE, + .of_match = lvds_codec_ids, + .ops = &lvds_codec_ops, + .probe = lvds_codec_probe, + .priv_auto = sizeof(struct lvds_codec_priv), +}; diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c index 2084a2e03ee..1b8aa12b9e8 100644 --- a/drivers/video/bridge/video-bridge-uclass.c +++ b/drivers/video/bridge/video-bridge-uclass.c @@ -33,6 +33,17 @@ int video_bridge_attach(struct udevice *dev) return ops->attach(dev); } +int video_bridge_get_display_timing(struct udevice *dev, + struct display_timing *timings) +{ + struct video_bridge_ops *ops = video_bridge_get_ops(dev); + + if (!ops->get_display_timing) + return -ENOSYS; + + return ops->get_display_timing(dev, timings); +} + int video_bridge_check_attached(struct udevice *dev) { struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); diff --git a/drivers/video/lp855x_backlight.c b/drivers/video/lp855x_backlight.c new file mode 100644 index 00000000000..5debc0aa453 --- /dev/null +++ b/drivers/video/lp855x_backlight.c @@ -0,0 +1,302 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 Texas Instruments + * Copyright (c) 2024 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT + +#include <malloc.h> +#include <backlight.h> +#include <dm.h> +#include <dm/devres.h> +#include <i2c.h> +#include <log.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <asm/gpio.h> +#include <power/regulator.h> + +#define LP855x_MIN_BRIGHTNESS 0x00 +#define LP855x_MAX_BRIGHTNESS 0xff + +/* LP8550/1/2/3/6 Registers */ +#define LP855X_BRIGHTNESS_CTRL 0x00 +#define LP855X_DEVICE_CTRL 0x01 +#define LP855X_EEPROM_START 0xa0 +#define LP855X_EEPROM_END 0xa7 +#define LP8556_EPROM_START 0x98 +#define LP8556_EPROM_END 0xaf + +/* LP8555/7 Registers */ +#define LP8557_BL_CMD 0x00 +#define LP8557_BL_MASK 0x01 +#define LP8557_BL_ON 0x01 +#define LP8557_BL_OFF 0x00 +#define LP8557_BRIGHTNESS_CTRL 0x04 +#define LP8557_CONFIG 0x10 +#define LP8555_EPROM_START 0x10 +#define LP8555_EPROM_END 0x7a +#define LP8557_EPROM_START 0x10 +#define LP8557_EPROM_END 0x1e + +struct lp855x_rom_data { + u8 addr; + u8 val; +}; + +struct lp855x_backlight_priv; + +/* + * struct lp855x_device_config + * @pre_init_device: init device function call before updating the brightness + * @reg_brightness: register address for brigthenss control + * @reg_devicectrl: register address for device control + * @post_init_device: late init device function call + */ +struct lp855x_device_config { + int (*pre_init_device)(struct udevice *dev); + u8 reg_brightness; + u8 reg_devicectrl; + u8 reg_eepromstart; + u8 reg_eepromend; + int (*post_init_device)(struct udevice *dev); +}; + +struct lp855x_backlight_priv { + struct udevice *supply; /* regulator for VDD input */ + struct udevice *enable; /* regulator for EN/VDDIO input */ + + u8 device_control; + u8 initial_brightness; + + int size_program; + struct lp855x_rom_data *rom_data; + struct lp855x_device_config *cfg; +}; + +static int lp855x_backlight_enable(struct udevice *dev) +{ + struct lp855x_backlight_priv *priv = dev_get_priv(dev); + int ret; + + ret = regulator_set_enable_if_allowed(priv->supply, 1); + if (ret) { + log_debug("%s: enabling power-supply failed (%d)\n", + __func__, ret); + return ret; + } + + ret = regulator_set_enable_if_allowed(priv->enable, 1); + if (ret) { + log_debug("%s: enabling enable-supply failed (%d)\n", + __func__, ret); + return ret; + } + mdelay(2); + + if (priv->cfg->pre_init_device) { + ret = priv->cfg->pre_init_device(dev); + if (ret) { + log_debug("%s: pre init device err: %d\n", + __func__, ret); + return ret; + } + } + + ret = dm_i2c_reg_write(dev, priv->cfg->reg_brightness, + priv->initial_brightness); + if (ret) + return ret; + + ret = dm_i2c_reg_write(dev, priv->cfg->reg_devicectrl, + priv->device_control); + if (ret) + return ret; + + if (priv->size_program > 0) { + int i; + u8 val, addr; + + for (i = 0; i < priv->size_program; i++) { + addr = priv->rom_data[i].addr; + val = priv->rom_data[i].val; + + if (addr < priv->cfg->reg_eepromstart && + addr > priv->cfg->reg_eepromend) + continue; + + ret = dm_i2c_reg_write(dev, addr, val); + if (ret) + return ret; + } + } + + if (priv->cfg->post_init_device) { + ret = priv->cfg->post_init_device(dev); + if (ret) { + log_debug("%s: post init device err: %d\n", + __func__, ret); + return ret; + } + } + + return 0; +} + +static int lp855x_backlight_set_brightness(struct udevice *dev, int percent) +{ + struct lp855x_backlight_priv *priv = dev_get_priv(dev); + + if (percent == BACKLIGHT_DEFAULT) + percent = priv->initial_brightness; + + if (percent < LP855x_MIN_BRIGHTNESS) + percent = LP855x_MIN_BRIGHTNESS; + + if (percent > LP855x_MAX_BRIGHTNESS) + percent = LP855x_MAX_BRIGHTNESS; + + /* Set brightness level */ + return dm_i2c_reg_write(dev, priv->cfg->reg_brightness, + percent); +} + +static int lp855x_backlight_probe(struct udevice *dev) +{ + struct lp855x_backlight_priv *priv = dev_get_priv(dev); + int rom_length, ret; + + if (device_get_uclass_id(dev->parent) != UCLASS_I2C) + return -EPROTONOSUPPORT; + + priv->cfg = (struct lp855x_device_config *)dev_get_driver_data(dev); + + dev_read_u8(dev, "dev-ctrl", &priv->device_control); + dev_read_u8(dev, "init-brt", &priv->initial_brightness); + + /* Fill ROM platform data if defined */ + rom_length = dev_get_child_count(dev); + if (rom_length > 0) { + struct lp855x_rom_data *rom; + ofnode child; + int i = 0; + + rom = devm_kcalloc(dev, rom_length, sizeof(*rom), GFP_KERNEL); + if (!rom) + return -ENOMEM; + + dev_for_each_subnode(child, dev) { + ofnode_read_u8(child, "rom-addr", &rom[i].addr); + ofnode_read_u8(child, "rom-val", &rom[i].val); + i++; + } + + priv->size_program = rom_length; + priv->rom_data = &rom[0]; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "power-supply", &priv->supply); + if (ret) { + log_err("%s: cannot get power-supply: ret = %d\n", __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "enable-supply", &priv->enable); + if (ret) { + log_err("%s: cannot get enable-supply: ret = %d\n", __func__, ret); + return ret; + } + + return 0; +} + +static const struct backlight_ops lp855x_backlight_ops = { + .enable = lp855x_backlight_enable, + .set_brightness = lp855x_backlight_set_brightness, +}; + +static int lp8556_bl_rst(struct udevice *dev) +{ + int ret; + + /* Reset backlight after updating EPROM settings */ + ret = dm_i2c_reg_clrset(dev, LP855X_DEVICE_CTRL, LP8557_BL_MASK, + LP8557_BL_OFF); + if (ret) + return ret; + + mdelay(10); + + return dm_i2c_reg_clrset(dev, LP855X_DEVICE_CTRL, LP8557_BL_MASK, + LP8557_BL_ON); +} + +static int lp8557_bl_off(struct udevice *dev) +{ + /* BL_ON = 0 before updating EPROM settings */ + return dm_i2c_reg_clrset(dev, LP8557_BL_CMD, LP8557_BL_MASK, + LP8557_BL_OFF); +} + +static int lp8557_bl_on(struct udevice *dev) +{ + /* BL_ON = 1 after updating EPROM settings */ + return dm_i2c_reg_clrset(dev, LP8557_BL_CMD, LP8557_BL_MASK, + LP8557_BL_ON); +} + +static struct lp855x_device_config lp855x_dev_cfg = { + .reg_brightness = LP855X_BRIGHTNESS_CTRL, + .reg_devicectrl = LP855X_DEVICE_CTRL, + .reg_eepromstart = LP855X_EEPROM_START, + .reg_eepromend = LP855X_EEPROM_END, +}; + +static struct lp855x_device_config lp8555_dev_cfg = { + .reg_brightness = LP8557_BRIGHTNESS_CTRL, + .reg_devicectrl = LP8557_CONFIG, + .reg_eepromstart = LP8555_EPROM_START, + .reg_eepromend = LP8555_EPROM_END, + .pre_init_device = lp8557_bl_off, + .post_init_device = lp8557_bl_on, +}; + +static struct lp855x_device_config lp8556_dev_cfg = { + .reg_brightness = LP855X_BRIGHTNESS_CTRL, + .reg_devicectrl = LP855X_DEVICE_CTRL, + .reg_eepromstart = LP8556_EPROM_START, + .reg_eepromend = LP8556_EPROM_END, + .post_init_device = lp8556_bl_rst, +}; + +static struct lp855x_device_config lp8557_dev_cfg = { + .reg_brightness = LP8557_BRIGHTNESS_CTRL, + .reg_devicectrl = LP8557_CONFIG, + .reg_eepromstart = LP8557_EPROM_START, + .reg_eepromend = LP8557_EPROM_END, + .pre_init_device = lp8557_bl_off, + .post_init_device = lp8557_bl_on, +}; + +static const struct udevice_id lp855x_backlight_ids[] = { + { .compatible = "ti,lp8550", .data = (ulong)&lp855x_dev_cfg }, + { .compatible = "ti,lp8551", .data = (ulong)&lp855x_dev_cfg }, + { .compatible = "ti,lp8552", .data = (ulong)&lp855x_dev_cfg }, + { .compatible = "ti,lp8553", .data = (ulong)&lp855x_dev_cfg }, + { .compatible = "ti,lp8555", .data = (ulong)&lp8555_dev_cfg }, + { .compatible = "ti,lp8556", .data = (ulong)&lp8556_dev_cfg }, + { .compatible = "ti,lp8557", .data = (ulong)&lp8557_dev_cfg }, + { } +}; + +U_BOOT_DRIVER(lp855x_backlight) = { + .name = "lp855x_backlight", + .id = UCLASS_PANEL_BACKLIGHT, + .of_match = lp855x_backlight_ids, + .probe = lp855x_backlight_probe, + .ops = &lp855x_backlight_ops, + .priv_auto = sizeof(struct lp855x_backlight_priv), +}; diff --git a/drivers/video/sharp-lq079l1sx01.c b/drivers/video/sharp-lq079l1sx01.c new file mode 100644 index 00000000000..a8197f40fc7 --- /dev/null +++ b/drivers/video/sharp-lq079l1sx01.c @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Sharp LQ079L1SX01 DSI panel driver + * + * Copyright (c) 2024 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <backlight.h> +#include <dm.h> +#include <panel.h> +#include <log.h> +#include <mipi_dsi.h> +#include <linux/delay.h> +#include <asm/gpio.h> +#include <power/regulator.h> + +struct sharp_lq079l1sx01_priv { + struct udevice *backlight; + struct udevice *panel_sec; + + struct udevice *avdd; + struct udevice *vddio; + struct udevice *vsp; + struct udevice *vsn; + + struct gpio_desc reset_gpio; +}; + +static struct display_timing default_timing = { + .pixelclock.typ = 215000000, + .hactive.typ = 1536, + .hfront_porch.typ = 136, + .hback_porch.typ = 28, + .hsync_len.typ = 28, + .vactive.typ = 2048, + .vfront_porch.typ = 14, + .vback_porch.typ = 8, + .vsync_len.typ = 2, +}; + +static int dcs_write_one(struct mipi_dsi_device *dsi, u8 cmd, u8 data) +{ + return mipi_dsi_dcs_write(dsi, cmd, &data, 1); +} + +static int sharp_lq079l1sx01_configure_link(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + struct mipi_dsi_device *dsi = plat->device; + int ret; + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) { + log_debug("%s: failed to exit sleep mode %s: %d\n", + __func__, dev->parent->name, ret); + } + mdelay(120); + + ret = dcs_write_one(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 0xff); + if (ret < 0) { + log_debug("%s: failed to SET_DISPLAY_BRIGHTNESS %s: %d\n", + __func__, dev->parent->name, ret); + } + ret = dcs_write_one(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x01); + if (ret < 0) { + log_debug("%s: failed to WRITE_POWER_SAVE %s: %d\n", + __func__, dev->parent->name, ret); + } + ret = dcs_write_one(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c); + if (ret < 0) { + log_debug("%s: failed to WRITE_CONTROL_DISPLAY %s: %d\n", + __func__, dev->parent->name, ret); + } + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret < 0) { + log_debug("%s: failed to set panel on %s: %d\n", + __func__, dev->parent->name, ret); + } + + return 0; +} + +static int sharp_lq079l1sx01_enable_backlight(struct udevice *dev) +{ + struct sharp_lq079l1sx01_priv *priv = dev_get_priv(dev); + + if (!priv->panel_sec) + return 0; + + sharp_lq079l1sx01_configure_link(dev); + sharp_lq079l1sx01_configure_link(priv->panel_sec); + + return 0; +} + +static int sharp_lq079l1sx01_set_backlight(struct udevice *dev, int percent) +{ + struct sharp_lq079l1sx01_priv *priv = dev_get_priv(dev); + int ret; + + if (!priv->panel_sec) + return 0; + + ret = backlight_enable(priv->backlight); + if (ret) + return ret; + + return backlight_set_brightness(priv->backlight, percent); +} + +static int sharp_lq079l1sx01_timings(struct udevice *dev, + struct display_timing *timing) +{ + memcpy(timing, &default_timing, sizeof(*timing)); + return 0; +} + +static int sharp_lq079l1sx01_of_to_plat(struct udevice *dev) +{ + struct sharp_lq079l1sx01_priv *priv = dev_get_priv(dev); + int ret; + + /* If node has no link2 it is secondary panel */ + if (!dev_read_bool(dev, "link2")) + return 0; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, + "link2", &priv->panel_sec); + if (ret) { + log_debug("%s: cannot get secondary panel: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", &priv->backlight); + if (ret) { + log_debug("%s: cannot get backlight: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "avdd-supply", &priv->avdd); + if (ret) { + log_debug("%s: cannot get avdd-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vddio-supply", &priv->vddio); + if (ret) { + log_debug("%s: cannot get vddio-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vsp-supply", &priv->vsp); + if (ret) { + log_debug("%s: cannot get vsp-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vsn-supply", &priv->vsn); + if (ret) { + log_debug("%s: cannot get vsn-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = gpio_request_by_name(dev, "reset-gpios", 0, + &priv->reset_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: cannot get reser-gpios (%d)\n", + __func__, ret); + return ret; + } + + return 0; +} + +static int sharp_lq079l1sx01_hw_init(struct udevice *dev) +{ + struct sharp_lq079l1sx01_priv *priv = dev_get_priv(dev); + int ret; + + if (!priv->panel_sec) + return 0; + + ret = regulator_set_enable_if_allowed(priv->vddio, 1); + if (ret) { + log_debug("%s: enabling vddio-supply failed (%d)\n", + __func__, ret); + return ret; + } + + ret = regulator_set_enable_if_allowed(priv->avdd, 1); + if (ret) { + log_debug("%s: enabling avdd-supply failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(12); + + ret = regulator_set_enable_if_allowed(priv->vsp, 1); + if (ret) { + log_debug("%s: enabling vsp-supply failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(12); + + ret = regulator_set_enable_if_allowed(priv->vsn, 1); + if (ret) { + log_debug("%s: enabling vsn-supply failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(24); + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: error disabling reset-gpios (%d)\n", + __func__, ret); + return ret; + } + udelay(3); + + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + log_debug("%s: error enabling reset-gpios (%d)\n", + __func__, ret); + return ret; + } + udelay(3); + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: error disabling reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(32); + + return 0; +} + +static int sharp_lq079l1sx01_probe(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + + /* fill characteristics of DSI data link */ + plat->lanes = 4; + plat->format = MIPI_DSI_FMT_RGB888; + plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM; + + return sharp_lq079l1sx01_hw_init(dev); +} + +static const struct panel_ops sharp_lq079l1sx01_ops = { + .enable_backlight = sharp_lq079l1sx01_enable_backlight, + .set_backlight = sharp_lq079l1sx01_set_backlight, + .get_display_timing = sharp_lq079l1sx01_timings, +}; + +static const struct udevice_id sharp_lq079l1sx01_ids[] = { + { .compatible = "sharp,lq079l1sx01" }, + { } +}; + +U_BOOT_DRIVER(sharp_lq079l1sx01) = { + .name = "sharp_lq079l1sx01", + .id = UCLASS_PANEL, + .of_match = sharp_lq079l1sx01_ids, + .ops = &sharp_lq079l1sx01_ops, + .of_to_plat = sharp_lq079l1sx01_of_to_plat, + .probe = sharp_lq079l1sx01_probe, + .plat_auto = sizeof(struct mipi_dsi_panel_plat), + .priv_auto = sizeof(struct sharp_lq079l1sx01_priv), +}; diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index d24aa375b39..16a2b5281bf 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -5,24 +5,16 @@ #include <backlight.h> #include <cpu_func.h> +#include <clk.h> #include <dm.h> #include <fdtdec.h> #include <log.h> #include <panel.h> -#include <part.h> -#include <pwm.h> #include <video.h> -#include <asm/cache.h> -#include <asm/global_data.h> #include <asm/system.h> -#include <asm/gpio.h> #include <asm/io.h> - #include <asm/arch/clock.h> -#include <asm/arch/funcmux.h> -#include <asm/arch/pinmux.h> #include <asm/arch/powergate.h> -#include <asm/arch/pwm.h> #include "tegra-dc.h" @@ -44,7 +36,8 @@ struct tegra_lcd_priv { const struct tegra_dc_soc_info *soc; fdt_addr_t frame_buffer; /* Address of frame buffer */ unsigned pixel_clock; /* Pixel clock in Hz */ - int dc_clk[2]; /* Contains clk and its parent */ + struct clk *clk; + struct clk *clk_parent; ulong scdiv; /* Clock divider used by disp_clk_ctrl */ bool rotation; /* 180 degree panel turn */ int pipe; /* DC controller: 0 for A, 1 for B */ @@ -144,10 +137,9 @@ static int update_display_mode(struct tegra_lcd_priv *priv) val |= DATA_ALIGNMENT_MSB << DATA_ALIGNMENT_SHIFT; val |= DATA_ORDER_RED_BLUE << DATA_ORDER_SHIFT; writel(val, &disp->disp_interface_ctrl); - } - if (priv->soc->has_rgb) writel(0x00010001, &disp->shift_clk_opt); + } val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT; val |= priv->scdiv << SHIFT_CLK_DIVIDER_SHIFT; @@ -267,7 +259,9 @@ static int setup_window(struct tegra_lcd_priv *priv, win->out_h = priv->height; win->phys_addr = priv->frame_buffer; win->stride = priv->width * (1 << priv->log2_bpp) / 8; - debug("%s: depth = %d\n", __func__, priv->log2_bpp); + + log_debug("%s: depth = %d\n", __func__, priv->log2_bpp); + switch (priv->log2_bpp) { case VIDEO_BPP32: win->fmt = COLOR_DEPTH_R8G8B8A8; @@ -279,7 +273,7 @@ static int setup_window(struct tegra_lcd_priv *priv, break; default: - debug("Unsupported LCD bit depth"); + log_debug("Unsupported LCD bit depth\n"); return -1; } @@ -301,7 +295,8 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, void *default_lcd_base) { struct disp_ctl_win window; - unsigned long rate = clock_get_rate(priv->dc_clk[1]); + unsigned long rate = clk_get_rate(priv->clk_parent); + int ret; priv->frame_buffer = (u32)default_lcd_base; @@ -309,14 +304,9 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, * We halve the rate if DISP1 parent is PLLD, since actual parent * is plld_out0 which is PLLD divided by 2. */ - if (priv->dc_clk[1] == CLOCK_ID_DISPLAY) - rate /= 2; - -#ifndef CONFIG_TEGRA20 - /* PLLD2 obeys same rules as PLLD but it is present only on T30+ */ - if (priv->dc_clk[1] == CLOCK_ID_DISPLAY2) + if (priv->clk_parent->id == CLOCK_ID_DISPLAY || + priv->clk_parent->id == CLOCK_ID_DISPLAY2) rate /= 2; -#endif /* * The pixel clock divider is in 7.1 format (where the bottom bit @@ -327,14 +317,14 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, if (!priv->scdiv) priv->scdiv = ((rate * 2 + priv->pixel_clock / 2) / priv->pixel_clock) - 2; - debug("Display clock %lu, divider %lu\n", rate, priv->scdiv); + log_debug("Display clock %lu, divider %lu\n", rate, priv->scdiv); /* * HOST1X is init by default at 150MHz with PLLC as parent */ clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_CGENERAL, 150 * 1000000); - clock_start_periph_pll(priv->dc_clk[0], priv->dc_clk[1], + clock_start_periph_pll(priv->clk->id, priv->clk_parent->id, rate); basic_init(&priv->dc->cmd); @@ -348,8 +338,9 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, if (priv->pixel_clock) update_display_mode(priv); - if (setup_window(priv, &window)) - return -1; + ret = setup_window(priv, &window); + if (ret) + return ret; update_window(priv, &window); @@ -364,10 +355,6 @@ static int tegra_lcd_probe(struct udevice *dev) int ret; /* Initialize the Tegra display controller */ -#ifdef CONFIG_TEGRA20 - funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); -#endif - if (priv->soc->has_pgate) { uint powergate; @@ -378,14 +365,14 @@ static int tegra_lcd_probe(struct udevice *dev) ret = tegra_powergate_power_off(powergate); if (ret < 0) { - log_err("failed to power off DISP gate: %d", ret); + log_debug("failed to power off DISP gate: %d", ret); return ret; } ret = tegra_powergate_sequence_power_up(powergate, - priv->dc_clk[0]); + priv->clk->id); if (ret < 0) { - log_err("failed to power up DISP gate: %d", ret); + log_debug("failed to power up DISP gate: %d", ret); return ret; } } @@ -402,19 +389,15 @@ static int tegra_lcd_probe(struct udevice *dev) memset((u8 *)plat->base, 0, plat->size); flush_dcache_all(); - if (tegra_display_probe(priv, (void *)plat->base)) { - debug("%s: Failed to probe display driver\n", __func__); - return -1; + ret = tegra_display_probe(priv, (void *)plat->base); + if (ret) { + log_debug("%s: Failed to probe display driver\n", __func__); + return ret; } -#ifdef CONFIG_TEGRA20 - pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM); - pinmux_tristate_disable(PMUX_PINGRP_GPU); -#endif - ret = panel_enable_backlight(priv->panel); if (ret) { - debug("%s: Cannot enable backlight, ret=%d\n", __func__, ret); + log_debug("%s: Cannot enable backlight, ret=%d\n", __func__, ret); return ret; } @@ -427,8 +410,8 @@ static int tegra_lcd_probe(struct udevice *dev) uc_priv->xsize = priv->width; uc_priv->ysize = priv->height; uc_priv->bpix = priv->log2_bpp; - debug("LCD frame buffer at %08x, size %x\n", priv->frame_buffer, - plat->size); + log_debug("LCD frame buffer at %08x, size %x\n", priv->frame_buffer, + plat->size); return panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); } @@ -445,17 +428,24 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) priv->dc = (struct dc_ctlr *)dev_read_addr_ptr(dev); if (!priv->dc) { - debug("%s: No display controller address\n", __func__); + log_debug("%s: No display controller address\n", __func__); return -EINVAL; } priv->soc = (struct tegra_dc_soc_info *)dev_get_driver_data(dev); - ret = clock_decode_pair(dev, priv->dc_clk); - if (ret < 0) { - debug("%s: Cannot decode clocks for '%s' (ret = %d)\n", - __func__, dev->name, ret); - return -EINVAL; + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + log_debug("%s: Could not get DC clock: %ld\n", + __func__, PTR_ERR(priv->clk)); + return PTR_ERR(priv->clk); + } + + priv->clk_parent = devm_clk_get(dev, "parent"); + if (IS_ERR(priv->clk_parent)) { + log_debug("%s: Could not get DC clock parent: %ld\n", + __func__, PTR_ERR(priv->clk_parent)); + return PTR_ERR(priv->clk_parent); } priv->rotation = dev_read_bool(dev, "nvidia,180-rotation"); @@ -463,8 +453,8 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) rgb = fdt_subnode_offset(blob, node, "rgb"); if (rgb < 0) { - debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", - __func__, dev->name, rgb); + log_debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", + __func__, dev->name, rgb); return -EINVAL; } @@ -474,15 +464,15 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) */ panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); if (panel_node < 0) { - debug("%s: Cannot find panel information\n", __func__); + log_debug("%s: Cannot find panel information\n", __func__); return -EINVAL; } ret = uclass_get_device_by_of_offset(UCLASS_PANEL, panel_node, &priv->panel); if (ret) { - debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__, - dev->name, ret); + log_debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__, + dev->name, ret); return ret; } @@ -500,8 +490,8 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) if (ret) { ret = fdtdec_decode_display_timing(blob, rgb, 0, &priv->timing); if (ret) { - debug("%s: Cannot read display timing for '%s' (ret=%d)\n", - __func__, dev->name, ret); + log_debug("%s: Cannot read display timing for '%s' (ret=%d)\n", + __func__, dev->name, ret); return -EINVAL; } } @@ -564,6 +554,9 @@ static const struct udevice_id tegra_lcd_ids[] = { .compatible = "nvidia,tegra114-dc", .data = (ulong)&tegra114_dc_soc_info }, { + .compatible = "nvidia,tegra124-dc", + .data = (ulong)&tegra114_dc_soc_info + }, { /* sentinel */ } }; diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 6327266dd22..9f39ac7589b 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -5,6 +5,7 @@ */ #include <dm.h> +#include <clk.h> #include <log.h> #include <misc.h> #include <mipi_display.h> @@ -46,10 +47,13 @@ struct tegra_dsi_priv { enum tegra_dsi_format format; - int dsi_clk; + struct clk *clk; + struct clk *clk_parent; + int video_fifo_depth; int host_fifo_depth; + u32 calibration_pads; u32 version; /* for ganged-mode support */ @@ -515,8 +519,9 @@ static void tegra_dsi_pad_calibrate(struct dsi_pad_ctrl_reg *pad) writel(value, TEGRA_VI_BASE + (CSI_CIL_PAD_CONFIG << 2)); } -static void tegra_dsi_mipi_calibrate(struct tegra_dsi_priv *priv) +static void tegra_dsi_mipi_calibrate(struct udevice *dev) { + struct tegra_dsi_priv *priv = dev_get_priv(dev); struct dsi_pad_ctrl_reg *pad = &priv->dsi->pad; u32 value; int ret; @@ -545,15 +550,20 @@ static void tegra_dsi_mipi_calibrate(struct tegra_dsi_priv *priv) DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); writel(value, &pad->pad_ctrl_3); - ret = misc_write(priv->mipi, 0, NULL, 0); + ret = misc_write(priv->mipi, priv->calibration_pads, NULL, 0); if (ret) log_debug("%s: MIPI calibration failed %d\n", __func__, ret); + + if (priv->slave) + tegra_dsi_mipi_calibrate(priv->slave); } -static void tegra_dsi_set_timeout(struct dsi_timeout_reg *rtimeout, +static void tegra_dsi_set_timeout(struct udevice *dev, unsigned long bclk, unsigned int vrefresh) { + struct tegra_dsi_priv *priv = dev_get_priv(dev); + struct dsi_timeout_reg *rtimeout = &priv->dsi->timeout; unsigned int timeout; u32 value; @@ -569,12 +579,17 @@ static void tegra_dsi_set_timeout(struct dsi_timeout_reg *rtimeout, value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0); writel(value, &rtimeout->dsi_to_tally); + + if (priv->slave) + tegra_dsi_set_timeout(priv->slave, bclk, vrefresh); } -static void tegra_dsi_set_phy_timing(struct dsi_timing_reg *ptiming, +static void tegra_dsi_set_phy_timing(struct udevice *dev, unsigned long period, const struct mipi_dphy_timing *dphy_timing) { + struct tegra_dsi_priv *priv = dev_get_priv(dev); + struct dsi_timing_reg *ptiming = &priv->dsi->ptiming; u32 value; value = DSI_TIMING_FIELD(dphy_timing->hsexit, period, 1) << 24 | @@ -598,6 +613,31 @@ static void tegra_dsi_set_phy_timing(struct dsi_timing_reg *ptiming, DSI_TIMING_FIELD(dphy_timing->tasure, period, 1) << 8 | DSI_TIMING_FIELD(dphy_timing->tago, period, 1); writel(value, &ptiming->dsi_bta_timing); + + if (priv->slave) + tegra_dsi_set_phy_timing(priv->slave, period, dphy_timing); +} + +static u32 tegra_dsi_get_lanes(struct udevice *dev) +{ + struct tegra_dsi_priv *priv = dev_get_priv(dev); + struct mipi_dsi_device *device = &priv->device; + + if (priv->master) { + struct tegra_dsi_priv *mpriv = dev_get_priv(priv->master); + struct mipi_dsi_device *mdevice = &mpriv->device; + + return mdevice->lanes + device->lanes; + } + + if (priv->slave) { + struct tegra_dsi_priv *spriv = dev_get_priv(priv->slave); + struct mipi_dsi_device *sdevice = &spriv->device; + + return device->lanes + sdevice->lanes; + } + + return device->lanes; } static void tegra_dsi_ganged_enable(struct udevice *dev, unsigned int start, @@ -611,7 +651,7 @@ static void tegra_dsi_ganged_enable(struct udevice *dev, unsigned int start, writel(DSI_GANGED_MODE_CONTROL_ENABLE, &ganged->ganged_mode_ctrl); } -static void tegra_dsi_configure(struct udevice *dev, +static void tegra_dsi_configure(struct udevice *dev, unsigned int pipe, unsigned long mode_flags) { struct tegra_dsi_priv *priv = dev_get_priv(dev); @@ -642,7 +682,7 @@ static void tegra_dsi_configure(struct udevice *dev, value = DSI_CONTROL_CHANNEL(0) | DSI_CONTROL_FORMAT(priv->format) | DSI_CONTROL_LANES(device->lanes - 1) | - DSI_CONTROL_SOURCE(0); + DSI_CONTROL_SOURCE(pipe); writel(value, &misc->dsi_ctrl); writel(priv->video_fifo_depth, &misc->dsi_max_threshold); @@ -680,12 +720,19 @@ static void tegra_dsi_configure(struct udevice *dev, /* horizontal back porch */ hbp = timing->hback_porch.typ * mul / div; - if ((mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0) - hbp += hsw; - /* horizontal front porch */ hfp = timing->hfront_porch.typ * mul / div; + if (priv->master || priv->slave) { + hact /= 2; + hsw /= 2; + hbp = hbp / 2 - 1; + hfp /= 2; + } + + if ((mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0) + hbp += hsw; + /* subtract packet overhead */ hsw -= 10; hbp -= 14; @@ -695,9 +742,6 @@ static void tegra_dsi_configure(struct udevice *dev, writel(hact << 16 | hbp, &len->dsi_pkt_len_2_3); writel(hfp, &len->dsi_pkt_len_4_5); writel(0x0f0f << 16, &len->dsi_pkt_len_6_7); - - /* set SOL delay (for non-burst mode only) */ - writel(8 * mul / div, &misc->dsi_sol_delay); } else { if (priv->master || priv->slave) { /* @@ -717,32 +761,33 @@ static void tegra_dsi_configure(struct udevice *dev, value = MIPI_DCS_WRITE_MEMORY_START << 8 | MIPI_DCS_WRITE_MEMORY_CONTINUE; writel(value, &len->dsi_dcs_cmds); + } - /* set SOL delay */ - if (priv->master || priv->slave) { - unsigned long delay, bclk, bclk_ganged; - unsigned int lanes = device->lanes; - unsigned long htotal = timing->hactive.typ + timing->hfront_porch.typ + - timing->hback_porch.typ + timing->hsync_len.typ; - - /* SOL to valid, valid to FIFO and FIFO write delay */ - delay = 4 + 4 + 2; - delay = DIV_ROUND_UP(delay * mul, div * lanes); - /* FIFO read delay */ - delay = delay + 6; - - bclk = DIV_ROUND_UP(htotal * mul, div * lanes); - bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes); - value = bclk - bclk_ganged + delay + 20; - } else { - /* TODO: revisit for non-ganged mode */ - value = 8 * mul / div; - } - - writel(value, &misc->dsi_sol_delay); + /* set SOL delay */ + if (priv->master || priv->slave) { + unsigned long delay, bclk, bclk_ganged; + unsigned int lanes = tegra_dsi_get_lanes(dev); + unsigned long htotal = timing->hactive.typ + timing->hfront_porch.typ + + timing->hback_porch.typ + timing->hsync_len.typ; + + /* SOL to valid, valid to FIFO and FIFO write delay */ + delay = 4 + 4 + 2; + delay = DIV_ROUND_UP(delay * mul, div * lanes); + /* FIFO read delay */ + delay = delay + 6; + + bclk = DIV_ROUND_UP(htotal * mul, div * lanes); + bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes); + value = bclk - bclk_ganged + delay + 20; + } else { + /* set SOL delay (for non-burst mode only) */ + value = 8 * mul / div; } + writel(value, &misc->dsi_sol_delay); + if (priv->slave) { + tegra_dsi_configure(priv->slave, pipe, mode_flags); /* * TODO: Support modes other than symmetrical left-right * split. @@ -753,15 +798,31 @@ static void tegra_dsi_configure(struct udevice *dev, } } +static void tegra_dsi_enable(struct udevice *dev) +{ + struct tegra_dsi_priv *priv = dev_get_priv(dev); + struct dsi_misc_reg *misc = &priv->dsi->misc; + u32 value; + + /* enable DSI controller */ + value = readl(&misc->dsi_pwr_ctrl); + value |= DSI_POWER_CONTROL_ENABLE; + writel(value, &misc->dsi_pwr_ctrl); + + if (priv->slave) + tegra_dsi_enable(priv->slave); +} + static int tegra_dsi_encoder_enable(struct udevice *dev) { struct tegra_dsi_priv *priv = dev_get_priv(dev); + struct tegra_dc_plat *dc_plat = dev_get_plat(dev); struct mipi_dsi_device *device = &priv->device; struct display_timing *timing = &priv->timing; struct dsi_misc_reg *misc = &priv->dsi->misc; unsigned int mul, div; unsigned long bclk, plld, period; - u32 value; + u32 value, lanes; int ret; /* If for some reasone DSI is enabled then it needs to @@ -780,16 +841,17 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) writel(0, &misc->int_enable); if (priv->version) - tegra_dsi_mipi_calibrate(priv); + tegra_dsi_mipi_calibrate(dev); else tegra_dsi_pad_calibrate(&priv->dsi->pad); tegra_dsi_get_muldiv(device->format, &mul, &div); /* compute byte clock */ - bclk = (timing->pixelclock.typ * mul) / (div * device->lanes); + lanes = tegra_dsi_get_lanes(dev); + bclk = (timing->pixelclock.typ * mul) / (div * lanes); - tegra_dsi_set_timeout(&priv->dsi->timeout, bclk, 60); + tegra_dsi_set_timeout(dev, bclk, 60); /* * Compute bit clock and round up to the next MHz. @@ -813,25 +875,18 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) * The D-PHY timing fields are expressed in byte-clock cycles, so * multiply the period by 8. */ - tegra_dsi_set_phy_timing(&priv->dsi->ptiming, - period * 8, &priv->dphy_timing); + tegra_dsi_set_phy_timing(dev, period * 8, &priv->dphy_timing); /* Perform panel HW setup */ ret = panel_enable_backlight(priv->panel); if (ret) return ret; - tegra_dsi_configure(dev, device->mode_flags); + tegra_dsi_configure(dev, dc_plat->pipe, device->mode_flags); tegra_dc_enable_controller(dev); - /* enable DSI controller */ - value = readl(&misc->dsi_pwr_ctrl); - value |= DSI_POWER_CONTROL_ENABLE; - writel(value, &misc->dsi_pwr_ctrl); - - if (priv->slave) - tegra_dsi_encoder_enable(priv->slave); + tegra_dsi_enable(dev); return 0; } @@ -859,21 +914,35 @@ static void tegra_dsi_init_clocks(struct udevice *dev) struct tegra_dsi_priv *priv = dev_get_priv(dev); struct tegra_dc_plat *dc_plat = dev_get_plat(dev); struct mipi_dsi_device *device = &priv->device; - unsigned int mul, div; + unsigned int mul, div, lanes; unsigned long bclk, plld; - if (!priv->slave) { + /* Switch parents of DSI clocks in case of not standard parent */ + if (priv->clk->id == PERIPH_ID_DSI && + priv->clk_parent->id == CLOCK_ID_DISPLAY2) { + /* Change DSIA clock parent to PLLD2 */ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + + /* DSIA_CLK_SRC */ + setbits_le32(&clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_base, + BIT(25)); + } + + if (priv->clk->id == PERIPH_ID_DSIB && + priv->clk_parent->id == CLOCK_ID_DISPLAY) { /* Change DSIB clock parent to match DSIA */ struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - clrbits_le32(&clkrst->plld2.pll_base, BIT(25)); /* DSIB_CLK_SRC */ + /* DSIB_CLK_SRC */ + clrbits_le32(&clkrst->plld2.pll_base, BIT(25)); } tegra_dsi_get_muldiv(device->format, &mul, &div); - bclk = (priv->timing.pixelclock.typ * mul) / - (div * device->lanes); + lanes = tegra_dsi_get_lanes(dev); + bclk = (priv->timing.pixelclock.typ * mul) / (div * lanes); plld = DIV_ROUND_UP(bclk * 8, USEC_PER_SEC); @@ -893,16 +962,16 @@ static void tegra_dsi_init_clocks(struct udevice *dev) switch (clock_get_osc_freq()) { case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */ case CLOCK_OSC_FREQ_48_0: /* OSC is 48Mhz */ - clock_set_rate(CLOCK_ID_DISPLAY, plld, 12, 0, 8); + clock_set_rate(priv->clk_parent->id, plld, 12, 0, 8); break; case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */ - clock_set_rate(CLOCK_ID_DISPLAY, plld, 26, 0, 8); + clock_set_rate(priv->clk_parent->id, plld, 26, 0, 8); break; case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */ case CLOCK_OSC_FREQ_16_8: /* OSC is 16.8Mhz */ - clock_set_rate(CLOCK_ID_DISPLAY, plld, 13, 0, 8); + clock_set_rate(priv->clk_parent->id, plld, 13, 0, 8); break; case CLOCK_OSC_FREQ_19_2: @@ -914,11 +983,7 @@ static void tegra_dsi_init_clocks(struct udevice *dev) break; } - priv->dsi_clk = clock_decode_periph_id(dev); - - clock_enable(priv->dsi_clk); - udelay(2); - reset_set_enable(priv->dsi_clk, 0); + clk_enable(priv->clk); } static int tegra_dsi_ganged_probe(struct udevice *dev) @@ -955,6 +1020,20 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) return -EINVAL; } + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + log_debug("%s: Could not get DSI clock: %ld\n", + __func__, PTR_ERR(priv->clk)); + return PTR_ERR(priv->clk); + } + + priv->clk_parent = devm_clk_get(dev, "parent"); + if (IS_ERR(priv->clk_parent)) { + log_debug("%s: Could not get DSI clock parent: %ld\n", + __func__, PTR_ERR(priv->clk_parent)); + return PTR_ERR(priv->clk_parent); + } + priv->video_fifo_depth = 1920; priv->host_fifo_depth = 64; @@ -973,10 +1052,22 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) debug("%s: Cannot get avdd-dsi-csi-supply: error %d\n", __func__, ret); - ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, - "panel", &priv->panel); + /* Check all DSI children */ + device_foreach_child(priv->panel, dev) { + if (device_get_uclass_id(priv->panel) == UCLASS_PANEL) + break; + } + + /* if loop exits without panel device return error */ + if (device_get_uclass_id(priv->panel) != UCLASS_PANEL) { + log_debug("%s: panel not found, ret %d\n", __func__, ret); + return -EINVAL; + } + + ret = uclass_get_device_by_ofnode(UCLASS_PANEL, dev_ofnode(priv->panel), + &priv->panel); if (ret) { - printf("%s: Cannot get panel: error %d\n", __func__, ret); + log_debug("%s: Cannot get panel: error %d\n", __func__, ret); return log_ret(ret); } @@ -988,6 +1079,14 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) log_debug("%s: cannot get MIPI: error %d\n", __func__, ret); return ret; } + + ret = dev_read_u32_index(dev, "nvidia,mipi-calibrate", 1, + &priv->calibration_pads); + if (ret) { + log_debug("%s: cannot get calibration pads: error %d\n", + __func__, ret); + return ret; + } } panel_get_display_timing(priv->panel, &priv->timing); @@ -1028,6 +1127,7 @@ static const struct panel_ops tegra_dsi_bridge_ops = { static const struct udevice_id tegra_dsi_bridge_ids[] = { { .compatible = "nvidia,tegra30-dsi", .data = DSI_V0 }, { .compatible = "nvidia,tegra114-dsi", .data = DSI_V1 }, + { .compatible = "nvidia,tegra124-dsi", .data = DSI_V1 }, { } }; @@ -1036,6 +1136,7 @@ U_BOOT_DRIVER(tegra_dsi) = { .id = UCLASS_PANEL, .of_match = tegra_dsi_bridge_ids, .ops = &tegra_dsi_bridge_ops, + .bind = dm_scan_fdt_dev, .probe = tegra_dsi_bridge_probe, .plat_auto = sizeof(struct tegra_dc_plat), .priv_auto = sizeof(struct tegra_dsi_priv), diff --git a/drivers/video/tegra20/tegra-mipi.c b/drivers/video/tegra20/tegra-mipi.c index 2df3c1a9942..a4f4343d008 100644 --- a/drivers/video/tegra20/tegra-mipi.c +++ b/drivers/video/tegra20/tegra-mipi.c @@ -10,9 +10,10 @@ #include <linux/delay.h> #include <linux/iopoll.h> +#include <asm/arch/clock.h> #include <asm/io.h> -/* MIPI control registers 0x00 ~ 0x60 */ +/* MIPI control registers 0x00 ~ 0x74 */ struct mipi_ctlr { uint mipi_cal_ctrl; uint mipi_cal_autocal_ctrl; @@ -38,8 +39,17 @@ struct mipi_ctlr { uint mipi_cal_bias_pad_cfg0; uint mipi_cal_bias_pad_cfg1; uint mipi_cal_bias_pad_cfg2; + + uint mipi_cal_dsia_config_2; + uint mipi_cal_dsib_config_2; + uint mipi_cal_cilc_config_2; + uint mipi_cal_cild_config_2; + uint mipi_cal_csie_config_2; }; +#define MIPI_DSIA_PADS 0x60 +#define MIPI_DSIB_PADS 0x180 + #define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26) #define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24) #define MIPI_CAL_CTRL_CLKEN_OVR BIT(4) @@ -64,26 +74,25 @@ struct mipi_ctlr { #define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4) #define MIPI_CAL_BIAS_PAD_PDVREG BIT(1) +#define MIPI_CAL_HSCLKPDOSDSI(x) (((x) & 0x1f) << 8) +#define MIPI_CAL_HSCLKPUOSDSI(x) (((x) & 0x1f) << 0) + struct tegra_mipi_priv { struct mipi_ctlr *mipi; struct clk *mipi_cal; + u32 version; }; -static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf, - int size) +enum { + T114, + T124, +}; + +static void tegra114_mipi_pads_cal(struct tegra_mipi_priv *priv, + int calibration_pads) { - struct tegra_mipi_priv *priv = dev_get_priv(dev); u32 value; - value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(0x2) | - MIPI_CAL_BIAS_PAD_DRV_UP_REF(0x0); - writel(value, &priv->mipi->mipi_cal_bias_pad_cfg1); - - value = readl(&priv->mipi->mipi_cal_bias_pad_cfg2); - value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7); - value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7); - writel(value, &priv->mipi->mipi_cal_bias_pad_cfg2); - value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) | MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x4) | MIPI_CAL_TERMOS(0x5); @@ -99,6 +108,95 @@ static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf value = readl(&priv->mipi->mipi_cal_config_dsid); value &= ~(MIPI_CAL_SEL(0x1)); writel(value, &priv->mipi->mipi_cal_config_dsid); +} + +static void tegra124_mipi_pads_cal(struct tegra_mipi_priv *priv, + int calibration_pads) +{ + u32 value; + + /* Calibrate DSI-A */ + if (calibration_pads == MIPI_DSIA_PADS) { + printf("Calibrating DSI-A pads\n"); + + value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x0) | + MIPI_CAL_TERMOS(0x0); + writel(value, &priv->mipi->mipi_cal_config_dsia); + writel(value, &priv->mipi->mipi_cal_config_dsib); + + value = MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSCLKPDOSDSI(0x1) | + MIPI_CAL_HSCLKPUOSDSI(0x2); + writel(value, &priv->mipi->mipi_cal_dsia_config_2); + writel(value, &priv->mipi->mipi_cal_dsib_config_2); + + /* Deselect PAD C */ + value = readl(&priv->mipi->mipi_cal_cilc_config_2); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, &priv->mipi->mipi_cal_cilc_config_2); + + /* Deselect PAD D */ + value = readl(&priv->mipi->mipi_cal_cild_config_2); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, &priv->mipi->mipi_cal_cild_config_2); + } + + /* Calibrate DSI-B */ + if (calibration_pads == MIPI_DSIB_PADS) { + printf("Calibrating DSI-B pads\n"); + + value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x0) | + MIPI_CAL_TERMOS(0x0); + writel(value, &priv->mipi->mipi_cal_config_csic); + writel(value, &priv->mipi->mipi_cal_config_csid); + + value = MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSCLKPDOSDSI(0x1) | + MIPI_CAL_HSCLKPUOSDSI(0x2); + writel(value, &priv->mipi->mipi_cal_cilc_config_2); + writel(value, &priv->mipi->mipi_cal_cild_config_2); + + /* Deselect PAD A */ + value = readl(&priv->mipi->mipi_cal_dsia_config_2); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, &priv->mipi->mipi_cal_dsia_config_2); + + /* Deselect PAD B */ + value = readl(&priv->mipi->mipi_cal_dsib_config_2); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, &priv->mipi->mipi_cal_dsib_config_2); + } +} + +static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf, + int size) +{ + struct tegra_mipi_priv *priv = dev_get_priv(dev); + u32 value; + + value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(0x2) | + MIPI_CAL_BIAS_PAD_DRV_UP_REF(0x0); + writel(value, &priv->mipi->mipi_cal_bias_pad_cfg1); + + value = readl(&priv->mipi->mipi_cal_bias_pad_cfg2); + value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7); + value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7); + writel(value, &priv->mipi->mipi_cal_bias_pad_cfg2); + + switch (priv->version) { + case T114: + tegra114_mipi_pads_cal(priv, offset); + break; + + case T124: + tegra124_mipi_pads_cal(priv, offset); + break; + + default: + return -EINVAL; + } value = readl(&priv->mipi->mipi_cal_ctrl); value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf); @@ -134,6 +232,11 @@ static int tegra_mipi_enable(struct udevice *dev, bool val) struct tegra_mipi_priv *priv = dev_get_priv(dev); u32 value; + reset_set_enable(priv->mipi_cal->id, 1); + mdelay(100); + reset_set_enable(priv->mipi_cal->id, 0); + mdelay(1); + clk_enable(priv->mipi_cal); value = readl(&priv->mipi->mipi_cal_bias_pad_cfg0); @@ -157,6 +260,8 @@ static int tegra_mipi_probe(struct udevice *dev) { struct tegra_mipi_priv *priv = dev_get_priv(dev); + priv->version = dev_get_driver_data(dev); + priv->mipi = (struct mipi_ctlr *)dev_read_addr_ptr(dev); if (!priv->mipi) { log_debug("%s: no MIPI controller address\n", __func__); @@ -174,7 +279,8 @@ static int tegra_mipi_probe(struct udevice *dev) } static const struct udevice_id tegra_mipi_ids[] = { - { .compatible = "nvidia,tegra114-mipi" }, + { .compatible = "nvidia,tegra114-mipi", .data = T114 }, + { .compatible = "nvidia,tegra124-mipi", .data = T124 }, { } }; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b39b2546e5c..1bb67f50352 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -95,6 +95,15 @@ config WDT_APPLE The watchdog will perform a full SoC reset resulting in a reboot of the entire system. +config WDT_ADI + bool "Analog Devices watchdog timer support" + select WDT + select SPL_WDT if SPL + depends on ARCH_SC5XX + help + Enable this to support Watchdog Timer on ADI SC57X, SC58X, SC59X, + and SC59X_64 processors + config WDT_ARMADA_37XX bool "Marvell Armada 37xx watchdog timer support" depends on WDT && ARMADA_3700 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 9b6b1a8e8ad..e6bd4c587af 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -53,3 +53,4 @@ obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o obj-$(CONFIG_WDT_SUNXI) += sunxi_wdt.o obj-$(CONFIG_WDT_TANGIER) += tangier_wdt.o obj-$(CONFIG_WDT_XILINX) += xilinx_wwdt.o +obj-$(CONFIG_WDT_ADI) += adi_wdt.o diff --git a/drivers/watchdog/adi_wdt.c b/drivers/watchdog/adi_wdt.c new file mode 100644 index 00000000000..6f5b3d5d042 --- /dev/null +++ b/drivers/watchdog/adi_wdt.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Converted to driver model by Nathan Barrett-Morrison + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * + * adi_wtd.c - driver for ADI on-chip watchdog + * + */ + +#include <clk.h> +#include <dm.h> +#include <wdt.h> +#include <linux/delay.h> +#include <linux/ioport.h> +#include <linux/io.h> + +#define WDOG_CTL 0x0 +#define WDOG_CNT 0x4 +#define WDOG_STAT 0x8 + +#define RCU_CTL 0x0 +#define RCU_STAT 0x4 + +#define SEC_GCTL 0x0 +#define SEC_FCTL 0x10 +#define SEC_SCTL0 0x800 + +#define WDEN 0x0010 +#define WDDIS 0x0AD0 + +struct adi_wdt_priv { + void __iomem *rcu_base; + void __iomem *sec_base; + void __iomem *wdt_base; + struct clk clock; +}; + +static int adi_wdt_reset(struct udevice *dev) +{ + struct adi_wdt_priv *priv = dev_get_priv(dev); + + iowrite32(0, priv->wdt_base + WDOG_STAT); + + return 0; +} + +static int adi_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) +{ + struct adi_wdt_priv *priv = dev_get_priv(dev); + + /* Disable SYSCD_RESETb input and clear the RCU0 reset status */ + iowrite32(0xf, priv->rcu_base + RCU_STAT); + iowrite32(0x0, priv->rcu_base + RCU_CTL); + + /* reset the SEC controller */ + iowrite32(0x2, priv->sec_base + SEC_GCTL); + iowrite32(0x2, priv->sec_base + SEC_FCTL); + + udelay(50); + + /* enable SEC fault event */ + iowrite32(0x1, priv->sec_base + SEC_GCTL); + + /* ANOMALY 36100004 Spurious External Fault event occurs when FCTL + * is re-programmed when currently active fault is not cleared + */ + iowrite32(0xc0, priv->sec_base + SEC_FCTL); + iowrite32(0xc1, priv->sec_base + SEC_FCTL); + + /* enable SEC fault source for watchdog0 */ + setbits_32(priv->sec_base + SEC_SCTL0 + (3*8), 0x6); + + /* Enable SYSCD_RESETb input */ + iowrite32(0x100, priv->rcu_base + RCU_CTL); + + /* enable watchdog0 */ + iowrite32(WDDIS, priv->wdt_base + WDOG_CTL); + + iowrite32(timeout_ms / 1000 * + (clk_get_rate(&priv->clock) / (IS_ENABLED(CONFIG_SC58X) ? 2 : 1)), + priv->wdt_base + WDOG_CNT); + + iowrite32(0, priv->wdt_base + WDOG_STAT); + iowrite32(WDEN, priv->wdt_base + WDOG_CTL); + + return 0; +} + +static int adi_wdt_probe(struct udevice *dev) +{ + struct adi_wdt_priv *priv = dev_get_priv(dev); + int ret; + struct resource res; + + ret = dev_read_resource_byname(dev, "rcu", &res); + if (ret) + return ret; + priv->rcu_base = devm_ioremap(dev, res.start, resource_size(&res)); + + ret = dev_read_resource_byname(dev, "sec", &res); + if (ret) + return ret; + priv->sec_base = devm_ioremap(dev, res.start, resource_size(&res)); + + ret = dev_read_resource_byname(dev, "wdt", &res); + if (ret) + return ret; + priv->wdt_base = devm_ioremap(dev, res.start, resource_size(&res)); + + ret = clk_get_by_name(dev, "sclk0", &priv->clock); + if (ret < 0) { + printf("Can't get WDT clk: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct wdt_ops adi_wdt_ops = { + .start = adi_wdt_start, + .reset = adi_wdt_reset, +}; + +static const struct udevice_id adi_wdt_ids[] = { + { .compatible = "adi,wdt" }, + {} +}; + +U_BOOT_DRIVER(adi_wdt) = { + .name = "adi_wdt", + .id = UCLASS_WDT, + .of_match = adi_wdt_ids, + .probe = adi_wdt_probe, + .ops = &adi_wdt_ops, + .priv_auto = sizeof(struct adi_wdt_priv), + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/env/mmc.c b/env/mmc.c index 379f5ec9be7..2ef15fb72e7 100644 --- a/env/mmc.c +++ b/env/mmc.c @@ -40,18 +40,6 @@ DECLARE_GLOBAL_DATA_PTR; -/* - * In case the environment is redundant, stored in eMMC hardware boot - * partition and the environment and redundant environment offsets are - * identical, store the environment and redundant environment in both - * eMMC boot partitions, one copy in each. - * */ -#if (defined(CONFIG_SYS_REDUNDAND_ENVIRONMENT) && \ - (CONFIG_SYS_MMC_ENV_PART == 1) && \ - (CONFIG_ENV_OFFSET == CONFIG_ENV_OFFSET_REDUND)) -#define ENV_MMC_HWPART_REDUND 1 -#endif - #if CONFIG_IS_ENABLED(OF_CONTROL) static int mmc_env_partition_by_name(struct blk_desc *desc, const char *str, @@ -217,6 +205,23 @@ static inline s64 mmc_offset(struct mmc *mmc, int copy) } #endif +static bool mmc_env_is_redundant_in_both_boot_hwparts(struct mmc *mmc) +{ + /* + * In case the environment is redundant, stored in eMMC hardware boot + * partition and the environment and redundant environment offsets are + * identical, store the environment and redundant environment in both + * eMMC boot partitions, one copy in each. + */ + if (!IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) + return false; + + if (CONFIG_SYS_MMC_ENV_PART != 1) + return false; + + return mmc_offset(mmc, 0) == mmc_offset(mmc, 1); +} + __weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr) { s64 offset = mmc_offset(mmc, copy); @@ -336,7 +341,7 @@ static int env_mmc_save(void) if (gd->env_valid == ENV_VALID) copy = 1; - if (IS_ENABLED(ENV_MMC_HWPART_REDUND)) { + if (mmc_env_is_redundant_in_both_boot_hwparts(mmc)) { ret = mmc_set_env_part(mmc, copy + 1); if (ret) goto fini; @@ -409,7 +414,7 @@ static int env_mmc_erase(void) if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) { copy = 1; - if (IS_ENABLED(ENV_MMC_HWPART_REDUND)) { + if (mmc_env_is_redundant_in_both_boot_hwparts(mmc)) { ret = mmc_set_env_part(mmc, copy + 1); if (ret) goto fini; @@ -443,13 +448,7 @@ static inline int read_env(struct mmc *mmc, unsigned long size, return (n == blk_cnt) ? 0 : -1; } -#if defined(ENV_IS_EMBEDDED) -static int env_mmc_load(void) -{ - return 0; -} -#elif defined(CONFIG_SYS_REDUNDAND_ENVIRONMENT) -static int env_mmc_load(void) +static int env_mmc_load_redundant(void) { struct mmc *mmc; u32 offset1, offset2; @@ -477,7 +476,7 @@ static int env_mmc_load(void) goto fini; } - if (IS_ENABLED(ENV_MMC_HWPART_REDUND)) { + if (mmc_env_is_redundant_in_both_boot_hwparts(mmc)) { ret = mmc_set_env_part(mmc, 1); if (ret) goto fini; @@ -485,7 +484,7 @@ static int env_mmc_load(void) read1_fail = read_env(mmc, CONFIG_ENV_SIZE, offset1, tmp_env1); - if (IS_ENABLED(ENV_MMC_HWPART_REDUND)) { + if (mmc_env_is_redundant_in_both_boot_hwparts(mmc)) { ret = mmc_set_env_part(mmc, 2); if (ret) goto fini; @@ -505,8 +504,8 @@ err: return ret; } -#else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */ -static int env_mmc_load(void) + +static int env_mmc_load_singular(void) { ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); struct mmc *mmc; @@ -551,7 +550,16 @@ err: return ret; } -#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ + +static int env_mmc_load(void) +{ + if (IS_ENABLED(CONFIG_ENV_IS_EMBEDDED)) + return 0; + else if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) + return env_mmc_load_redundant(); + else + return env_mmc_load_singular(); +} U_BOOT_ENV_LOCATION(mmc) = { .location = ENVL_MMC, diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig index 9bb11eac9f7..19d52238713 100644 --- a/fs/fat/Kconfig +++ b/fs/fat/Kconfig @@ -13,6 +13,13 @@ config FAT_WRITE This provides support for creating and writing new files to an existing FAT filesystem partition. +config FAT_RENAME + bool "Enable filesystem rename support" + depends on FAT_WRITE + help + This provides support for renaming and moving files within a + FAT filesystem partition. + config FS_FAT_MAX_CLUSTSIZE int "Set maximum possible clustersize" default 65536 diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index ea877ee9171..0b924541187 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -1216,6 +1216,124 @@ static void fill_dentry(fsdata *mydata, dir_entry *dentptr, } /** + * fat_itr_parent() - modifies the iterator to the parent directory of the + * current iterator. + * + * @itr: iterator positioned anywhere in a directory + * @Return: 0 if the iterator is in the parent directory, -errno otherwise + */ +static int fat_itr_parent(fat_itr *itr) +{ + int ret; + + if (itr->is_root) + return -EIO; + + /* ensure iterator is at the first directory entry */ + ret = fat_move_to_cluster(itr, itr->start_clust); + if (ret) + return ret; + + return fat_itr_resolve(itr, "..", TYPE_DIR); +} + +/** + * update_parent_dir_props - updates the modified time for the parent directory + * + * @dir_itr: iterator positioned anywhere in a directory whose parent + * should be updated + * @Return: 0 for success, -errno otherwise + */ +static int update_parent_dir_props(fat_itr *dir_itr) +{ + int ret = 0; + + fat_itr itr; + fsdata fsdata = { .fatbuf = NULL, }, *mydata = &fsdata; + __u32 target_clust = dir_itr->start_clust; + + /* Short circuit if no RTC because it only updates timestamps */ + if (!CONFIG_IS_ENABLED(DM_RTC)) + return ret; + + /* duplicate fsdata */ + itr = *dir_itr; + fsdata = *itr.fsdata; + + /* allocate local fat buffer */ + fsdata.fatbuf = malloc_cache_aligned(FATBUFSIZE); + if (!fsdata.fatbuf) { + log_debug("Error: allocating memory\n"); + ret = -ENOMEM; + return ret; + } + + fsdata.fatbufnum = -1; + itr.fsdata = &fsdata; + + if (!itr.is_root) { + ret = fat_itr_parent(&itr); + if (ret) + goto exit; + + while (fat_itr_next(&itr)) { + if (START(itr.dent) == target_clust) + goto update; + } + + /* dent not found */ + ret = -EIO; + goto exit; +update: + dentry_set_time(itr.dent); + ret = flush_dir(&itr); + } + +exit: + free(fsdata.fatbuf); + + return ret; +} + +/** + * create_link() - inserts a directory entry for a file or directory + * + * @itr: directory iterator + * @basename: file name + * @clust: cluster number the new directory entry should point to. Use 0 + * if no cluster is assigned yet + * @size: file size + * @attr: file attributes + * Return: 0 for success + */ +static int create_link(fat_itr *itr, char *basename, __u32 clust, __u32 size, + __u8 attr) +{ + char shortname[SHORT_NAME_SIZE]; + int ndent; + int ret; + + /* Check if long name is needed */ + ndent = set_name(itr, basename, shortname); + if (ndent < 0) + return ndent; + ret = fat_find_empty_dentries(itr, ndent); + if (ret) + return ret; + if (ndent > 1) { + /* Set long name entries */ + ret = fill_dir_slot(itr, basename, shortname); + if (ret) + return ret; + } + + fill_dentry(itr->fsdata, itr->dent, shortname, clust, size, attr); + ret = update_parent_dir_props(itr); + + return ret; +} + +/** * find_directory_entry() - find a directory entry by filename * * @itr: directory iterator @@ -1420,35 +1538,15 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer, /* Update change date */ dentry_set_time(retdent); } else { - /* Create a new file */ - char shortname[SHORT_NAME_SIZE]; - int ndent; - if (pos) { /* No hole allowed */ ret = -EINVAL; goto exit; } - /* Check if long name is needed */ - ndent = set_name(itr, basename, shortname); - if (ndent < 0) { - ret = ndent; - goto exit; - } - ret = fat_find_empty_dentries(itr, ndent); + ret = create_link(itr, basename, 0, size, ATTR_ARCH); if (ret) goto exit; - if (ndent > 1) { - /* Set long name entries */ - ret = fill_dir_slot(itr, basename, shortname); - if (ret) - goto exit; - } - - /* Set short name entry */ - fill_dentry(itr->fsdata, itr->dent, shortname, 0, size, - ATTR_ARCH); retdent = itr->dent; } @@ -1565,6 +1663,36 @@ static int delete_long_name(fat_itr *itr) } /** + * delete_dentry_link() - deletes a directory entry, but not the cluster chain + * it points to + * + * @itr: the first directory entry (if a longname) to remove + * Return: 0 for success + */ +static int delete_dentry_link(fat_itr *itr) +{ + int ret; + + itr->dent = itr->dent_start; + itr->remaining = itr->dent_rem; + /* Delete long name */ + if ((itr->dent->attr & ATTR_VFAT) == ATTR_VFAT && + (itr->dent->nameext.name[0] & LAST_LONG_ENTRY_MASK)) { + ret = delete_long_name(itr); + if (ret) + return ret; + } + /* Delete short name */ + delete_single_dentry(itr); + + ret = flush_dir(itr); + if (ret) + return ret; + + return update_parent_dir_props(itr); +} + +/** * delete_dentry_long() - remove directory entry * * @itr: directory iterator @@ -1589,21 +1717,7 @@ static int delete_dentry_long(fat_itr *itr) if (ret) return ret; } - itr->dent = itr->dent_start; - itr->remaining = itr->dent_rem; - dent = itr->dent_start; - /* Delete long name */ - if ((dent->attr & ATTR_VFAT) == ATTR_VFAT && - (dent->nameext.name[0] & LAST_LONG_ENTRY_MASK)) { - int ret; - - ret = delete_long_name(itr); - if (ret) - return ret; - } - /* Delete short name */ - delete_single_dentry(itr); - return flush_dir(itr); + return delete_dentry_link(itr); } int fat_unlink(const char *filename) @@ -1725,9 +1839,6 @@ int fat_mkdir(const char *dirname) ret = -EEXIST; goto exit; } else { - char shortname[SHORT_NAME_SIZE]; - int ndent; - if (itr->is_root) { /* root dir cannot have "." or ".." */ if (!strcmp(l_dirname, ".") || @@ -1737,25 +1848,9 @@ int fat_mkdir(const char *dirname) } } - /* Check if long name is needed */ - ndent = set_name(itr, basename, shortname); - if (ndent < 0) { - ret = ndent; - goto exit; - } - ret = fat_find_empty_dentries(itr, ndent); + ret = create_link(itr, basename, 0, 0, ATTR_DIR | ATTR_ARCH); if (ret) goto exit; - if (ndent > 1) { - /* Set long name entries */ - ret = fill_dir_slot(itr, basename, shortname); - if (ret) - goto exit; - } - - /* Set attribute as archive for regular file */ - fill_dentry(itr->fsdata, itr->dent, shortname, 0, 0, - ATTR_DIR | ATTR_ARCH); retdent = itr->dent; } @@ -1813,3 +1908,272 @@ exit: free(dotdent); return ret; } + +/** + * check_path_prefix() - ensures one path does not contains another path as a + * prefix. + * + * for example: path foo/bar/baz/qux contains the path prefix foo/bar/baz + * + * note: the iterator may be pointing to any directory entry in the directory + * + * @prefix_clust: start cluster of the final directory in the prefix path + * (the start cluster of 'baz' in the above example) + * @path_itr: iterator of the path to check (an iterator pointing to any + * direntry in 'qux' in the above example) + * Return: -errno on error, 0 if path_itr does not have the directory + * at prefix_clust as an ancestor. + */ +static int check_path_prefix(loff_t prefix_clust, fat_itr *path_itr) +{ + fat_itr itr; + fsdata fsdata = { .fatbuf = NULL, }, *mydata = &fsdata; + int ret; + + /* duplicate fsdata */ + itr = *path_itr; + fsdata = *itr.fsdata; + + /* allocate local fat buffer */ + fsdata.fatbuf = malloc_cache_aligned(FATBUFSIZE); + if (!fsdata.fatbuf) { + log_debug("Error: allocating memory\n"); + ret = -ENOMEM; + goto exit; + } + + fsdata.fatbufnum = -1; + itr.fsdata = &fsdata; + + /* ensure iterator is at the first directory entry */ + ret = fat_move_to_cluster(&itr, itr.start_clust); + if (ret) + goto exit; + + while (1) { + if (prefix_clust == itr.start_clust) { + ret = -EINVAL; + goto exit; + } + + if (itr.is_root) { + ret = 0; + goto exit; + } + + /* Should not occur in a well-formed FAT filesystem besides the root */ + if (fat_itr_parent(&itr)) { + log_debug("FAT filesystem corrupt!\n"); + log_debug("dir @ clust %u has no parent direntry\n", + itr.start_clust); + ret = -EIO; + goto exit; + } + } + +exit: + free(fsdata.fatbuf); + return ret; +} + +/** + * fat_rename - rename/move a file or directory + * + * @old_path: path to the existing file/directory + * @new_path: new path/name for the rename/move + * Return: 0 on success, -errno otherwise + */ +int fat_rename(const char *old_path, const char *new_path) +{ + fat_itr *old_itr = NULL, *new_itr = NULL; + fsdata old_datablock = { .fatbuf = NULL, }; + fsdata new_datablock = { .fatbuf = NULL, }; + /* used for START macro */ + fsdata *mydata = &old_datablock; + int ret = -EIO, is_old_dir; + char *old_path_copy, *old_dirname, *old_basename; + char *new_path_copy, *new_dirname, *new_basename; + char l_new_basename[VFAT_MAXLEN_BYTES]; + __u32 old_clust; + dir_entry *found_existing; + /* only set if found_existing != NULL */ + __u32 new_clust; + + old_path_copy = strdup(old_path); + new_path_copy = strdup(new_path); + old_itr = malloc_cache_aligned(sizeof(fat_itr)); + new_itr = malloc_cache_aligned(sizeof(fat_itr)); + if (!old_path_copy || !new_path_copy || !old_itr || !new_itr) { + log_debug("Error: out of memory\n"); + ret = -ENOMEM; + goto exit; + } + split_filename(old_path_copy, &old_dirname, &old_basename); + split_filename(new_path_copy, &new_dirname, &new_basename); + + if (normalize_longname(l_new_basename, new_basename)) { + log_debug("FAT: illegal filename (%s)\n", new_basename); + ret = -EINVAL; + goto exit; + } + + if (!strcmp(old_basename, ".") || !strcmp(old_basename, "..") || + !strcmp(old_basename, "") || !strcmp(l_new_basename, ".") || + !strcmp(l_new_basename, "..") || !strcmp(l_new_basename, "")) { + ret = -EINVAL; + goto exit; + } + + /* checking for old_path == new_path is deferred until they're resolved */ + + /* resolve old_path */ + ret = fat_itr_root(old_itr, &old_datablock); + if (ret) + goto exit; + + ret = fat_itr_resolve(old_itr, old_dirname, TYPE_DIR); + if (ret) { + log_debug("%s doesn't exist (%d)\n", old_dirname, ret); + ret = -ENOENT; + goto exit; + } + + if (!find_directory_entry(old_itr, old_basename)) { + log_debug("%s doesn't exist (%d)\n", old_basename, -ENOENT); + ret = -ENOENT; + goto exit; + } + + /* store clust old_path points to, to relink later */ + total_sector = old_datablock.total_sect; + old_clust = START(old_itr->dent); + is_old_dir = fat_itr_isdir(old_itr); + + /* resolve new_path*/ + ret = fat_itr_root(new_itr, &new_datablock); + if (ret) + goto exit; + + ret = fat_itr_resolve(new_itr, new_dirname, TYPE_DIR); + if (ret) { + log_debug("%s doesn't exist (%d)\n", new_dirname, ret); + ret = -ENOENT; + goto exit; + } + + found_existing = find_directory_entry(new_itr, l_new_basename); + + if (found_existing) { + /* store cluster of new_path since it may need to be deleted */ + new_clust = START(new_itr->dent); + + /* old_path is new_path, noop */ + if (old_clust == new_clust) { + ret = 0; + goto exit; + } + + if (fat_itr_isdir(new_itr) != is_old_dir) { + if (is_old_dir) + ret = -ENOTDIR; + else + ret = -EISDIR; + goto exit; + } + } + + if (is_old_dir) { + ret = check_path_prefix(old_clust, new_itr); + if (ret) + goto exit; + } + + /* create/update dentry to point to old_path's data cluster */ + if (found_existing) { + struct nameext new_name = new_itr->dent->nameext; + __u8 lcase = new_itr->dent->lcase; + + if (is_old_dir) { + int n_entries = fat_dir_entries(new_itr); + + if (n_entries < 0) { + ret = n_entries; + goto exit; + } + if (n_entries > 2) { + log_debug("Error: directory is not empty: %d\n", + n_entries); + ret = -ENOTEMPTY; + goto exit; + } + } + + *new_itr->dent = *old_itr->dent; + new_itr->dent->nameext = new_name; + new_itr->dent->lcase = lcase; + + ret = update_parent_dir_props(new_itr); + if (ret) + goto exit; + } else { + /* reset iterator to the start of the directory */ + ret = fat_move_to_cluster(new_itr, new_itr->start_clust); + if (ret) + goto exit; + + ret = create_link(new_itr, l_new_basename, old_clust, + old_itr->dent->size, + old_itr->dent->attr | ATTR_ARCH); + if (ret) + goto exit; + } + + ret = flush_dir(new_itr); + if (ret) + goto exit; + + /* with new_path data cluster unreferenced, clear it */ + if (found_existing) { + ret = clear_fatent(&new_datablock, new_clust); + if (ret) + goto exit; + } + + /* update moved directory so the parent is new_path */ + if (is_old_dir) { + __u32 clust = new_itr->start_clust; + dir_entry *dent; + + fat_itr_child(new_itr, new_itr); + dent = find_directory_entry(new_itr, ".."); + if (!dent) { + log_debug("FAT filesystem corrupt!\n"); + log_debug("dir %s has no parent direntry\n", + l_new_basename); + ret = -EIO; + goto exit; + } + set_start_cluster(&new_datablock, dent, clust); + ret = flush_dir(new_itr); + if (ret) + goto exit; + /* restore directory location to update parent props below */ + fat_itr_child(new_itr, new_itr); + } + + /* refresh old in case write happened to the same block. */ + ret = fat_move_to_cluster(old_itr, old_itr->dent_clust); + if (ret) + goto exit; + + ret = delete_dentry_link(old_itr); +exit: + free(new_datablock.fatbuf); + free(old_datablock.fatbuf); + free(new_itr); + free(old_itr); + free(new_path_copy); + free(old_path_copy); + + return ret; +} @@ -143,6 +143,12 @@ static inline int fs_mkdir_unsupported(const char *dirname) return -1; } +static inline int fs_rename_unsupported(const char *old_path, + const char *new_path) +{ + return -1; +} + struct fstype_info { int fstype; char *name; @@ -183,6 +189,7 @@ struct fstype_info { int (*unlink)(const char *filename); int (*mkdir)(const char *dirname); int (*ln)(const char *filename, const char *target); + int (*rename)(const char *old_path, const char *new_path); }; static struct fstype_info fstypes[] = { @@ -211,6 +218,11 @@ static struct fstype_info fstypes[] = { .readdir = fat_readdir, .closedir = fat_closedir, .ln = fs_ln_unsupported, +#if CONFIG_IS_ENABLED(FAT_RENAME) && !IS_ENABLED(CONFIG_XPL_BUILD) + .rename = fat_rename, +#else + .rename = fs_rename_unsupported, +#endif }, #endif @@ -238,6 +250,7 @@ static struct fstype_info fstypes[] = { .closedir = ext4fs_closedir, .unlink = fs_unlink_unsupported, .mkdir = fs_mkdir_unsupported, + .rename = fs_rename_unsupported, }, #endif #if IS_ENABLED(CONFIG_SANDBOX) && !IS_ENABLED(CONFIG_XPL_BUILD) @@ -257,6 +270,7 @@ static struct fstype_info fstypes[] = { .unlink = fs_unlink_unsupported, .mkdir = fs_mkdir_unsupported, .ln = fs_ln_unsupported, + .rename = fs_rename_unsupported, }, #endif #if CONFIG_IS_ENABLED(SEMIHOSTING) @@ -276,6 +290,7 @@ static struct fstype_info fstypes[] = { .unlink = fs_unlink_unsupported, .mkdir = fs_mkdir_unsupported, .ln = fs_ln_unsupported, + .rename = fs_rename_unsupported, }, #endif #ifndef CONFIG_XPL_BUILD @@ -296,6 +311,7 @@ static struct fstype_info fstypes[] = { .unlink = fs_unlink_unsupported, .mkdir = fs_mkdir_unsupported, .ln = fs_ln_unsupported, + .rename = fs_rename_unsupported, }, #endif #endif @@ -317,6 +333,7 @@ static struct fstype_info fstypes[] = { .unlink = fs_unlink_unsupported, .mkdir = fs_mkdir_unsupported, .ln = fs_ln_unsupported, + .rename = fs_rename_unsupported, }, #endif #endif @@ -339,6 +356,7 @@ static struct fstype_info fstypes[] = { .ln = fs_ln_unsupported, .unlink = fs_unlink_unsupported, .mkdir = fs_mkdir_unsupported, + .rename = fs_rename_unsupported, }, #endif #if IS_ENABLED(CONFIG_FS_EROFS) @@ -360,6 +378,7 @@ static struct fstype_info fstypes[] = { .ln = fs_ln_unsupported, .unlink = fs_unlink_unsupported, .mkdir = fs_mkdir_unsupported, + .rename = fs_rename_unsupported, }, #endif { @@ -378,6 +397,7 @@ static struct fstype_info fstypes[] = { .unlink = fs_unlink_unsupported, .mkdir = fs_mkdir_unsupported, .ln = fs_ln_unsupported, + .rename = fs_rename_unsupported, }, }; @@ -713,6 +733,22 @@ int fs_ln(const char *fname, const char *target) return ret; } +int fs_rename(const char *old_path, const char *new_path) +{ + struct fstype_info *info = fs_get_info(fs_type); + int ret; + + ret = info->rename(old_path, new_path); + + if (ret < 0) { + log_debug("Unable to rename %s -> %s\n", old_path, new_path); + ret = -1; + } + fs_close(); + + return ret; +} + int do_size(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], int fstype) { @@ -975,6 +1011,65 @@ int do_ln(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], return 0; } +int do_mv(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype) +{ + struct fs_dir_stream *dirs; + char *src = argv[3]; + char *dst = argv[4]; + char *new_dst = NULL; + int ret = 1; + + if (argc != 5) { + ret = CMD_RET_USAGE; + goto exit; + } + + if (fs_set_blk_dev(argv[1], argv[2], fstype)) + goto exit; + + dirs = fs_opendir(dst); + /* dirs being valid means dst points to an existing directory. + * mv should copy the file/dir (keeping the same name) into the + * directory + */ + if (dirs) { + char *src_name = strrchr(src, '/'); + int dst_len; + + if (src_name) + src_name += 1; + else + src_name = src; + + dst_len = strlen(dst); + new_dst = calloc(1, dst_len + strlen(src_name) + 2); + strcpy(new_dst, dst); + + /* If there is already a trailing slash, don't add another */ + if (new_dst[dst_len - 1] != '/') { + new_dst[dst_len] = '/'; + dst_len += 1; + } + + strcpy(new_dst + dst_len, src_name); + dst = new_dst; + } + fs_closedir(dirs); + + if (fs_set_blk_dev(argv[1], argv[2], fstype)) + goto exit; + + if (fs_rename(src, dst)) + goto exit; + + ret = 0; + +exit: + free(new_dst); + return ret; +} + int do_fs_types(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) { struct fstype_info *drv = fstypes; diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c index 8fac6c6c5a9..7c364686f14 100644 --- a/fs/squashfs/sqfs.c +++ b/fs/squashfs/sqfs.c @@ -1712,7 +1712,8 @@ static int sqfs_size_nest(const char *filename, loff_t *size) case SQFS_LSYMLINK_TYPE: if (++symlinknest == MAX_SYMLINK_NEST) { *size = 0; - return -ELOOP; + ret = -ELOOP; + break; } symlink = (struct squashfs_symlink_inode *)ipos; diff --git a/include/configs/mocha.h b/include/configs/mocha.h new file mode 100644 index 00000000000..1c2eb906085 --- /dev/null +++ b/include/configs/mocha.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. + * + * Copyright (c) 2024, Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include "tegra124-common.h" + +/* High-level configuration options */ +#define CFG_TEGRA_BOARD_STRING "Xiaomi Mocha" + +/* Board-specific serial config */ +#define CFG_SYS_NS16550_COM1 NV_PA_APB_UARTD_BASE + +#ifdef CONFIG_TEGRA_SUPPORT_NON_SECURE + #define CFG_PRAM 0x38400 /* 225 MB */ +#endif + +#include "tegra-common-post.h" + +#endif /* __CONFIG_H */ diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 2372485c84e..db2ac7f83bb 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -6,7 +6,7 @@ #ifndef __CONFIG_H #define __CONFIG_H -#define CFG_MALLOC_F_ADDR 0x0010000 +#define CFG_MALLOC_F_ADDR 0x000f4000 /* Size of our emulated memory */ #define SB_CONCAT(x, y) x ## y diff --git a/include/crypto/mscode.h b/include/crypto/mscode.h index 678e69001b9..55501c22acb 100644 --- a/include/crypto/mscode.h +++ b/include/crypto/mscode.h @@ -10,6 +10,7 @@ #include <crypto/hash_info.h> #endif #if CONFIG_IS_ENABLED(MBEDTLS_LIB_X509) +#include "mbedtls_options.h" #include <mbedtls/asn1.h> #include <mbedtls/oid.h> #endif diff --git a/include/crypto/pkcs7_parser.h b/include/crypto/pkcs7_parser.h index 469c2711fa6..fd1e48da09e 100644 --- a/include/crypto/pkcs7_parser.h +++ b/include/crypto/pkcs7_parser.h @@ -12,6 +12,7 @@ #include <crypto/pkcs7.h> #include <crypto/x509_parser.h> #if CONFIG_IS_ENABLED(MBEDTLS_LIB_X509) +#include "mbedtls_options.h" #include <mbedtls/pkcs7.h> #include <library/x509_internal.h> #include <mbedtls/asn1.h> diff --git a/include/dm/ofnode_graph.h b/include/dm/ofnode_graph.h new file mode 100644 index 00000000000..908c990a3f3 --- /dev/null +++ b/include/dm/ofnode_graph.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#ifndef _DM_OFNODE_GRAPH_H +#define _DM_OFNODE_GRAPH_H + +#include <dm/of.h> + +/** + * ofnode_graph_get_endpoint_count() - get the number of endpoints in a device ofnode + * @parent: ofnode to the device containing ports and endpoints + * + * Return: count of endpoint of this device ofnode + */ +unsigned int ofnode_graph_get_endpoint_count(ofnode parent); + +/** + * ofnode_graph_get_port_count() - get the number of port in a device or ports ofnode + * @parent: ofnode to the device or ports node + * + * Return: count of port of this device or ports node + */ +unsigned int ofnode_graph_get_port_count(ofnode parent); + +/** + * ofnode_graph_get_port_by_id() - get the port matching a given id + * @parent: parent ofnode + * @id: id of the port + * + * Return: ofnode in given port. + */ +ofnode ofnode_graph_get_port_by_id(ofnode parent, u32 id); + +/** + * ofnode_graph_get_endpoint_by_regs() - get the endpoint matching a given id + * @parent: parent ofnode + * @reg_id: id of the port + * @id: id for the endpoint + * + * Return: ofnode in given endpoint or NULL if not found. + * reg and port_reg are ignored when they are -1. + */ +ofnode ofnode_graph_get_endpoint_by_regs(ofnode parent, u32 reg_id, u32 id); + +/** + * ofnode_graph_get_remote_endpoint() - get remote endpoint node + * @endoint: ofnode of a local endpoint + * + * Return: Remote endpoint ofnode linked with local endpoint. + */ +ofnode ofnode_graph_get_remote_endpoint(ofnode endpoint); + +/** + * ofnode_graph_get_port_parent() - get port's parent node + * @endpoint: ofnode of a local endpoint + * + * Return: device ofnode associated with endpoint + */ +ofnode ofnode_graph_get_port_parent(ofnode endpoint); + +/** + * ofnode_graph_get_remote_port_parent() - get remote port's parent ofnode + * @endoint: ofnode of a local endpoint + * + * Return: device ofnode associated with endpoint linked to local endpoint. + */ +ofnode ofnode_graph_get_remote_port_parent(ofnode endpoint); + +/** + * ofnode_graph_get_remote_port() - get remote port ofnode + * @endoint: ofnode of a local endpoint + * + * Return: port ofnode associated with remote endpoint node linked + * to local endpoint. + */ +ofnode ofnode_graph_get_remote_port(ofnode endpoint); + +/** + * ofnode_graph_get_remote_node() - get remote parent ofnode for given port/endpoint + * @parent: parent ofnode containing graph port/endpoint + * @port: identifier (value of reg property) of the parent port ofnode + * @endpoint: identifier (value of reg property) of the endpoint ofnode + * + * Return: device ofnode associated with endpoint linked to local endpoint. + */ +ofnode ofnode_graph_get_remote_node(ofnode parent, u32 port, u32 endpoint); + +#endif diff --git a/include/dt-bindings/pinctrl/adi-adsp.h b/include/dt-bindings/pinctrl/adi-adsp.h new file mode 100644 index 00000000000..7dc8a1ef5c4 --- /dev/null +++ b/include/dt-bindings/pinctrl/adi-adsp.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * + */ + +#ifndef DT_BINDINGS_PINCTRL_ADI_ADSP +#define DT_BINDINGS_PINCTRL_ADI_ADSP + +#define ADI_ADSP_PIN(port, pin) (16 * ((port) - 'A') + (pin)) +#define ADI_ADSP_PINFUNC_ALT0 0 +#define ADI_ADSP_PINFUNC_ALT1 1 +#define ADI_ADSP_PINFUNC_ALT2 2 +#define ADI_ADSP_PINFUNC_ALT3 3 + +#endif diff --git a/include/efi_loader.h b/include/efi_loader.h index 1d75d97ebbc..e9c10819ba2 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -15,13 +15,13 @@ #include <efi_api.h> #include <image.h> #include <pe.h> +#include <setjmp.h> #include <linux/list.h> #include <linux/sizes.h> #include <linux/oid_registry.h> struct blk_desc; struct bootflow; -struct jmp_buf_data; #if CONFIG_IS_ENABLED(EFI_LOADER) @@ -129,17 +129,22 @@ static inline void efi_set_bootdev(const char *dev, const char *devnr, #if CONFIG_IS_ENABLED(NETDEVICES) && CONFIG_IS_ENABLED(EFI_LOADER) /* Call this to update the current device path of the efi net device */ -efi_status_t efi_net_set_dp(const char *dev, const char *server); +efi_status_t efi_net_new_dp(const char *dev, const char *server, struct udevice *udev); /* Call this to get the current device path of the efi net device */ -void efi_net_get_dp(struct efi_device_path **dp); +void efi_net_dp_from_dev(struct efi_device_path **dp, struct udevice *udev, bool cache_only); void efi_net_get_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw); + struct efi_ipv4_address *gw, + struct udevice *dev); void efi_net_set_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw); + struct efi_ipv4_address *gw, + struct udevice *dev); +#if IS_ENABLED(CONFIG_EFI_HTTP_PROTOCOL) efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buffer, - u32 *status_code, ulong *file_size, char *headers_buffer); + u32 *status_code, ulong *file_size, char *headers_buffer, + struct efi_service_binding_protocol *parent); +#endif #define MAX_HTTP_HEADERS_SIZE SZ_64K #define MAX_HTTP_HEADERS 100 #define MAX_HTTP_HEADER_NAME 128 @@ -151,13 +156,16 @@ struct http_header { void efi_net_parse_headers(ulong *num_headers, struct http_header *headers); #else -static inline void efi_net_get_dp(struct efi_device_path **dp) { } +static inline void efi_net_dp_from_dev(struct efi_device_path **dp, + struct udevice *udev, bool cache_only) { } static inline void efi_net_get_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw) { } + struct efi_ipv4_address *gw, + struct udevice *dev) { } static inline void efi_net_set_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw) { } + struct efi_ipv4_address *gw, + struct udevice *dev) { } #endif /* Maximum number of configuration tables */ @@ -321,6 +329,8 @@ extern const efi_guid_t efi_guid_host_dev; #endif /* GUID of the EFI_BLOCK_IO_PROTOCOL */ extern const efi_guid_t efi_block_io_guid; +/* GUID of the EFI_SIMPLE_NETWORK_PROTOCOL */ +extern const efi_guid_t efi_net_guid; 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; @@ -485,7 +495,7 @@ struct efi_loaded_image_obj { efi_status_t *exit_status; efi_uintn_t *exit_data_size; u16 **exit_data; - struct jmp_buf_data *exit_jmp; + jmp_buf *exit_jmp; EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, struct efi_system_table *st); u16 image_type; @@ -647,7 +657,8 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, /* Called by bootefi to make GOP (graphical) interface available */ efi_status_t efi_gop_register(void); /* Called by bootefi to make the network interface available */ -efi_status_t efi_net_register(void); +efi_status_t efi_net_register(struct udevice *dev); +efi_status_t efi_net_do_start(struct udevice *dev); /* Called by efi_net_register to make the ip4 config2 protocol available */ efi_status_t efi_ipconfig_register(const efi_handle_t handle, struct efi_ip4_config2_protocol *ip4config); @@ -733,6 +744,10 @@ efi_status_t efi_search_protocol(const efi_handle_t handle, efi_status_t efi_add_protocol(const efi_handle_t handle, const efi_guid_t *protocol, void *protocol_interface); +/* Uninstall new protocol on a handle */ +efi_status_t efi_uninstall_protocol + (efi_handle_t handle, const efi_guid_t *protocol, + void *protocol_interface, bool preserve); /* Reinstall a protocol on a handle */ efi_status_t EFIAPI efi_reinstall_protocol_interface( efi_handle_t handle, @@ -748,6 +763,15 @@ efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(efi_handle_t *handle, ...); efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(efi_handle_t handle, ...); +/* Connect and disconnect controller */ +efi_status_t EFIAPI efi_connect_controller(efi_handle_t controller_handle, + efi_handle_t *driver_image_handle, + struct efi_device_path *remain_device_path, + bool recursive); +efi_status_t EFIAPI efi_disconnect_controller( + efi_handle_t controller_handle, + efi_handle_t driver_image_handle, + efi_handle_t child_handle); /* Get handles that support a given protocol */ efi_status_t EFIAPI efi_locate_handle_buffer( enum efi_locate_search_type search_type, @@ -768,6 +792,8 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, void *context), void *notify_context, const efi_guid_t *group, struct efi_event **event); +/* Call this to close an event */ +efi_status_t EFIAPI efi_close_event(struct efi_event *event); /* Call this to set a timer */ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type, uint64_t trigger_time); @@ -907,8 +933,8 @@ struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part); struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp, const char *path); -struct efi_device_path *efi_dp_from_eth(void); -struct efi_device_path *efi_dp_from_http(const char *server); +struct efi_device_path *efi_dp_from_eth(struct udevice *dev); +struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev); struct efi_device_path *efi_dp_from_mem(uint32_t mem_type, uint64_t start_address, size_t size); diff --git a/include/fat.h b/include/fat.h index 3dce99a23cf..ca97880de12 100644 --- a/include/fat.h +++ b/include/fat.h @@ -206,6 +206,7 @@ int fat_opendir(const char *filename, struct fs_dir_stream **dirsp); int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp); void fat_closedir(struct fs_dir_stream *dirs); int fat_unlink(const char *filename); +int fat_rename(const char *old_path, const char *new_path); int fat_mkdir(const char *dirname); void fat_close(void); void *fat_next_cluster(fat_itr *itr, unsigned int *nbytes); diff --git a/include/fs.h b/include/fs.h index 2474880385d..54449faf2e5 100644 --- a/include/fs.h +++ b/include/fs.h @@ -86,7 +86,7 @@ int fs_set_blk_dev_with_part(struct blk_desc *desc, int part); * * Many file functions implicitly call fs_close(), e.g. fs_closedir(), * fs_exist(), fs_ln(), fs_ls(), fs_mkdir(), fs_read(), fs_size(), fs_write(), - * fs_unlink(). + * fs_unlink(), fs_rename(). */ void fs_close(void); @@ -270,6 +270,18 @@ int fs_unlink(const char *filename); */ int fs_mkdir(const char *filename); +/** + * fs_rename - rename/move a file or directory + * + * @old_path: existing path of the file/directory to rename + * @new_path: new path of the file/directory. If this points to an existing + * file or empty directory, the existing file/directory will be unlinked. + * If this points to a non-empty directory, the rename will fail. + * + * Return: 0 on success, -1 on error conditions + */ +int fs_rename(const char *old_path, const char *new_path); + /* * Common implementation for various filesystem commands, optionally limited * to a specific filesystem type via the fstype parameter. @@ -290,6 +302,8 @@ int do_mkdir(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], int fstype); int do_ln(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], int fstype); +int do_mv(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype); /* * Determine the UUID of the specified filesystem and print it. Optionally it is diff --git a/include/image.h b/include/image.h index 07912606f33..c1db8383459 100644 --- a/include/image.h +++ b/include/image.h @@ -1688,6 +1688,24 @@ struct sig_header_s { */ int image_pre_load(ulong addr); +#if defined(USE_HOSTCC) +/** + * rsa_verify_openssl() - Verify a signature against some data with openssl API + * + * Verify a RSA PKCS1.5/PSS signature against an expected hash. + * + * @info: Specifies the key and algorithms + * @region: Pointer to the input data + * @region_count: Number of region + * @sig: Signature + * @sig_len: Number of bytes in the signature + * Return: 0 if verified, -ve on error + */ +int rsa_verify_openssl(struct image_sign_info *info, + const struct image_region region[], int region_count, + uint8_t *sig, uint sig_len); +#endif + /** * fit_image_verify_required_sigs() - Verify signatures marked as 'required' * diff --git a/include/interrupt.h b/include/interrupt.h index 46ef2e196d4..6ea28b54a56 100644 --- a/include/interrupt.h +++ b/include/interrupt.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#include <asm/setjmp.h> +#include <setjmp.h> /** * struct resume_data - data for resume after interrupt diff --git a/include/mcheck.h b/include/mcheck.h index bd506ae6291..4b11751ebcc 100644 --- a/include/mcheck.h +++ b/include/mcheck.h @@ -1,18 +1,7 @@ -/* SPDX-License-Identifier: GPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 1996-2024 Free Software Foundation, Inc. * This file is part of the GNU C Library. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * <https://www.gnu.org/licenses/>. */ #ifndef _MCHECK_H #define _MCHECK_H 1 diff --git a/include/miiphy.h b/include/miiphy.h index b879fd16ae3..00d0b9b6a43 100644 --- a/include/miiphy.h +++ b/include/miiphy.h @@ -33,8 +33,6 @@ int miiphy_is_1000base_x(const char *devname, unsigned char addr); int miiphy_link(const char *devname, unsigned char addr); #endif -void miiphy_init(void); - int miiphy_set_current_dev(const char *devname); const char *miiphy_get_current_dev(void); struct mii_dev *mdio_get_current_dev(void); @@ -44,7 +42,6 @@ struct phy_device *mdio_phydev_for_ethname(const char *devname); void miiphy_listdev(void); -void mdio_init(struct mii_dev *bus); struct mii_dev *mdio_alloc(void); void mdio_free(struct mii_dev *bus); int mdio_register(struct mii_dev *bus); @@ -64,23 +61,19 @@ void mdio_list_devices(void); #define BB_MII_DEVNAME "bb_miiphy" -struct bb_miiphy_bus { - int (*mdio_active)(struct bb_miiphy_bus *bus); - int (*mdio_tristate)(struct bb_miiphy_bus *bus); - int (*set_mdio)(struct bb_miiphy_bus *bus, int v); - int (*get_mdio)(struct bb_miiphy_bus *bus, int *v); - int (*set_mdc)(struct bb_miiphy_bus *bus, int v); - int (*delay)(struct bb_miiphy_bus *bus); - void *priv; - struct mii_dev mii; +struct bb_miiphy_bus_ops { + int (*mdio_active)(struct mii_dev *miidev); + int (*mdio_tristate)(struct mii_dev *miidev); + int (*set_mdio)(struct mii_dev *miidev, int v); + int (*get_mdio)(struct mii_dev *miidev, int *v); + int (*set_mdc)(struct mii_dev *miidev, int v); + int (*delay)(struct mii_dev *miidev); }; -struct bb_miiphy_bus *bb_miiphy_alloc(void); -void bb_miiphy_free(struct bb_miiphy_bus *bus); - -int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg); -int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg, - u16 value); +int bb_miiphy_read(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops, + int addr, int devad, int reg); +int bb_miiphy_write(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops, + int addr, int devad, int reg, u16 value); #endif /* phy seed setup */ diff --git a/include/net-common.h b/include/net-common.h index 29d31f37263..1d507b13b06 100644 --- a/include/net-common.h +++ b/include/net-common.h @@ -291,6 +291,7 @@ struct eth_ops { #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops) struct udevice *eth_get_dev(void); /* get the current device */ +void eth_set_dev(struct udevice *dev); /* set a device */ unsigned char *eth_get_ethaddr(void); /* get the current device MAC */ int eth_rx(void); /* Check for received packets */ void eth_halt(void); /* stop SCC */ diff --git a/include/serial.h b/include/serial.h index e5f6d984d28..0a707ca730d 100644 --- a/include/serial.h +++ b/include/serial.h @@ -48,26 +48,6 @@ extern int serial_assign(const char *name); extern void serial_reinit_all(void); int serial_initialize(void); -/* For usbtty */ -#ifdef CONFIG_USB_TTY - -struct stdio_dev; - -int usbtty_getc(struct stdio_dev *dev); -void usbtty_putc(struct stdio_dev *dev, const char c); -void usbtty_puts(struct stdio_dev *dev, const char *str); -int usbtty_tstc(struct stdio_dev *dev); - -#else - -/* stubs */ -#define usbtty_getc(dev) 0 -#define usbtty_putc(dev, a) -#define usbtty_puts(dev, a) -#define usbtty_tstc(dev) 0 - -#endif /* CONFIG_USB_TTY */ - struct udevice; enum serial_par { diff --git a/include/setjmp.h b/include/setjmp.h new file mode 100644 index 00000000000..37d3a8af85d --- /dev/null +++ b/include/setjmp.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ 1 + +#ifdef CONFIG_HAVE_SETJMP +#include <asm/setjmp.h> +#else +struct jmp_buf_data { +}; +#endif + +/** + * typedef jmp_buf - information needed to restore a calling environment + */ +typedef struct jmp_buf_data jmp_buf[1]; + +/** + * setjmp() - prepare for a long jump + * + * Registers, the stack pointer, and the return address are saved in the + * jump bufffer. The function returns zero afterwards. When longjmp() is + * executed the function returns a second time with a non-zero value. + * + * @env: jump buffer used to store register values + * Return: 0 after setting up jump buffer, non-zero after longjmp() + */ +int setjmp(jmp_buf env); + +/** + * longjmp() - long jump + * + * Jump back to the address and the register state saved by setjmp(). + * + * @env: jump buffer + * @val: value to be returned by setjmp(), 0 is replaced by 1 + */ +void longjmp(jmp_buf env, int val); + +#endif /* _SETJMP_H_ */ diff --git a/include/stdio_dev.h b/include/stdio_dev.h index 4e3c4708f80..f7f9c10199e 100644 --- a/include/stdio_dev.h +++ b/include/stdio_dev.h @@ -101,7 +101,6 @@ struct stdio_dev *stdio_clone(struct stdio_dev *dev); int drv_lcd_init(void); int drv_video_init(void); int drv_keyboard_init(void); -int drv_usbtty_init(void); int drv_usbacm_init(void); int drv_nc_init(void); int drv_jtag_console_init(void); diff --git a/include/sysinfo.h b/include/sysinfo.h index ba2ac273e8e..e87cf969fcd 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -57,6 +57,7 @@ enum sysinfo_id { SYSID_SM_SYSTEM_WAKEUP, SYSID_SM_SYSTEM_SKU, SYSID_SM_SYSTEM_FAMILY, + SYSID_SM_SYSTEM_UUID, /* Baseboard (or Module) Information (Type 2) */ SYSID_SM_BASEBOARD_MANUFACTURER, @@ -151,6 +152,8 @@ enum sysinfo_id { /* For show_board_info() */ SYSID_BOARD_MODEL, SYSID_BOARD_MANUFACTURER, + SYSID_BOARD_MAC_ADDR, + SYSID_BOARD_RAM_SIZE_MB, SYSID_PRIOR_STAGE_VERSION, SYSID_PRIOR_STAGE_DATE, @@ -221,6 +224,30 @@ struct sysinfo_ops { int (*get_data)(struct udevice *dev, int id, void **data, size_t *size); /** + * get_item_count() - Get the item count of the specific data area that + * describes the hardware setup. + * @dev: The sysinfo instance to gather the data. + * @id: A unique identifier for the data area to be get. + * + * Return: non-negative item count if OK, -ve on error. + */ + int (*get_item_count)(struct udevice *dev, int id); + + /** + * get_data_by_index() - Get a data value by index from the platform. + * + * @dev: The sysinfo instance to gather the data. + * @id: A unique identifier for the data area to be get. + * @index: The item index, starting from 0. + * @data: Pointer to the address of the data area. + * @size: Pointer to the size of the data area. + * + * Return: 0 if OK, -ve on error. + */ + int (*get_data_by_index)(struct udevice *dev, int id, int index, + void **data, size_t *size); + + /** * get_fit_loadable - Get the name of an image to load from FIT * This function can be used to provide the image names based on runtime * detection. A classic use-case would when DTBOs are used to describe @@ -304,6 +331,32 @@ int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val); int sysinfo_get_data(struct udevice *dev, int id, void **data, size_t *size); /** + * sysinfo_get_item_count() - Get the item count of the specific data area that + * describes the hardware setup. + * @dev: The sysinfo instance to gather the data. + * @id: A unique identifier for the data area to be get. + * + * Return: non-negative item count if OK, -EPERM if called before + * sysinfo_detect(), else -ve on error. + */ +int sysinfo_get_item_count(struct udevice *dev, int id); + +/** + * sysinfo_get_data_by_index() - Get a data value by index from the platform. + * + * @dev: The sysinfo instance to gather the data. + * @id: A unique identifier for the data area to be get. + * @index: The item index, starting from 0. + * @data: Pointer to the address of the data area. + * @size: Pointer to the size of the data area. + * + * Return: 0 if OK, -EPERM if called before sysinfo_detect(), else -ve on + * error. + */ +int sysinfo_get_data_by_index(struct udevice *dev, int id, int index, + void **data, size_t *size); + +/** * sysinfo_get() - Return the sysinfo device for the sysinfo in question. * @devp: Pointer to structure to receive the sysinfo device. * @@ -364,6 +417,18 @@ static inline int sysinfo_get_data(struct udevice *dev, int id, void **data, return -ENOSYS; } +static inline int sysinfo_get_item_count(struct udevice *dev, int id) +{ + return -ENOSYS; +} + +static inline int sysinfo_get_data_by_index(struct udevice *dev, int id, + int index, void **data, + size_t *size) +{ + return -ENOSYS; +} + static inline int sysinfo_get(struct udevice **devp) { return -ENOSYS; diff --git a/include/u-boot/sha1.h b/include/u-boot/sha1.h index dd66258bbe9..c2d62e9cf0f 100644 --- a/include/u-boot/sha1.h +++ b/include/u-boot/sha1.h @@ -18,17 +18,7 @@ #include <linux/types.h> #if CONFIG_IS_ENABLED(MBEDTLS_LIB_CRYPTO) -/* - * FIXME: - * MbedTLS define the members of "mbedtls_sha256_context" as private, - * but "state" needs to be access by arch/arm/cpu/armv8/sha1_ce_glue. - * MBEDTLS_ALLOW_PRIVATE_ACCESS needs to be enabled to allow the external - * access. - * Directly including <external/mbedtls/library/common.h> is not allowed, - * since this will include <malloc.h> and break the sandbox test. - */ -#define MBEDTLS_ALLOW_PRIVATE_ACCESS - +#include "mbedtls_options.h" #include <mbedtls/sha1.h> #endif diff --git a/include/u-boot/sha256.h b/include/u-boot/sha256.h index d7a3403270b..2d86508332e 100644 --- a/include/u-boot/sha256.h +++ b/include/u-boot/sha256.h @@ -7,17 +7,7 @@ #include <linux/types.h> #if CONFIG_IS_ENABLED(MBEDTLS_LIB_CRYPTO) -/* - * FIXME: - * MbedTLS define the members of "mbedtls_sha256_context" as private, - * but "state" needs to be access by arch/arm/cpu/armv8/sha256_ce_glue. - * MBEDTLS_ALLOW_PRIVATE_ACCESS needs to be enabled to allow the external - * access. - * Directly including <external/mbedtls/library/common.h> is not allowed, - * since this will include <malloc.h> and break the sandbox test. - */ -#define MBEDTLS_ALLOW_PRIVATE_ACCESS - +#include "mbedtls_options.h" #include <mbedtls/sha256.h> #endif diff --git a/include/video_bridge.h b/include/video_bridge.h index 3b429eac578..00e9804565c 100644 --- a/include/video_bridge.h +++ b/include/video_bridge.h @@ -54,6 +54,19 @@ struct video_bridge_ops { int (*set_backlight)(struct udevice *dev, int percent); /** + * get_display_timing() - Get display timings from bridge. + * + * @dev: Bridge device containing the linked display timings + * @tim: Place to put timings + * @return 0 if OK, -ve on error + * + * This call it totally optional and useful mainly for integrated + * bridges with fixed output device. + */ + int (*get_display_timing)(struct udevice *dev, + struct display_timing *timing); + + /** * read_edid() - Read information from EDID * * @dev: Device to read from @@ -67,6 +80,7 @@ struct video_bridge_ops { #define video_bridge_get_ops(dev) \ ((struct video_bridge_ops *)(dev)->driver->ops) +#if CONFIG_IS_ENABLED(VIDEO_BRIDGE) /** * video_bridge_attach() - attach a video bridge * @@ -99,6 +113,14 @@ int video_bridge_set_active(struct udevice *dev, bool active); int video_bridge_check_attached(struct udevice *dev); /** + * video_bridge_get_display_timing() - Get display timings from bridge. + * + * @dev: Bridge device containing the linked display timings + * Return: 0 if OK, -ve on error + */ +int video_bridge_get_display_timing(struct udevice *dev, + struct display_timing *timing); +/** * video_bridge_read_edid() - Read information from EDID * * @dev: Device to read from @@ -107,5 +129,37 @@ int video_bridge_check_attached(struct udevice *dev); * Return: number of bytes read, <=0 for error */ int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size); +#else +static inline int video_bridge_attach(struct udevice *dev) +{ + return -ENOSYS; +} + +static inline int video_bridge_set_backlight(struct udevice *dev, int percent) +{ + return -ENOSYS; +} + +static inline int video_bridge_set_active(struct udevice *dev, bool active) +{ + return -ENOSYS; +} + +static inline int video_bridge_check_attached(struct udevice *dev) +{ + return -ENOSYS; +} + +static inline int video_bridge_get_display_timing(struct udevice *dev, + struct display_timing *timing) +{ + return -ENOSYS; +} + +static inline int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size) +{ + return -ENOSYS; +} +#endif /* CONFIG_VIDEO_BRIDGE */ #endif diff --git a/lib/Kconfig b/lib/Kconfig index 1a683dea670..a21b3378fa7 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1008,14 +1008,14 @@ config OF_LIBFDT_OVERLAY This enables the FDT library (libfdt) overlay support. config SYS_FDT_PAD - hex "Maximum size of the FDT memory area passeed to the OS" + hex "Free space added to device-tree before booting" depends on OF_LIBFDT default 0x13000 if FMAN_ENET || QE || U_QE default 0x3000 help - During OS boot, we allocate a region of memory within the bootmap - for the FDT. This is the size that we will expand the FDT that we - are using will be extended to be, in bytes. + The operating system may need a free area at the end of the device- + tree for fix-ups. This setting defines by how many bytes U-Boot + extends the device-tree before booting. config SPL_OF_LIBFDT bool "Enable the FDT library for SPL" diff --git a/lib/Makefile b/lib/Makefile index a7bc2f3134a..a30ce1595d5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -28,11 +28,7 @@ obj-y += charset.o endif endif -ifdef CONFIG_USB_TTY -obj-y += circbuf.o -else obj-$(CONFIG_CIRCBUF) += circbuf.o -endif obj-y += crc8.o obj-$(CONFIG_ERRNO_STR) += errno_str.o diff --git a/lib/ecdsa/ecdsa-libcrypto.c b/lib/ecdsa/ecdsa-libcrypto.c index 1c5dde60691..f0095e9dbcf 100644 --- a/lib/ecdsa/ecdsa-libcrypto.c +++ b/lib/ecdsa/ecdsa-libcrypto.c @@ -363,8 +363,10 @@ int ecdsa_add_verify_data(struct image_sign_info *info, void *fdt) ret = prepare_ctx(&ctx, info); if (ret >= 0) { ret = do_add(&ctx, fdt, fdt_key_name, info); - if (ret < 0) - ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; + if (ret < 0) { + free_ctx(&ctx); + return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; + } } free_ctx(&ctx); diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index d4f6b56afaa..6130af14337 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -27,6 +27,7 @@ config EFI_LOADER select REGEX imply FAT imply FAT_WRITE + imply FAT_RENAME imply USB_KEYBOARD_FN_KEYS imply VIDEO_ANSI help diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index 10ec5e9ada3..deafb2ce1c2 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -16,6 +16,7 @@ #include <log.h> #include <malloc.h> #include <mapmem.h> +#include <net.h> static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path; @@ -67,7 +68,7 @@ static efi_status_t calculate_paths(const char *dev, const char *devnr, #if IS_ENABLED(CONFIG_NETDEVICES) if (!strcmp(dev, "Net") || !strcmp(dev, "Http")) { - ret = efi_net_set_dp(dev, devnr); + ret = efi_net_new_dp(dev, devnr, eth_get_dev()); if (ret != EFI_SUCCESS) return ret; } diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 5164cb15986..c8d9a6037f7 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -21,7 +21,6 @@ #include <usb.h> #include <watchdog.h> #include <asm/global_data.h> -#include <asm/setjmp.h> #include <linux/libfdt_env.h> DECLARE_GLOBAL_DATA_PTR; @@ -60,9 +59,9 @@ static efi_handle_t current_image; static volatile gd_t *efi_gd, *app_gd; #endif -static efi_status_t efi_uninstall_protocol - (efi_handle_t handle, const efi_guid_t *protocol, - void *protocol_interface, bool preserve); +efi_status_t efi_uninstall_protocol + (efi_handle_t handle, const efi_guid_t *protocol, + void *protocol_interface, bool preserve); /* 1 if inside U-Boot code, 0 if inside EFI payload code */ static int entry_count = 1; @@ -100,12 +99,11 @@ const efi_guid_t efi_guid_load_file2_protocol = EFI_LOAD_FILE2_PROTOCOL_GUID; /* GUID of the SMBIOS table */ const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID; -static efi_status_t EFIAPI efi_disconnect_controller( +efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t controller_handle, efi_handle_t driver_image_handle, efi_handle_t child_handle); -static efi_status_t EFIAPI efi_connect_controller(efi_handle_t controller_handle, efi_handle_t *driver_image_handle, struct efi_device_path *remain_device_path, @@ -1039,7 +1037,7 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event) * * Return: status code */ -static efi_status_t EFIAPI efi_close_event(struct efi_event *event) +efi_status_t EFIAPI efi_close_event(struct efi_event *event) { struct efi_register_notify_event *item, *next; @@ -1380,9 +1378,9 @@ static efi_status_t efi_disconnect_all_drivers * * Return: status code */ -static efi_status_t efi_uninstall_protocol - (efi_handle_t handle, const efi_guid_t *protocol, - void *protocol_interface, bool preserve) +efi_status_t efi_uninstall_protocol + (efi_handle_t handle, const efi_guid_t *protocol, + void *protocol_interface, bool preserve) { struct efi_handler *handler; struct efi_open_protocol_info_item *item; @@ -2233,8 +2231,6 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, if (!efi_st_keep_devices) { bootm_disable_interrupts(); - if (IS_ENABLED(CONFIG_USB_DEVICE)) - udc_disconnect(); board_quiesce_devices(); dm_remove_devices_active(); } @@ -3199,7 +3195,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, void *info; efi_handle_t parent_image = current_image; efi_status_t exit_status; - struct jmp_buf_data exit_jmp; + jmp_buf exit_jmp; EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data); @@ -3238,7 +3234,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, } /* call the image! */ - if (setjmp(&exit_jmp)) { + if (setjmp(exit_jmp)) { /* * We called the entry point of the child image with EFI_CALL * in the lines below. The child image called the Exit() boot @@ -3444,7 +3440,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, struct efi_loaded_image *loaded_image_protocol; struct efi_loaded_image_obj *image_obj = (struct efi_loaded_image_obj *)image_handle; - struct jmp_buf_data *exit_jmp; + jmp_buf *exit_jmp; EFI_ENTRY("%p, %ld, %zu, %p", image_handle, exit_status, exit_data_size, exit_data); @@ -3511,7 +3507,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, */ efi_restore_gd(); - longjmp(exit_jmp, 1); + longjmp(*exit_jmp, 1); panic("EFI application exited"); out: @@ -3665,7 +3661,7 @@ static efi_status_t efi_connect_single_controller( * * Return: status code */ -static efi_status_t EFIAPI efi_connect_controller( +efi_status_t EFIAPI efi_connect_controller( efi_handle_t controller_handle, efi_handle_t *driver_image_handle, struct efi_device_path *remain_device_path, @@ -3844,7 +3840,7 @@ static efi_status_t efi_get_child_controllers( * * Return: status code */ -static efi_status_t EFIAPI efi_disconnect_controller( +efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t controller_handle, efi_handle_t driver_image_handle, efi_handle_t child_handle) diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index c0633a736b6..c9bf2726fe2 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -954,20 +954,20 @@ struct efi_device_path *efi_dp_from_uart(void) return buf; } -struct efi_device_path __maybe_unused *efi_dp_from_eth(void) +struct efi_device_path __maybe_unused *efi_dp_from_eth(struct udevice *dev) { void *buf, *start; unsigned dpsize = 0; - assert(eth_get_dev()); + assert(dev); - dpsize += dp_size(eth_get_dev()); + dpsize += dp_size(dev); start = buf = efi_alloc(dpsize + sizeof(END)); if (!buf) return NULL; - buf = dp_fill(buf, eth_get_dev()); + buf = dp_fill(buf, dev); *((struct efi_device_path *)buf) = END; @@ -984,11 +984,13 @@ struct efi_device_path __maybe_unused *efi_dp_from_eth(void) * @ip: IPv4 local address * @mask: network mask * @srv: IPv4 remote/server address + * @dev: net udevice * Return: pointer to device path, NULL on error */ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *srv) + struct efi_ipv4_address *srv, + struct udevice *dev) { struct efi_device_path *dp1, *dp2, *pos; struct { @@ -1010,7 +1012,7 @@ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip, pos = &dp.end; memcpy(pos, &END, sizeof(END)); - dp1 = efi_dp_from_eth(); + dp1 = efi_dp_from_eth(dev); if (!dp1) return NULL; @@ -1029,9 +1031,10 @@ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip, * and an END node. * * @server: URI of remote server + * @dev: net udevice * Return: pointer to HTTP device path, NULL on error */ -struct efi_device_path *efi_dp_from_http(const char *server) +struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev) { struct efi_device_path *dp1, *dp2; struct efi_device_path_uri *uridp; @@ -1045,12 +1048,13 @@ struct efi_device_path *efi_dp_from_http(const char *server) (!server && IS_ENABLED(CONFIG_NET_LWIP))) return NULL; - efi_net_get_addr(&ip, &mask, NULL); + efi_net_get_addr(&ip, &mask, NULL, dev); - dp1 = efi_dp_from_ipv4(&ip, &mask, NULL); + dp1 = efi_dp_from_ipv4(&ip, &mask, NULL, dev); if (!dp1) return NULL; + strcpy(tmp, "http://"); if (server) { @@ -1185,8 +1189,8 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, dp = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, (uintptr_t)image_addr, image_size); } else if (IS_ENABLED(CONFIG_NETDEVICES) && - (!strcmp(dev, "Net") || !strcmp(dev, "Http"))) { - efi_net_get_dp(&dp); + (!strcmp(dev, "Net") || !strcmp(dev, "Http"))) { + efi_net_dp_from_dev(&dp, eth_get_dev(), false); } else if (!strcmp(dev, "Uart")) { dp = efi_dp_from_uart(); } else { diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 201fa5f8f3c..7d81da8f2d8 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -40,7 +40,7 @@ struct file_handle { struct fs_dir_stream *dirs; struct fs_dirent *dent; - char path[0]; + char *path; }; #define to_fh(x) container_of(x, struct file_handle, base) @@ -178,6 +178,7 @@ static struct efi_file_handle *file_open(struct file_system *fs, u64 attributes) { struct file_handle *fh; + char *path; char f0[MAX_UTF8_PER_UTF16] = {0}; int plen = 0; int flen = 0; @@ -194,11 +195,13 @@ static struct efi_file_handle *file_open(struct file_system *fs, plen = strlen(parent->path) + 1; } + fh = calloc(1, sizeof(*fh)); /* +2 is for null and '/' */ - fh = calloc(1, sizeof(*fh) + plen + (flen * MAX_UTF8_PER_UTF16) + 2); - if (!fh) - return NULL; + path = calloc(1, plen + (flen * MAX_UTF8_PER_UTF16) + 2); + if (!fh || !path) + goto error; + fh->path = path; fh->open_mode = open_mode; fh->base = efi_file_handle_protocol; fh->fs = fs; @@ -245,6 +248,7 @@ static struct efi_file_handle *file_open(struct file_system *fs, return &fh->base; error: + free(fh->path); free(fh); return NULL; } @@ -368,6 +372,7 @@ out: static efi_status_t file_close(struct file_handle *fh) { fs_closedir(fh->dirs); + free(fh->path); free(fh); return EFI_SUCCESS; } @@ -949,6 +954,7 @@ static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file, { struct file_handle *fh = to_fh(file); efi_status_t ret = EFI_UNSUPPORTED; + char *new_file_name = NULL, *new_path = NULL; EFI_ENTRY("%p, %pUs, %zu, %p", file, info_type, buffer_size, buffer); @@ -978,13 +984,43 @@ static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file, pos = new_file_name; utf16_utf8_strcpy(&pos, info->file_name); if (strcmp(new_file_name, filename)) { - /* TODO: we do not support renaming */ - EFI_PRINT("Renaming not supported\n"); - free(new_file_name); - ret = EFI_ACCESS_DENIED; - goto out; + int dlen; + int rv; + + if (set_blk_dev(fh)) { + ret = EFI_DEVICE_ERROR; + goto out; + } + dlen = filename - fh->path; + new_path = calloc(1, dlen + strlen(new_file_name) + 1); + if (!new_path) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + memcpy(new_path, fh->path, dlen); + strcpy(new_path + dlen, new_file_name); + sanitize_path(new_path); + rv = fs_exists(new_path); + if (rv) { + ret = EFI_ACCESS_DENIED; + goto out; + } + /* fs_exists() calls fs_close(), so open file system again */ + if (set_blk_dev(fh)) { + ret = EFI_DEVICE_ERROR; + goto out; + } + rv = fs_rename(fh->path, new_path); + if (rv) { + ret = EFI_ACCESS_DENIED; + goto out; + } + free(fh->path); + fh->path = new_path; + /* Prevent new_path from being freed on out */ + new_path = NULL; + ret = EFI_SUCCESS; } - free(new_file_name); /* Check for truncation */ if (!fh->isdir) { ret = efi_get_file_size(fh, &file_size); @@ -1007,6 +1043,8 @@ static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file, ret = EFI_UNSUPPORTED; } out: + free(new_path); + free(new_file_name); return EFI_EXIT(ret); } diff --git a/lib/efi_loader/efi_http.c b/lib/efi_loader/efi_http.c index 88816256b03..189317fe2d2 100644 --- a/lib/efi_loader/efi_http.c +++ b/lib/efi_loader/efi_http.c @@ -36,6 +36,7 @@ static const efi_guid_t efi_http_guid = EFI_HTTP_PROTOCOL_GUID; struct efi_http_instance { struct efi_http_protocol http; efi_handle_t handle; + struct efi_service_binding_protocol *parent; bool configured; void *http_load_addr; ulong file_size; @@ -188,7 +189,7 @@ static efi_status_t EFIAPI efi_http_configure(struct efi_http_protocol *this, if (!ipv4_node->use_default_address) { efi_net_set_addr((struct efi_ipv4_address *)&ipv4_node->local_address, - (struct efi_ipv4_address *)&ipv4_node->local_subnet, NULL); + (struct efi_ipv4_address *)&ipv4_node->local_subnet, NULL, NULL); } http_instance->current_offset = 0; @@ -243,7 +244,7 @@ static efi_status_t EFIAPI efi_http_request(struct efi_http_protocol *this, ret = efi_net_do_request(url_8, current_method, &http_instance->http_load_addr, &http_instance->status_code, &http_instance->file_size, - http_instance->headers_buffer); + http_instance->headers_buffer, http_instance->parent); if (ret != EFI_SUCCESS) goto out; @@ -408,6 +409,7 @@ static efi_status_t EFIAPI efi_http_service_binding_create_child( goto failure_to_add_protocol; } + new_instance->parent = this; efi_add_handle(new_instance->handle); *child_handle = new_instance->handle; diff --git a/lib/efi_loader/efi_ipconfig.c b/lib/efi_loader/efi_ipconfig.c index f1c092daafd..9f51f77fa9a 100644 --- a/lib/efi_loader/efi_ipconfig.c +++ b/lib/efi_loader/efi_ipconfig.c @@ -60,7 +60,7 @@ static efi_status_t EFIAPI efi_ip4_config2_set_data(struct efi_ip4_config2_proto memcpy((void *)¤t_http_ip, data, sizeof(struct efi_ip4_config2_manual_address)); efi_net_set_addr(¤t_http_ip.address, - ¤t_http_ip.subnet_mask, NULL); + ¤t_http_ip.subnet_mask, NULL, NULL); return EFI_EXIT(EFI_SUCCESS); } return EFI_EXIT(EFI_BAD_BUFFER_SIZE); @@ -133,7 +133,7 @@ static efi_status_t EFIAPI efi_ip4_config2_get_data(struct efi_ip4_config2_proto return EFI_EXIT(EFI_BUFFER_TOO_SMALL); } - efi_net_get_addr(¤t_http_ip.address, ¤t_http_ip.subnet_mask, NULL); + efi_net_get_addr(¤t_http_ip.address, ¤t_http_ip.subnet_mask, NULL, NULL); memcpy(data, (void *)¤t_http_ip, sizeof(struct efi_ip4_config2_manual_address)); diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index ce9272fa240..b3291b4f1d5 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -24,54 +24,70 @@ #include <vsprintf.h> #include <net.h> -static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; +#define MAX_EFI_NET_OBJS 10 +#define MAX_NUM_DHCP_ENTRIES 10 +#define MAX_NUM_DP_ENTRIES 10 + +const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; static const efi_guid_t efi_pxe_base_code_protocol_guid = EFI_PXE_BASE_CODE_PROTOCOL_GUID; -static struct efi_pxe_packet *dhcp_ack; -static void *new_tx_packet; -static void *transmit_buffer; -static uchar **receive_buffer; -static size_t *receive_lengths; -static int rx_packet_idx; -static int rx_packet_num; -static struct efi_net_obj *netobj; + +struct dp_entry { + struct efi_device_path *net_dp; + struct udevice *dev; + bool is_valid; +}; /* - * The current network device path. This device path is updated when a new - * bootfile is downloaded from the network. If then the bootfile is loaded - * as an efi image, net_dp is passed as the device path of the loaded image. + * The network device path cache. An entry is added when a new bootfile + * is downloaded from the network. If the bootfile is then loaded as an + * efi image, the most recent entry corresponding to the device is passed + * as the device path of the loaded image. */ -static struct efi_device_path *net_dp; +static struct dp_entry dp_cache[MAX_NUM_DP_ENTRIES]; +static int next_dp_entry; +#if IS_ENABLED(CONFIG_EFI_HTTP_PROTOCOL) static struct wget_http_info efi_wget_info = { .set_bootdev = false, .check_buffer_size = true, }; +#endif -/* - * The notification function of this event is called in every timer cycle - * to check if a new network packet has been received. - */ -static struct efi_event *network_timer_event; -/* - * This event is signaled when a packet has been received. - */ -static struct efi_event *wait_for_packet; +struct dhcp_entry { + struct efi_pxe_packet *dhcp_ack; + struct udevice *dev; + bool is_valid; +}; + +static struct dhcp_entry dhcp_cache[MAX_NUM_DHCP_ENTRIES]; +static int next_dhcp_entry; /** * struct efi_net_obj - EFI object representing a network interface * * @header: EFI object header + * @dev: net udevice * @net: simple network protocol interface * @net_mode: status of the network interface * @pxe: PXE base code protocol interface * @pxe_mode: status of the PXE base code protocol * @ip4_config2: IP4 Config2 protocol interface * @http_service_binding: Http service binding protocol interface + * @new_tx_packet: new transmit packet + * @transmit_buffer: transmit buffer + * @receive_buffer: array of receive buffers + * @receive_lengths: array of lengths for received packets + * @rx_packet_idx: index of the current receive packet + * @rx_packet_num: number of received packets + * @wait_for_packet: signaled when a packet has been received + * @network_timer_event: event to check for new network packets. + * @efi_seq_num: sequence number of the EFI net object. */ struct efi_net_obj { struct efi_object header; + struct udevice *dev; struct efi_simple_network net; struct efi_simple_network_mode net_mode; struct efi_pxe_base_code_protocol pxe; @@ -82,8 +98,54 @@ struct efi_net_obj { #if IS_ENABLED(CONFIG_EFI_HTTP_PROTOCOL) struct efi_service_binding_protocol http_service_binding; #endif + void *new_tx_packet; + void *transmit_buffer; + uchar **receive_buffer; + size_t *receive_lengths; + int rx_packet_idx; + int rx_packet_num; + struct efi_event *wait_for_packet; + struct efi_event *network_timer_event; + int efi_seq_num; }; +static int curr_efi_net_obj; +static struct efi_net_obj *net_objs[MAX_EFI_NET_OBJS]; + +/** + * efi_netobj_is_active() - checks if a netobj is active in the efi subsystem + * + * @netobj: pointer to efi_net_obj + * Return: true if active + */ +static bool efi_netobj_is_active(struct efi_net_obj *netobj) +{ + if (!netobj || !efi_search_obj(&netobj->header)) + return false; + + return true; +} + +/* + * efi_netobj_from_snp() - get efi_net_obj from simple network protocol + * + * + * @snp: pointer to the simple network protocol + * Return: pointer to efi_net_obj, NULL on error + */ +static struct efi_net_obj *efi_netobj_from_snp(struct efi_simple_network *snp) +{ + int i; + + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && &net_objs[i]->net == snp) { + // Do not register duplicate devices + return net_objs[i]; + } + } + return NULL; +} + /* * efi_net_start() - start the network interface * @@ -97,20 +159,22 @@ struct efi_net_obj { static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this) { efi_status_t ret = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p", this); - /* Check parameters */ if (!this) { ret = EFI_INVALID_PARAMETER; goto out; } + nt = efi_netobj_from_snp(this); + if (this->mode->state != EFI_NETWORK_STOPPED) { ret = EFI_ALREADY_STARTED; } else { this->int_status = 0; - wait_for_packet->is_signaled = false; + nt->wait_for_packet->is_signaled = false; this->mode->state = EFI_NETWORK_STARTED; } out: @@ -130,6 +194,7 @@ out: static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this) { efi_status_t ret = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p", this); @@ -139,13 +204,17 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this) goto out; } + nt = efi_netobj_from_snp(this); + if (this->mode->state == EFI_NETWORK_STOPPED) { ret = EFI_NOT_STARTED; } else { /* Disable hardware and put it into the reset state */ + eth_set_dev(nt->dev); + env_set("ethact", eth_get_name()); eth_halt(); /* Clear cache of packets */ - rx_packet_num = 0; + nt->rx_packet_num = 0; this->mode->state = EFI_NETWORK_STOPPED; } out: @@ -169,6 +238,7 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, { int ret; efi_status_t r = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p, %lx, %lx", this, extra_rx, extra_tx); @@ -177,6 +247,7 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, r = EFI_INVALID_PARAMETER; goto out; } + nt = efi_netobj_from_snp(this); switch (this->mode->state) { case EFI_NETWORK_INITIALIZED: @@ -189,14 +260,13 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, /* Setup packet buffers */ net_init(); - /* Disable hardware and put it into the reset state */ - eth_halt(); /* Clear cache of packets */ - rx_packet_num = 0; - /* Set current device according to environment variables */ - eth_set_current(); + nt->rx_packet_num = 0; + /* Set the net device corresponding to the efi net object */ + eth_set_dev(nt->dev); + env_set("ethact", eth_get_name()); /* Get hardware ready for send and receive operations */ - ret = eth_init(); + ret = eth_start_udev(nt->dev); if (ret < 0) { eth_halt(); this->mode->state = EFI_NETWORK_STOPPED; @@ -204,7 +274,7 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, goto out; } else { this->int_status = 0; - wait_for_packet->is_signaled = false; + nt->wait_for_packet->is_signaled = false; this->mode->state = EFI_NETWORK_INITIALIZED; } out: @@ -265,6 +335,7 @@ out: static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this) { efi_status_t ret = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p", this); @@ -273,6 +344,7 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this) ret = EFI_INVALID_PARAMETER; goto out; } + nt = efi_netobj_from_snp(this); switch (this->mode->state) { case EFI_NETWORK_INITIALIZED: @@ -285,9 +357,12 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this) goto out; } + eth_set_dev(nt->dev); + env_set("ethact", eth_get_name()); eth_halt(); + this->int_status = 0; - wait_for_packet->is_signaled = false; + nt->wait_for_packet->is_signaled = false; this->mode->state = EFI_NETWORK_STARTED; out: @@ -463,6 +538,7 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this, u32 *int_status, void **txbuf) { efi_status_t ret = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p, %p, %p", this, int_status, txbuf); @@ -474,6 +550,8 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this, goto out; } + nt = efi_netobj_from_snp(this); + switch (this->mode->state) { case EFI_NETWORK_STOPPED: ret = EFI_NOT_STARTED; @@ -490,9 +568,9 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this, this->int_status = 0; } if (txbuf) - *txbuf = new_tx_packet; + *txbuf = nt->new_tx_packet; - new_tx_packet = NULL; + nt->new_tx_packet = NULL; out: return EFI_EXIT(ret); } @@ -519,6 +597,7 @@ static efi_status_t EFIAPI efi_net_transmit struct efi_mac_address *dest_addr, u16 *protocol) { efi_status_t ret = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p, %lu, %lu, %p, %p, %p, %p", this, (unsigned long)header_size, (unsigned long)buffer_size, @@ -532,6 +611,8 @@ static efi_status_t EFIAPI efi_net_transmit goto out; } + nt = efi_netobj_from_snp(this); + /* We do not support jumbo packets */ if (buffer_size > PKTSIZE_ALIGN) { ret = EFI_INVALID_PARAMETER; @@ -576,11 +657,14 @@ static efi_status_t EFIAPI efi_net_transmit break; } + eth_set_dev(nt->dev); + env_set("ethact", eth_get_name()); + /* Ethernet packets always fit, just bounce */ - memcpy(transmit_buffer, buffer, buffer_size); - net_send_packet(transmit_buffer, buffer_size); + memcpy(nt->transmit_buffer, buffer, buffer_size); + net_send_packet(nt->transmit_buffer, buffer_size); - new_tx_packet = buffer; + nt->new_tx_packet = buffer; this->int_status |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; out: return EFI_EXIT(ret); @@ -611,6 +695,7 @@ static efi_status_t EFIAPI efi_net_receive struct ethernet_hdr *eth_hdr; size_t hdr_size = sizeof(struct ethernet_hdr); u16 protlen; + struct efi_net_obj *nt; EFI_ENTRY("%p, %p, %p, %p, %p, %p, %p", this, header_size, buffer_size, buffer, src_addr, dest_addr, protocol); @@ -624,6 +709,8 @@ static efi_status_t EFIAPI efi_net_receive goto out; } + nt = efi_netobj_from_snp(this); + switch (this->mode->state) { case EFI_NETWORK_STOPPED: ret = EFI_NOT_STARTED; @@ -635,16 +722,16 @@ static efi_status_t EFIAPI efi_net_receive break; } - if (!rx_packet_num) { + if (!nt->rx_packet_num) { ret = EFI_NOT_READY; goto out; } /* Fill export parameters */ - eth_hdr = (struct ethernet_hdr *)receive_buffer[rx_packet_idx]; + eth_hdr = (struct ethernet_hdr *)nt->receive_buffer[nt->rx_packet_idx]; protlen = ntohs(eth_hdr->et_protlen); if (protlen == 0x8100) { hdr_size += 4; - protlen = ntohs(*(u16 *)&receive_buffer[rx_packet_idx][hdr_size - 2]); + protlen = ntohs(*(u16 *)&nt->receive_buffer[nt->rx_packet_idx][hdr_size - 2]); } if (header_size) *header_size = hdr_size; @@ -654,20 +741,20 @@ static efi_status_t EFIAPI efi_net_receive memcpy(src_addr, eth_hdr->et_src, ARP_HLEN); if (protocol) *protocol = protlen; - if (*buffer_size < receive_lengths[rx_packet_idx]) { + if (*buffer_size < nt->receive_lengths[nt->rx_packet_idx]) { /* Packet doesn't fit, try again with bigger buffer */ - *buffer_size = receive_lengths[rx_packet_idx]; + *buffer_size = nt->receive_lengths[nt->rx_packet_idx]; ret = EFI_BUFFER_TOO_SMALL; goto out; } /* Copy packet */ - memcpy(buffer, receive_buffer[rx_packet_idx], - receive_lengths[rx_packet_idx]); - *buffer_size = receive_lengths[rx_packet_idx]; - rx_packet_idx = (rx_packet_idx + 1) % ETH_PACKETS_BATCH_RECV; - rx_packet_num--; - if (rx_packet_num) - wait_for_packet->is_signaled = true; + memcpy(buffer, nt->receive_buffer[nt->rx_packet_idx], + nt->receive_lengths[nt->rx_packet_idx]); + *buffer_size = nt->receive_lengths[nt->rx_packet_idx]; + nt->rx_packet_idx = (nt->rx_packet_idx + 1) % ETH_PACKETS_BATCH_RECV; + nt->rx_packet_num--; + if (nt->rx_packet_num) + nt->wait_for_packet->is_signaled = true; else this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; out: @@ -684,18 +771,35 @@ out: */ void efi_net_set_dhcp_ack(void *pkt, int len) { - int maxsize = sizeof(*dhcp_ack); + struct efi_pxe_packet **dhcp_ack; + struct udevice *dev; + int i; + + dhcp_ack = &dhcp_cache[next_dhcp_entry].dhcp_ack; + + /* For now this function gets called only by the current device */ + dev = eth_get_dev(); - if (!dhcp_ack) { - dhcp_ack = malloc(maxsize); - if (!dhcp_ack) + int maxsize = sizeof(**dhcp_ack); + + if (!*dhcp_ack) { + *dhcp_ack = malloc(maxsize); + if (!*dhcp_ack) return; } - memset(dhcp_ack, 0, maxsize); - memcpy(dhcp_ack, pkt, min(len, maxsize)); + memset(*dhcp_ack, 0, maxsize); + memcpy(*dhcp_ack, pkt, min(len, maxsize)); + + dhcp_cache[next_dhcp_entry].is_valid = true; + dhcp_cache[next_dhcp_entry].dev = dev; + next_dhcp_entry++; + next_dhcp_entry %= MAX_NUM_DHCP_ENTRIES; - if (netobj) - netobj->pxe_mode.dhcp_ack = *dhcp_ack; + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && net_objs[i]->dev == dev) { + net_objs[i]->pxe_mode.dhcp_ack = **dhcp_ack; + } + } } /** @@ -709,6 +813,11 @@ void efi_net_set_dhcp_ack(void *pkt, int len) static void efi_net_push(void *pkt, int len) { int rx_packet_next; + struct efi_net_obj *nt; + + nt = net_objs[curr_efi_net_obj]; + if (!nt) + return; /* Check that we at least received an Ethernet header */ if (len < sizeof(struct ethernet_hdr)) @@ -719,15 +828,15 @@ static void efi_net_push(void *pkt, int len) return; /* Can't store more than pre-alloced buffer */ - if (rx_packet_num >= ETH_PACKETS_BATCH_RECV) + if (nt->rx_packet_num >= ETH_PACKETS_BATCH_RECV) return; - rx_packet_next = (rx_packet_idx + rx_packet_num) % + rx_packet_next = (nt->rx_packet_idx + nt->rx_packet_num) % ETH_PACKETS_BATCH_RECV; - memcpy(receive_buffer[rx_packet_next], pkt, len); - receive_lengths[rx_packet_next] = len; + memcpy(nt->receive_buffer[rx_packet_next], pkt, len); + nt->receive_lengths[rx_packet_next] = len; - rx_packet_num++; + nt->rx_packet_num++; } /** @@ -742,6 +851,7 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event, void *context) { struct efi_simple_network *this = (struct efi_simple_network *)context; + struct efi_net_obj *nt; EFI_ENTRY("%p, %p", event, context); @@ -752,14 +862,19 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event, if (!this || this->mode->state != EFI_NETWORK_INITIALIZED) goto out; - if (!rx_packet_num) { + nt = efi_netobj_from_snp(this); + curr_efi_net_obj = nt->efi_seq_num; + + if (!nt->rx_packet_num) { + eth_set_dev(nt->dev); + env_set("ethact", eth_get_name()); push_packet = efi_net_push; eth_rx(); push_packet = NULL; - if (rx_packet_num) { + if (nt->rx_packet_num) { this->int_status |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; - wait_for_packet->is_signaled = true; + nt->wait_for_packet->is_signaled = true; } } out: @@ -879,30 +994,179 @@ static efi_status_t EFIAPI efi_pxe_base_code_set_packets( } /** + * efi_netobj_set_dp() - set device path of a netobj + * + * @netobj: pointer to efi_net_obj + * @dp: device path to set, allocated by caller + * Return: status code + */ +efi_status_t efi_netobj_set_dp(struct efi_net_obj *netobj, struct efi_device_path *dp) +{ + efi_status_t ret; + struct efi_handler *phandler; + struct efi_device_path *new_net_dp; + + if (!efi_netobj_is_active(netobj)) + return EFI_SUCCESS; + + // Create a device path for the netobj + new_net_dp = dp; + if (!new_net_dp) + return EFI_OUT_OF_RESOURCES; + + phandler = NULL; + efi_search_protocol(&netobj->header, &efi_guid_device_path, &phandler); + + // If the device path protocol is not yet installed, install it + if (!phandler) + goto add; + + // If it is already installed, try to update it + ret = efi_reinstall_protocol_interface(&netobj->header, &efi_guid_device_path, + phandler->protocol_interface, new_net_dp); + if (ret != EFI_SUCCESS) + return ret; + + return EFI_SUCCESS; +add: + ret = efi_add_protocol(&netobj->header, &efi_guid_device_path, + new_net_dp); + if (ret != EFI_SUCCESS) + return ret; + + return EFI_SUCCESS; +} + +/** + * efi_netobj_get_dp() - get device path of a netobj + * + * @netobj: pointer to efi_net_obj + * Return: device path, NULL on error + */ +static struct efi_device_path *efi_netobj_get_dp(struct efi_net_obj *netobj) +{ + struct efi_handler *phandler; + + if (!efi_netobj_is_active(netobj)) + return NULL; + + phandler = NULL; + efi_search_protocol(&netobj->header, &efi_guid_device_path, &phandler); + + if (phandler && phandler->protocol_interface) + return efi_dp_dup(phandler->protocol_interface); + + return NULL; +} + +/** + * efi_net_do_start() - start the efi network stack + * + * This gets called from do_bootefi_exec() each time a payload gets executed. + * + * @dev: net udevice + * Return: status code + */ +efi_status_t efi_net_do_start(struct udevice *dev) +{ + efi_status_t r = EFI_SUCCESS; + struct efi_net_obj *netobj; + struct efi_device_path *net_dp; + int i; + + netobj = NULL; + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && net_objs[i]->dev == dev) { + netobj = net_objs[i]; + break; + } + } + + if (!efi_netobj_is_active(netobj)) + return r; + + efi_net_dp_from_dev(&net_dp, netobj->dev, true); + // If no dp cache entry applies and there already + // is a device path installed, continue + if (!net_dp) { + if (efi_netobj_get_dp(netobj)) + goto set_addr; + else + net_dp = efi_dp_from_eth(netobj->dev); + + } + + if (!net_dp) + return EFI_OUT_OF_RESOURCES; + + r = efi_netobj_set_dp(netobj, net_dp); + if (r != EFI_SUCCESS) + return r; +set_addr: +#ifdef CONFIG_EFI_HTTP_PROTOCOL + /* + * No harm on doing the following. If the PXE handle is present, the client could + * find it and try to get its IP address from it. In here the PXE handle is present + * but the PXE protocol is not yet implmenented, so we add this in the meantime. + */ + efi_net_get_addr((struct efi_ipv4_address *)&netobj->pxe_mode.station_ip, + (struct efi_ipv4_address *)&netobj->pxe_mode.subnet_mask, NULL, dev); +#endif + + return r; +} + +/** * efi_net_register() - register the simple network protocol * * This gets called from do_bootefi_exec(). + * @dev: net udevice */ -efi_status_t efi_net_register(void) +efi_status_t efi_net_register(struct udevice *dev) { efi_status_t r; - int i; - - if (!eth_get_dev()) { + int seq_num; + struct efi_net_obj *netobj; + void *transmit_buffer = NULL; + uchar **receive_buffer = NULL; + size_t *receive_lengths; + int i, j; + + if (!dev) { /* No network device active, don't expose any */ return EFI_SUCCESS; } + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && net_objs[i]->dev == dev) { + // Do not register duplicate devices + return EFI_SUCCESS; + } + } + + seq_num = -1; + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (!net_objs[i]) { + seq_num = i; + break; + } + } + if (seq_num < 0) + return EFI_OUT_OF_RESOURCES; + /* We only expose the "active" network device, so one is enough */ netobj = calloc(1, sizeof(*netobj)); if (!netobj) goto out_of_resources; + netobj->dev = dev; + /* Allocate an aligned transmit buffer */ transmit_buffer = calloc(1, PKTSIZE_ALIGN + PKTALIGN); if (!transmit_buffer) goto out_of_resources; transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN); + netobj->transmit_buffer = transmit_buffer; /* Allocate a number of receive buffers */ receive_buffer = calloc(ETH_PACKETS_BATCH_RECV, @@ -914,10 +1178,13 @@ efi_status_t efi_net_register(void) if (!receive_buffer[i]) goto out_of_resources; } + netobj->receive_buffer = receive_buffer; + receive_lengths = calloc(ETH_PACKETS_BATCH_RECV, sizeof(*receive_lengths)); if (!receive_lengths) goto out_of_resources; + netobj->receive_lengths = receive_lengths; /* Hook net up to the device list */ efi_add_handle(&netobj->header); @@ -927,12 +1194,7 @@ efi_status_t efi_net_register(void) &netobj->net); if (r != EFI_SUCCESS) goto failure_to_add_protocol; - if (!net_dp) - efi_net_set_dp("Net", NULL); - r = efi_add_protocol(&netobj->header, &efi_guid_device_path, - net_dp); - if (r != EFI_SUCCESS) - goto failure_to_add_protocol; + r = efi_add_protocol(&netobj->header, &efi_pxe_base_code_protocol_guid, &netobj->pxe); if (r != EFI_SUCCESS) @@ -953,7 +1215,9 @@ efi_status_t efi_net_register(void) netobj->net.receive = efi_net_receive; netobj->net.mode = &netobj->net_mode; netobj->net_mode.state = EFI_NETWORK_STOPPED; - memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6); + if (dev_get_plat(dev)) + memcpy(netobj->net_mode.current_address.mac_addr, + ((struct eth_pdata *)dev_get_plat(dev))->enetaddr, 6); netobj->net_mode.hwaddr_size = ARP_HLEN; netobj->net_mode.media_header_size = ETHER_HDR_SIZE; netobj->net_mode.max_packet_size = PKTSIZE; @@ -973,20 +1237,31 @@ efi_status_t efi_net_register(void) netobj->pxe.set_station_ip = efi_pxe_base_code_set_station_ip; netobj->pxe.set_packets = efi_pxe_base_code_set_packets; netobj->pxe.mode = &netobj->pxe_mode; - if (dhcp_ack) - netobj->pxe_mode.dhcp_ack = *dhcp_ack; + + /* + * Scan dhcp entries for one corresponding + * to this udevice, from newest to oldest + */ + i = (next_dhcp_entry + MAX_NUM_DHCP_ENTRIES - 1) % MAX_NUM_DHCP_ENTRIES; + for (j = 0; dhcp_cache[i].is_valid && j < MAX_NUM_DHCP_ENTRIES; + i = (i + MAX_NUM_DHCP_ENTRIES - 1) % MAX_NUM_DHCP_ENTRIES, j++) { + if (dev == dhcp_cache[i].dev) { + netobj->pxe_mode.dhcp_ack = *dhcp_cache[i].dhcp_ack; + break; + } + } /* * Create WaitForPacket event. */ r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_network_timer_notify, NULL, NULL, - &wait_for_packet); + &netobj->wait_for_packet); if (r != EFI_SUCCESS) { printf("ERROR: Failed to register network event\n"); return r; } - netobj->net.wait_for_packet = wait_for_packet; + netobj->net.wait_for_packet = netobj->wait_for_packet; /* * Create a timer event. * @@ -997,13 +1272,13 @@ efi_status_t efi_net_register(void) */ r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, efi_network_timer_notify, &netobj->net, NULL, - &network_timer_event); + &netobj->network_timer_event); if (r != EFI_SUCCESS) { printf("ERROR: Failed to register network event\n"); return r; } /* Network is time critical, create event in every timer cycle */ - r = efi_set_timer(network_timer_event, EFI_TIMER_PERIODIC, 0); + r = efi_set_timer(netobj->network_timer_event, EFI_TIMER_PERIODIC, 0); if (r != EFI_SUCCESS) { printf("ERROR: Failed to set network timer\n"); return r; @@ -1019,15 +1294,9 @@ efi_status_t efi_net_register(void) r = efi_http_register(&netobj->header, &netobj->http_service_binding); if (r != EFI_SUCCESS) goto failure_to_add_protocol; - /* - * No harm on doing the following. If the PXE handle is present, the client could - * find it and try to get its IP address from it. In here the PXE handle is present - * but the PXE protocol is not yet implmenented, so we add this in the meantime. - */ - efi_net_get_addr((struct efi_ipv4_address *)&netobj->pxe_mode.station_ip, - (struct efi_ipv4_address *)&netobj->pxe_mode.subnet_mask, NULL); #endif - + netobj->efi_seq_num = seq_num; + net_objs[seq_num] = netobj; return EFI_SUCCESS; failure_to_add_protocol: printf("ERROR: Failure to add protocol\n"); @@ -1046,46 +1315,103 @@ out_of_resources: } /** - * efi_net_set_dp() - set device path of efi net device + * efi_net_new_dp() - update device path associated to a net udevice * * This gets called to update the device path when a new boot * file is downloaded * * @dev: dev to set the device path from * @server: remote server address + * @udev: net udevice * Return: status code */ -efi_status_t efi_net_set_dp(const char *dev, const char *server) +efi_status_t efi_net_new_dp(const char *dev, const char *server, struct udevice *udev) { - efi_free_pool(net_dp); + efi_status_t ret; + struct efi_net_obj *netobj; + struct efi_device_path *old_net_dp, *new_net_dp; + struct efi_device_path **dp; + int i; + + dp = &dp_cache[next_dp_entry].net_dp; - net_dp = NULL; + dp_cache[next_dp_entry].dev = udev; + dp_cache[next_dp_entry].is_valid = true; + next_dp_entry++; + next_dp_entry %= MAX_NUM_DP_ENTRIES; + + old_net_dp = *dp; + new_net_dp = NULL; if (!strcmp(dev, "Net")) - net_dp = efi_dp_from_eth(); + new_net_dp = efi_dp_from_eth(udev); else if (!strcmp(dev, "Http")) - net_dp = efi_dp_from_http(server); + new_net_dp = efi_dp_from_http(server, udev); + if (!new_net_dp) + return EFI_OUT_OF_RESOURCES; - if (!net_dp) + *dp = new_net_dp; + // Free the old cache entry + efi_free_pool(old_net_dp); + + netobj = NULL; + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && net_objs[i]->dev == udev) { + netobj = net_objs[i]; + break; + } + } + if (!netobj) + return EFI_SUCCESS; + + new_net_dp = efi_dp_dup(*dp); + if (!new_net_dp) return EFI_OUT_OF_RESOURCES; + ret = efi_netobj_set_dp(netobj, new_net_dp); + if (ret != EFI_SUCCESS) + efi_free_pool(new_net_dp); - return EFI_SUCCESS; + return ret; } /** - * efi_net_get_dp() - get device path of efi net device + * efi_net_dp_from_dev() - get device path associated to a net udevice * * Produce a copy of the current device path * - * @dp: copy of the current device path, or NULL on error + * @dp: copy of the current device path + * @udev: net udevice + * @cache_only: get device path from cache only */ -void efi_net_get_dp(struct efi_device_path **dp) +void efi_net_dp_from_dev(struct efi_device_path **dp, struct udevice *udev, bool cache_only) { + int i, j; + if (!dp) return; - if (!net_dp) - efi_net_set_dp("Net", NULL); - if (net_dp) - *dp = efi_dp_dup(net_dp); + + *dp = NULL; + + if (cache_only) + goto cache; + + // If a netobj matches: + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && net_objs[i]->dev == udev) { + *dp = efi_netobj_get_dp(net_objs[i]); + if (*dp) + return; + } + } +cache: + // Search in the cache + i = (next_dp_entry + MAX_NUM_DP_ENTRIES - 1) % MAX_NUM_DP_ENTRIES; + for (j = 0; dp_cache[i].is_valid && j < MAX_NUM_DP_ENTRIES; + i = (i + MAX_NUM_DP_ENTRIES - 1) % MAX_NUM_DP_ENTRIES, j++) { + if (dp_cache[i].dev == udev) { + *dp = efi_dp_dup(dp_cache[i].net_dp); + return; + } + } } /** @@ -1101,11 +1427,15 @@ void efi_net_get_dp(struct efi_device_path **dp) * be filled with the current network mask * @gw: pointer to an efi_ipv4_address struct to be * filled with the current network gateway + * @dev: udevice */ void efi_net_get_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw) + struct efi_ipv4_address *gw, + struct udevice *dev) { + if (!dev) + dev = eth_get_dev(); #ifdef CONFIG_NET_LWIP char ipstr[] = "ipaddr\0\0"; char maskstr[] = "netmask\0\0"; @@ -1114,7 +1444,7 @@ void efi_net_get_addr(struct efi_ipv4_address *ip, struct in_addr tmp; char *env; - idx = dev_seq(eth_get_dev()); + idx = dev_seq(dev); if (idx < 0 || idx > 99) { log_err("unexpected idx %d\n", idx); @@ -1161,11 +1491,15 @@ void efi_net_get_addr(struct efi_ipv4_address *ip, * @ip: pointer to new IP address * @mask: pointer to new network mask to set * @gw: pointer to new network gateway + * @dev: udevice */ void efi_net_set_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw) + struct efi_ipv4_address *gw, + struct udevice *dev) { + if (!dev) + dev = eth_get_dev(); #ifdef CONFIG_NET_LWIP char ipstr[] = "ipaddr\0\0"; char maskstr[] = "netmask\0\0"; @@ -1174,7 +1508,7 @@ void efi_net_set_addr(struct efi_ipv4_address *ip, struct in_addr *addr; char tmp[46]; - idx = dev_seq(eth_get_dev()); + idx = dev_seq(dev); if (idx < 0 || idx > 99) { log_err("unexpected idx %d\n", idx); @@ -1212,6 +1546,7 @@ void efi_net_set_addr(struct efi_ipv4_address *ip, #endif } +#if IS_ENABLED(CONFIG_EFI_HTTP_PROTOCOL) /** * efi_net_set_buffer() - allocate a buffer of min 64K * @@ -1299,26 +1634,41 @@ void efi_net_parse_headers(ulong *num_headers, struct http_header *headers) * @status_code: HTTP status code * @file_size: file size in bytes * @headers_buffer: headers buffer + * @parent: service binding protocol * Return: status code */ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buffer, - u32 *status_code, ulong *file_size, char *headers_buffer) + u32 *status_code, ulong *file_size, char *headers_buffer, + struct efi_service_binding_protocol *parent) { efi_status_t ret = EFI_SUCCESS; int wget_ret; static bool last_head; + struct udevice *dev; + int i; - if (!buffer || !file_size) + if (!buffer || !file_size || !parent) return EFI_ABORTED; efi_wget_info.method = (enum wget_http_method)method; efi_wget_info.headers = headers_buffer; + // Set corresponding udevice + dev = NULL; + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && &net_objs[i]->http_service_binding == parent) + dev = net_objs[i]->dev; + } + if (!dev) + return EFI_ABORTED; + switch (method) { case HTTP_METHOD_GET: ret = efi_net_set_buffer(buffer, last_head ? (size_t)efi_wget_info.hdr_cont_len : 0); if (ret != EFI_SUCCESS) goto out; + eth_set_dev(dev); + env_set("ethact", eth_get_name()); wget_ret = wget_request((ulong)*buffer, url, &efi_wget_info); if ((ulong)efi_wget_info.hdr_cont_len > efi_wget_info.buffer_size) { // Try again with updated buffer size @@ -1326,6 +1676,8 @@ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buf ret = efi_net_set_buffer(buffer, (size_t)efi_wget_info.hdr_cont_len); if (ret != EFI_SUCCESS) goto out; + eth_set_dev(dev); + env_set("ethact", eth_get_name()); if (wget_request((ulong)*buffer, url, &efi_wget_info)) { efi_free_pool(*buffer); ret = EFI_DEVICE_ERROR; @@ -1345,6 +1697,8 @@ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buf ret = efi_net_set_buffer(buffer, 0); if (ret != EFI_SUCCESS) goto out; + eth_set_dev(dev); + env_set("ethact", eth_get_name()); wget_request((ulong)*buffer, url, &efi_wget_info); *file_size = 0; *status_code = efi_wget_info.status_code; @@ -1358,3 +1712,4 @@ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buf out: return ret; } +#endif diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index aa59bc7779d..48f91da5df7 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -11,7 +11,9 @@ #include <efi_variable.h> #include <log.h> #include <asm-generic/unaligned.h> +#include <net.h> +#define OBJ_LIST_INITIALIZED 0 #define OBJ_LIST_NOT_INITIALIZED 1 efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; @@ -209,6 +211,21 @@ out: } /** + * efi_start_obj_list() - Start EFI object list + * + * Return: status code + */ +static efi_status_t efi_start_obj_list(void) +{ + efi_status_t ret = EFI_SUCCESS; + + if (IS_ENABLED(CONFIG_NETDEVICES)) + ret = efi_net_do_start(eth_get_dev()); + + return ret; +} + +/** * efi_init_obj_list() - Initialize and populate EFI object list * * Return: status code @@ -217,7 +234,9 @@ efi_status_t efi_init_obj_list(void) { efi_status_t ret = EFI_SUCCESS; - /* Initialize once only */ + /* Initialize only once, but start every time if correctly initialized*/ + if (efi_obj_list_initialized == OBJ_LIST_INITIALIZED) + return efi_start_obj_list(); if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED) return efi_obj_list_initialized; @@ -318,7 +337,7 @@ efi_status_t efi_init_obj_list(void) goto out; } if (IS_ENABLED(CONFIG_NETDEVICES)) { - ret = efi_net_register(); + ret = efi_net_register(eth_get_dev()); if (ret != EFI_SUCCESS) goto out; } @@ -349,6 +368,10 @@ efi_status_t efi_init_obj_list(void) if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK) && !IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY)) ret = efi_launch_capsules(); + if (ret != EFI_SUCCESS) + goto out; + + ret = efi_start_obj_list(); out: efi_obj_list_initialized = ret; return ret; diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index 15af8d3e18c..b00c76c2f17 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -67,7 +67,6 @@ struct dhcp { static struct efi_boot_services *boottime; static struct efi_simple_network *net; static struct efi_event *timer; -static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; /* IP packet ID */ static unsigned int net_ip_id; diff --git a/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c b/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c index 46421588fef..ef51a5ac168 100644 --- a/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c +++ b/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c @@ -298,6 +298,9 @@ altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t * if (ret != 0) { LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_handshake failed: %d\n", ret)); /* handshake failed, connection has to be closed */ + if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { + printf("Certificate verification failed\n"); + } if (conn->err) { conn->err(conn->arg, ERR_CLSD); } @@ -786,6 +789,7 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav int ret; struct altcp_tls_config *conf; mbedtls_x509_crt *mem; + int authmode = have_ca ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE; if (TCP_WND < MBEDTLS_SSL_IN_CONTENT_LEN || TCP_WND < MBEDTLS_SSL_OUT_CONTENT_LEN) { LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG|LWIP_DBG_LEVEL_SERIOUS, @@ -840,7 +844,10 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav altcp_mbedtls_free_config(conf); return NULL; } - mbedtls_ssl_conf_authmode(&conf->conf, ALTCP_MBEDTLS_AUTHMODE); + if (authmode == MBEDTLS_SSL_VERIFY_NONE) { + printf("WARNING: no CA certificates, HTTPS connections not authenticated\n"); + } + mbedtls_ssl_conf_authmode(&conf->conf, authmode); mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg); #if ALTCP_MBEDTLS_LIB_DEBUG != LWIP_DBG_OFF diff --git a/lib/lwip/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h b/lib/lwip/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h index e41301c061c..71aa5993935 100644 --- a/lib/lwip/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h +++ b/lib/lwip/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h @@ -100,12 +100,6 @@ #define ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS (60 * 60 * 24) #endif -/** Certificate verification mode: MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL (default), - * MBEDTLS_SSL_VERIFY_REQUIRED (recommended)*/ -#ifndef ALTCP_MBEDTLS_AUTHMODE -#define ALTCP_MBEDTLS_AUTHMODE MBEDTLS_SSL_VERIFY_OPTIONAL -#endif - #endif /* LWIP_ALTCP */ #endif /* LWIP_HDR_ALTCP_TLS_OPTS_H */ diff --git a/lib/mbedtls/Kconfig b/lib/mbedtls/Kconfig index 35d8c507a89..789721ee6cd 100644 --- a/lib/mbedtls/Kconfig +++ b/lib/mbedtls/Kconfig @@ -1,57 +1,54 @@ +# For U-Boot Proper + choice - prompt "Select crypto libraries" - default LEGACY_CRYPTO + prompt "Crypto libraries (U-Boot Proper)" + default LEGACY_HASHING_AND_CRYPTO help Select crypto libraries. - LEGACY_CRYPTO for legacy crypto libraries, + LEGACY_HASHING_AND_CRYPTO for legacy crypto libraries, MBEDTLS_LIB for MbedTLS libraries. -config LEGACY_CRYPTO +config LEGACY_HASHING_AND_CRYPTO bool "legacy crypto libraries" - select LEGACY_CRYPTO_BASIC - select LEGACY_CRYPTO_CERT + select LEGACY_HASHING + select LEGACY_CRYPTO config MBEDTLS_LIB bool "MbedTLS libraries" select MBEDTLS_LIB_X509 endchoice -if LEGACY_CRYPTO || MBEDTLS_LIB_CRYPTO_ALT +if LEGACY_HASHING_AND_CRYPTO || MBEDTLS_LIB_HASHING_ALT -config LEGACY_CRYPTO_BASIC - bool "legacy basic crypto libraries" +config LEGACY_HASHING + bool "Use U-Boot legacy hashing libraries" select MD5_LEGACY if MD5 select SHA1_LEGACY if SHA1 select SHA256_LEGACY if SHA256 select SHA512_LEGACY if SHA512 select SHA384_LEGACY if SHA384 - select SPL_MD5_LEGACY if SPL_MD5 - select SPL_SHA1_LEGACY if SPL_SHA1 - select SPL_SHA256_LEGACY if SPL_SHA256 - select SPL_SHA512_LEGACY if SPL_SHA512 - select SPL_SHA384_LEGACY if SPL_SHA384 help - Enable legacy basic crypto libraries. + Enable U-Boot legacy hashing libraries. -if LEGACY_CRYPTO_BASIC +if LEGACY_HASHING config SHA1_LEGACY bool "Enable SHA1 support with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SHA1 + depends on LEGACY_HASHING && SHA1 help This option enables support of hashing using SHA1 algorithm with legacy crypto library. config SHA256_LEGACY bool "Enable SHA256 support with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SHA256 + depends on LEGACY_HASHING && SHA256 help This option enables support of hashing using SHA256 algorithm with legacy crypto library. config SHA512_LEGACY bool "Enable SHA512 support with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SHA512 + depends on LEGACY_HASHING && SHA512 default y if TI_SECURE_DEVICE && FIT_SIGNATURE help This option enables support of hashing using SHA512 algorithm @@ -59,7 +56,7 @@ config SHA512_LEGACY config SHA384_LEGACY bool "Enable SHA384 support with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SHA384 + depends on LEGACY_HASHING && SHA384 select SHA512_LEGACY help This option enables support of hashing using SHA384 algorithm @@ -67,95 +64,16 @@ config SHA384_LEGACY config MD5_LEGACY bool "Enable MD5 support with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && MD5 + depends on LEGACY_HASHING && MD5 help This option enables support of hashing using MD5 algorithm with legacy crypto library. -if SPL - -config SPL_SHA1_LEGACY - bool "Enable SHA1 support in SPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SPL_SHA1 - help - This option enables support of hashing using SHA1 algorithm - with legacy crypto library. - -config SPL_SHA256_LEGACY - bool "Enable SHA256 support in SPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SPL_SHA256 - help - This option enables support of hashing using SHA256 algorithm - with legacy crypto library. +endif # LEGACY_HASHING -config SPL_SHA512_LEGACY - bool "Enable SHA512 support in SPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SPL_SHA512 - help - This option enables support of hashing using SHA512 algorithm - with legacy crypto library. - -config SPL_SHA384_LEGACY - bool "Enable SHA384 support in SPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SPL_SHA384 - select SPL_SHA512_LEGACY - help - This option enables support of hashing using SHA384 algorithm - with legacy crypto library. - -config SPL_MD5_LEGACY - bool "Enable MD5 support in SPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SPL_MD5 - help - This option enables support of hashing using MD5 algorithm - with legacy crypto library. - -endif # SPL - -if VPL - -config VPL_SHA1_LEGACY - bool "Enable SHA1 support in VPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && VPL_SHA1 - help - This option enables support of hashing using SHA1 algorithm - with legacy crypto library. - -config VPL_SHA256_LEGACY - bool "Enable SHA256 support in VPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && VPL_SHA256 - help - This option enables support of hashing using SHA256 algorithm - with legacy crypto library. - -config VPL_SHA512_LEGACY - bool "Enable SHA512 support in VPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && VPL_SHA512 - help - This option enables support of hashing using SHA512 algorithm - with legacy crypto library. - -config VPL_SHA384_LEGACY - bool "Enable SHA384 support in VPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && VPL_SHA384 - select VPL_SHA512_LEGACY - help - This option enables support of hashing using SHA384 algorithm - with legacy crypto library. - -config VPL_MD5_LEGACY - bool "Enable MD5 support in VPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && VPL_MD5 - help - This option enables support of hashing using MD5 algorithm - with legacy crypto library. - -endif # VPL - -endif # LEGACY_CRYPTO_BASIC - -config LEGACY_CRYPTO_CERT +config LEGACY_CRYPTO bool "legacy certificate libraries" + depends on LEGACY_HASHING_AND_CRYPTO select ASN1_DECODER_LEGACY if ASN1_DECODER select ASYMMETRIC_PUBLIC_KEY_LEGACY if \ ASYMMETRIC_PUBLIC_KEY_SUBTYPE @@ -163,24 +81,20 @@ config LEGACY_CRYPTO_CERT select X509_CERTIFICATE_PARSER_LEGACY if X509_CERTIFICATE_PARSER select PKCS7_MESSAGE_PARSER_LEGACY if PKCS7_MESSAGE_PARSER select MSCODE_PARSER_LEGACY if MSCODE_PARSER - select SPL_ASN1_DECODER_LEGACY if SPL_ASN1_DECODER - select SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY if \ - SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE - select SPL_RSA_PUBLIC_KEY_PARSER_LEGACY if SPL_RSA_PUBLIC_KEY_PARSER help Enable legacy certificate libraries. -if LEGACY_CRYPTO_CERT +if LEGACY_CRYPTO config ASN1_DECODER_LEGACY bool "ASN1 decoder with legacy certificate library" - depends on LEGACY_CRYPTO_CERT && ASN1_DECODER + depends on LEGACY_CRYPTO && ASN1_DECODER help This option chooses legacy certificate library for ASN1 decoder. config ASYMMETRIC_PUBLIC_KEY_LEGACY bool "Asymmetric public key crypto with legacy certificate library" - depends on LEGACY_CRYPTO_CERT && ASYMMETRIC_PUBLIC_KEY_SUBTYPE + depends on LEGACY_CRYPTO && ASYMMETRIC_PUBLIC_KEY_SUBTYPE help This option chooses legacy certificate library for asymmetric public key crypto algorithm. @@ -211,68 +125,41 @@ config PKCS7_MESSAGE_PARSER_LEGACY config MSCODE_PARSER_LEGACY bool "MS authenticode parser with legacy certificate library" - depends on LEGACY_CRYPTO_CERT && MSCODE_PARSER + depends on LEGACY_CRYPTO && MSCODE_PARSER select ASN1_DECODER_LEGACY help This option chooses legacy certificate library for MS authenticode parser. -if SPL - -config SPL_ASN1_DECODER_LEGACY - bool "ASN1 decoder with legacy certificate library in SPL" - depends on LEGACY_CRYPTO_CERT && SPL_ASN1_DECODER - help - This option chooses legacy certificate library for ASN1 decoder in - SPL. - -config SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY - bool "Asymmetric public key crypto with legacy certificate library in SPL" - depends on LEGACY_CRYPTO_CERT && SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE - help - This option chooses legacy certificate library for asymmetric public - key crypto algorithm in SPL. - -config SPL_RSA_PUBLIC_KEY_PARSER_LEGACY - bool "RSA public key parser with legacy certificate library in SPL" - depends on SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY - select SPL_ASN1_DECODER_LEGACY - help - This option chooses legacy certificate library for RSA public key - parser in SPL. - -endif # SPL - -endif # LEGACY_CRYPTO_CERT - endif # LEGACY_CRYPTO +endif # LEGACY_HASHING_AND_CRYPTO || MBEDTLS_LIB_HASHING_ALT + if MBEDTLS_LIB -config MBEDTLS_LIB_CRYPTO_ALT - bool "MbedTLS crypto alternatives" +config MBEDTLS_LIB_HASHING_ALT + bool "Replace MbedTLS native hashing with U-Boot legacy libraries" depends on MBEDTLS_LIB && !MBEDTLS_LIB_CRYPTO - select LEGACY_CRYPTO_BASIC + select LEGACY_HASHING default y if MBEDTLS_LIB && !MBEDTLS_LIB_CRYPTO help - Enable MbedTLS crypto alternatives. + Enable MbedTLS hashing alternatives and replace them with legacy hashing + libraries. + This allows user to use U-Boot legacy hashing algorithms together with + other MbedTLS modules. Mutually incompatible with MBEDTLS_LIB_CRYPTO. config MBEDTLS_LIB_CRYPTO - bool "MbedTLS crypto libraries" + bool "Use MbedTLS native crypto libraries for hashing" + default y if MBEDTLS_LIB select MD5_MBEDTLS if MD5 select SHA1_MBEDTLS if SHA1 select SHA256_MBEDTLS if SHA256 select SHA512_MBEDTLS if SHA512 select SHA384_MBEDTLS if SHA384 - select SPL_MD5_MBEDTLS if SPL_MD5 - select SPL_SHA1_MBEDTLS if SPL_SHA1 - select SPL_SHA256_MBEDTLS if SPL_SHA256 - select SPL_SHA512_MBEDTLS if SPL_SHA512 - select SPL_SHA384_MBEDTLS if SPL_SHA384 help - Enable MbedTLS crypto libraries. - Mutually incompatible with MBEDTLS_LIB_CRYPTO_ALT. + Enable MbedTLS native crypto libraries. + Mutually incompatible with MBEDTLS_LIB_HASHING_ALT. if MBEDTLS_LIB_CRYPTO @@ -344,53 +231,6 @@ config HKDF_MBEDTLS This option enables support of key derivation using HKDF algorithm with MbedTLS crypto library. -if SPL - -config SPL_SHA1_MBEDTLS - bool "Enable SHA1 support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO && SPL_SHA1 - help - This option enables support of hashing using SHA1 algorithm - with MbedTLS crypto library. - -config SPL_SHA256_MBEDTLS - bool "Enable SHA256 support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO && SPL_SHA256 - help - This option enables support of hashing using SHA256 algorithm - with MbedTLS crypto library. - -config SPL_SHA512_MBEDTLS - bool "Enable SHA512 support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO && SPL_SHA512 - help - This option enables support of hashing using SHA512 algorithm - with MbedTLS crypto library. - -config SPL_SHA384_MBEDTLS - bool "Enable SHA384 support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO && SPL_SHA384 - select SPL_SHA512 - help - This option enables support of hashing using SHA384 algorithm - with MbedTLS crypto library. - -config SPL_MD5_MBEDTLS - bool "Enable MD5 support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO && SPL_MD5 - help - This option enables support of hashing using MD5 algorithm - with MbedTLS crypto library. - -config SPL_HKDF_MBEDTLS - bool "Enable HKDF support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO - help - This option enables support of key derivation using HKDF algorithm - with MbedTLS crypto library. - -endif # SPL - endif # MBEDTLS_LIB_CRYPTO config MBEDTLS_LIB_X509 @@ -402,10 +242,6 @@ config MBEDTLS_LIB_X509 select X509_CERTIFICATE_PARSER_MBEDTLS if X509_CERTIFICATE_PARSER select PKCS7_MESSAGE_PARSER_MBEDTLS if PKCS7_MESSAGE_PARSER select MSCODE_PARSER_MBEDTLS if MSCODE_PARSER - select SPL_ASN1_DECODER_MBEDTLS if SPL_ASN1_DECODER - select SPL_ASYMMETRIC_PUBLIC_KEY_MBEDTLS if \ - SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE - select SPL_RSA_PUBLIC_KEY_PARSER_MBEDTLS if SPL_RSA_PUBLIC_KEY_PARSER help Enable MbedTLS certificate libraries. @@ -456,44 +292,554 @@ config MSCODE_PARSER_MBEDTLS This option chooses MbedTLS certificate library for MS authenticode parser. +endif # MBEDTLS_LIB_X509 + +config MBEDTLS_LIB_TLS + bool "MbedTLS TLS library" + depends on RSA_PUBLIC_KEY_PARSER_MBEDTLS + depends on X509_CERTIFICATE_PARSER_MBEDTLS + depends on ASYMMETRIC_PUBLIC_KEY_MBEDTLS + depends on ASN1_DECODER_MBEDTLS + depends on MBEDTLS_LIB + help + Enable MbedTLS TLS library. Required for HTTPs support + in wget + +endif # MBEDTLS_LIB + +# For SPL + if SPL +choice + prompt "Crypto libraries (SPL)" + default SPL_LEGACY_HASHING_AND_CRYPTO + help + Select crypto libraries in SPL. + SPL_LEGACY_HASHING_AND_CRYPTO for legacy crypto libraries, + SPL_MBEDTLS_LIB for MbedTLS libraries. + +config SPL_LEGACY_HASHING_AND_CRYPTO + bool "legacy crypto libraries" + select SPL_LEGACY_HASHING + select SPL_LEGACY_CRYPTO + +config SPL_MBEDTLS_LIB + bool "MbedTLS libraries" + select SPL_MBEDTLS_LIB_X509 +endchoice + +if SPL_LEGACY_HASHING_AND_CRYPTO || SPL_MBEDTLS_LIB_HASHING_ALT + +config SPL_LEGACY_HASHING + bool "Use U-Boot legacy hashing libraries (SPL)" + select SPL_MD5_LEGACY if SPL_MD5 + select SPL_SHA1_LEGACY if SPL_SHA1 + select SPL_SHA256_LEGACY if SPL_SHA256 + select SPL_SHA512_LEGACY if SPL_SHA512 + select SPL_SHA384_LEGACY if SPL_SHA384 + help + Enable U-Boot legacy hashing libraries in SPL. + +if SPL_LEGACY_HASHING + +config SPL_SHA1_LEGACY + bool "Enable SHA1 support with legacy crypto library (SPL)" + depends on SPL_LEGACY_HASHING && SPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with legacy crypto library in SPL. + +config SPL_SHA256_LEGACY + bool "Enable SHA256 support with legacy crypto library (SPL)" + depends on SPL_LEGACY_HASHING && SPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with legacy crypto library in SPL. + +config SPL_SHA512_LEGACY + bool "Enable SHA512 support with legacy crypto library (SPL)" + depends on SPL_LEGACY_HASHING && SPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with legacy crypto library in SPL. + +config SPL_SHA384_LEGACY + bool "Enable SHA384 support with legacy crypto library (SPL)" + depends on SPL_LEGACY_HASHING && SPL_SHA384 + select SPL_SHA512_LEGACY + help + This option enables support of hashing using SHA384 algorithm + with legacy crypto library in SPL. + +config SPL_MD5_LEGACY + bool "Enable MD5 support with legacy crypto library (SPL)" + depends on SPL_LEGACY_HASHING && SPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with legacy crypto library in SPL. + +endif # SPL_LEGACY_HASHING + +config SPL_LEGACY_CRYPTO + bool "legacy certificate libraries (SPL)" + depends on SPL_LEGACY_HASHING_AND_CRYPTO + select SPL_ASN1_DECODER_LEGACY if SPL_ASN1_DECODER + select SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY if \ + SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select SPL_RSA_PUBLIC_KEY_PARSER_LEGACY if SPL_RSA_PUBLIC_KEY_PARSER + help + Enable legacy certificate libraries in SPL. + +if SPL_LEGACY_CRYPTO + +config SPL_ASN1_DECODER_LEGACY + bool "ASN1 decoder with legacy certificate library (SPL)" + depends on SPL_LEGACY_CRYPTO && SPL_ASN1_DECODER + help + This option chooses legacy certificate library for ASN1 decoder in + SPL. + +config SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY + bool "Asymmetric public key crypto with legacy certificate library (SPL)" + depends on SPL_LEGACY_CRYPTO && SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE + help + This option chooses legacy certificate library for asymmetric public + key crypto algorithm in SPL. + +config SPL_RSA_PUBLIC_KEY_PARSER_LEGACY + bool "RSA public key parser with legacy certificate library (SPL)" + depends on SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY + select SPL_ASN1_DECODER_LEGACY + help + This option chooses legacy certificate library for RSA public key + parser in SPL. + +endif # SPL_LEGACY_CRYPTO + +endif # SPL_LEGACY_HASHING_AND_CRYPTO || SPL_MBEDTLS_LIB_HASHING_ALT + +if SPL_MBEDTLS_LIB + +config SPL_MBEDTLS_LIB_HASHING_ALT + bool "Replace MbedTLS native hashing with U-Boot legacy libraries (SPL)" + depends on SPL_MBEDTLS_LIB && !SPL_MBEDTLS_LIB_CRYPTO + select SPL_LEGACY_HASHING + default y if SPL_MBEDTLS_LIB && !SPL_MBEDTLS_LIB_CRYPTO + help + Enable MbedTLS hashing alternatives and replace them with legacy hashing + libraries in SPL. + This allows user to use U-Boot legacy hashing algorithms together with + other MbedTLS modules. + Mutually incompatible with SPL_MBEDTLS_LIB_CRYPTO. + +config SPL_MBEDTLS_LIB_CRYPTO + bool "Use MbedTLS native crypto libraries for hashing (SPL)" + default y if SPL_MBEDTLS_LIB + select SPL_MD5_MBEDTLS if SPL_MD5 + select SPL_SHA1_MBEDTLS if SPL_SHA1 + select SPL_SHA256_MBEDTLS if SPL_SHA256 + select SPL_SHA512_MBEDTLS if SPL_SHA512 + select SPL_SHA384_MBEDTLS if SPL_SHA384 + help + Enable MbedTLS native crypto libraries in SPL. + +if SPL_MBEDTLS_LIB_CRYPTO + +config SPL_SHA1_MBEDTLS + bool "Enable SHA1 support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO && SPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with MbedTLS crypto library in SPL. + +config SPL_SHA256_MBEDTLS + bool "Enable SHA256 support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO && SPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with MbedTLS crypto library in SPL. + +config SPL_SHA512_MBEDTLS + bool "Enable SHA512 support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO && SPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with MbedTLS crypto library in SPL. + +config SPL_SHA384_MBEDTLS + bool "Enable SHA384 support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO && SPL_SHA384 + select SPL_SHA512 + help + This option enables support of hashing using SHA384 algorithm + with MbedTLS crypto library in SPL. + +config SPL_MD5_MBEDTLS + bool "Enable MD5 support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO && SPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with MbedTLS crypto library in SPL. + +config SPL_HKDF_MBEDTLS + bool "Enable HKDF support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO + help + This option enables support of key derivation using HKDF algorithm + with MbedTLS crypto library in SPL. + +endif # SPL_MBEDTLS_LIB_CRYPTO + +config SPL_MBEDTLS_LIB_X509 + bool "MbedTLS certificate libraries (SPL)" + select SPL_ASN1_DECODER_MBEDTLS if SPL_ASN1_DECODER + select SPL_ASYMMETRIC_PUBLIC_KEY_MBEDTLS if \ + SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select SPL_RSA_PUBLIC_KEY_PARSER_MBEDTLS if SPL_RSA_PUBLIC_KEY_PARSER + help + Enable MbedTLS certificate libraries in SPL. + +if SPL_MBEDTLS_LIB_X509 + config SPL_ASN1_DECODER_MBEDTLS - bool "ASN1 decoder with MbedTLS certificate library in SPL" - depends on MBEDTLS_LIB_X509 && SPL_ASN1_DECODER + bool "ASN1 decoder with MbedTLS certificate library (SPL)" + depends on SPL_MBEDTLS_LIB_X509 && SPL_ASN1_DECODER help This option chooses MbedTLS certificate library for ASN1 decoder in SPL. config SPL_ASYMMETRIC_PUBLIC_KEY_MBEDTLS - bool "Asymmetric public key crypto with MbedTLS certificate library in SPL" - depends on MBEDTLS_LIB_X509 && SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE + bool "Asymmetric public key crypto with MbedTLS certificate library (SPL)" + depends on SPL_MBEDTLS_LIB_X509 && SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE help This option chooses MbedTLS certificate library for asymmetric public key crypto algorithm in SPL. config SPL_RSA_PUBLIC_KEY_PARSER_MBEDTLS - bool "RSA public key parser with MbedTLS certificate library in SPL" + bool "RSA public key parser with MbedTLS certificate library (SPL)" depends on SPL_ASYMMETRIC_PUBLIC_KEY_MBEDTLS select SPL_ASN1_DECODER_MBEDTLS help This option chooses MbedTLS certificate library for RSA public key parser in SPL. +endif # SPL_MBEDTLS_LIB_X509 + +config SPL_MBEDTLS_LIB_TLS + bool "MbedTLS TLS library (SPL)" + depends on SPL_RSA_PUBLIC_KEY_PARSER_MBEDTLS + depends on SPL_X509_CERTIFICATE_PARSER_MBEDTLS + depends on SPL_ASYMMETRIC_PUBLIC_KEY_MBEDTLS + depends on SPL_ASN1_DECODER_MBEDTLS + depends on SPL_MBEDTLS_LIB + help + Enable MbedTLS TLS library in SPL. Required for HTTPs support + in wget + +endif # SPL_MBEDTLS_LIB + endif # SPL -endif # MBEDTLS_LIB_X509 +# For TPL -config MBEDTLS_LIB_TLS - bool "MbedTLS TLS library" - depends on RSA_PUBLIC_KEY_PARSER_MBEDTLS - depends on X509_CERTIFICATE_PARSER_MBEDTLS - depends on ASYMMETRIC_PUBLIC_KEY_MBEDTLS - depends on ASN1_DECODER_MBEDTLS - depends on ASYMMETRIC_PUBLIC_KEY_MBEDTLS - depends on MBEDTLS_LIB_CRYPTO +if TPL + +choice + prompt "Crypto libraries (TPL)" + default TPL_LEGACY_HASHING_AND_CRYPTO help - Enable MbedTLS TLS library. Required for HTTPs support - in wget + Select crypto libraries in TPL. + TPL_LEGACY_HASHING_AND_CRYPTO for legacy crypto libraries, + TPL_MBEDTLS_LIB for MbedTLS libraries. -endif # MBEDTLS_LIB +config TPL_LEGACY_HASHING_AND_CRYPTO + bool "legacy crypto libraries" + select TPL_LEGACY_HASHING + select TPL_LEGACY_CRYPTO + +config TPL_MBEDTLS_LIB + bool "MbedTLS libraries" + +endchoice + +if TPL_LEGACY_HASHING_AND_CRYPTO || TPL_MBEDTLS_LIB_HASHING_ALT + +config TPL_LEGACY_HASHING + bool "Use U-Boot legacy hashing libraries (TPL)" + select TPL_MD5_LEGACY if TPL_MD5 + select TPL_SHA1_LEGACY if TPL_SHA1 + select TPL_SHA256_LEGACY if TPL_SHA256 + select TPL_SHA512_LEGACY if TPL_SHA512 + select TPL_SHA384_LEGACY if TPL_SHA384 + help + Enable U-Boot legacy hashing libraries in TPL. + +if TPL_LEGACY_HASHING + +config TPL_SHA1_LEGACY + bool "Enable SHA1 support with legacy crypto library (TPL)" + depends on TPL_LEGACY_HASHING && TPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with legacy crypto library in TPL. + +config TPL_SHA256_LEGACY + bool "Enable SHA256 support with legacy crypto library (TPL)" + depends on TPL_LEGACY_HASHING && TPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with legacy crypto library in TPL. + +config TPL_SHA512_LEGACY + bool "Enable SHA512 support with legacy crypto library (TPL)" + depends on TPL_LEGACY_HASHING && TPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with legacy crypto library in TPL. + +config TPL_SHA384_LEGACY + bool "Enable SHA384 support with legacy crypto library (TPL)" + depends on TPL_LEGACY_HASHING && TPL_SHA384 + select TPL_SHA512_LEGACY + help + This option enables support of hashing using SHA384 algorithm + with legacy crypto library in TPL. + +config TPL_MD5_LEGACY + bool "Enable MD5 support with legacy crypto library (TPL)" + depends on TPL_LEGACY_HASHING && TPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with legacy crypto library in TPL. + +endif # TPL_LEGACY_HASHING + +endif # TPL_LEGACY_HASHING_AND_CRYPTO || TPL_MBEDTLS_LIB_HASHING_ALT + +if TPL_MBEDTLS_LIB + +config TPL_MBEDTLS_LIB_HASHING_ALT + bool "Replace MbedTLS native hashing with U-Boot legacy libraries (TPL)" + depends on TPL_MBEDTLS_LIB && !TPL_MBEDTLS_LIB_CRYPTO + select TPL_LEGACY_HASHING + default y if TPL_MBEDTLS_LIB && !TPL_MBEDTLS_LIB_CRYPTO + help + Enable MbedTLS hashing alternatives and replace them with legacy hashing + libraries in TPL. + This allows user to use U-Boot legacy hashing algorithms together with + other MbedTLS modules. + Mutually incompatible with TPL_MBEDTLS_LIB_CRYPTO. + +config TPL_MBEDTLS_LIB_CRYPTO + bool "Use MbedTLS native crypto libraries for hashing (TPL)" + default y if TPL_MBEDTLS_LIB + select TPL_MD5_MBEDTLS if TPL_MD5 + select TPL_SHA1_MBEDTLS if TPL_SHA1 + select TPL_SHA256_MBEDTLS if TPL_SHA256 + select TPL_SHA512_MBEDTLS if TPL_SHA512 + select TPL_SHA384_MBEDTLS if TPL_SHA384 + help + Enable MbedTLS native crypto libraries in TPL. + +if TPL_MBEDTLS_LIB_CRYPTO + +config TPL_SHA1_MBEDTLS + bool "Enable SHA1 support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO && TPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with MbedTLS crypto library in TPL. + +config TPL_SHA256_MBEDTLS + bool "Enable SHA256 support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO && TPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with MbedTLS crypto library in TPL. + +config TPL_SHA512_MBEDTLS + bool "Enable SHA512 support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO && TPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with MbedTLS crypto library in TPL. + +config TPL_SHA384_MBEDTLS + bool "Enable SHA384 support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO && TPL_SHA384 + select TPL_SHA512 + help + This option enables support of hashing using SHA384 algorithm + with MbedTLS crypto library in TPL. + +config TPL_MD5_MBEDTLS + bool "Enable MD5 support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO && TPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with MbedTLS crypto library in TPL. + +config TPL_HKDF_MBEDTLS + bool "Enable HKDF support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO + help + This option enables support of key derivation using HKDF algorithm + with MbedTLS crypto library in TPL. + +endif # TPL_MBEDTLS_LIB_CRYPTO + +endif # TPL_MBEDTLS_LIB + +endif # TPL + +# For VPL + +if VPL + +choice + prompt "Crypto libraries (VPL)" + default VPL_LEGACY_HASHING_AND_CRYPTO + help + Select crypto libraries in VPL. + VPL_LEGACY_HASHING_AND_CRYPTO for legacy crypto libraries, + VPL_MBEDTLS_LIB for MbedTLS libraries. + +config VPL_LEGACY_HASHING_AND_CRYPTO + bool "legacy crypto libraries" + select VPL_LEGACY_HASHING + +config VPL_MBEDTLS_LIB + bool "MbedTLS libraries" + +endchoice + +if VPL_LEGACY_HASHING_AND_CRYPTO || VPL_MBEDTLS_LIB_HASHING_ALT + +config VPL_LEGACY_HASHING + bool "Use U-Boot legacy hashing libraries (VPL)" + select VPL_MD5_LEGACY if VPL_MD5 + select VPL_SHA1_LEGACY if VPL_SHA1 + select VPL_SHA256_LEGACY if VPL_SHA256 + select VPL_SHA512_LEGACY if VPL_SHA512 + select VPL_SHA384_LEGACY if VPL_SHA384 + help + Enable U-Boot legacy hashing libraries in VPL. + +if VPL_LEGACY_HASHING + +config VPL_SHA1_LEGACY + bool "Enable SHA1 support with legacy crypto library (VPL)" + depends on VPL_LEGACY_HASHING && VPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with legacy crypto library in VPL. + +config VPL_SHA256_LEGACY + bool "Enable SHA256 support with legacy crypto library (VPL)" + depends on VPL_LEGACY_HASHING && VPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with legacy crypto library in VPL. + +config VPL_SHA512_LEGACY + bool "Enable SHA512 support with legacy crypto library (VPL)" + depends on VPL_LEGACY_HASHING && VPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with legacy crypto library in VPL. + +config VPL_SHA384_LEGACY + bool "Enable SHA384 support with legacy crypto library (VPL)" + depends on VPL_LEGACY_HASHING && VPL_SHA384 + select VPL_SHA512_LEGACY + help + This option enables support of hashing using SHA384 algorithm + with legacy crypto library in VPL. + +config VPL_MD5_LEGACY + bool "Enable MD5 support with legacy crypto library (VPL)" + depends on VPL_LEGACY_HASHING && VPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with legacy crypto library in VPL. + +endif # VPL_LEGACY_HASHING + +endif # VPL_LEGACY_HASHING_AND_CRYPTO || VPL_MBEDTLS_LIB_HASHING_ALT + +if VPL_MBEDTLS_LIB + +config VPL_MBEDTLS_LIB_HASHING_ALT + bool "Replace MbedTLS native hashing with U-Boot legacy libraries (VPL)" + depends on VPL_MBEDTLS_LIB && !VPL_MBEDTLS_LIB_CRYPTO + select VPL_LEGACY_HASHING + default y if VPL_MBEDTLS_LIB && !VPL_MBEDTLS_LIB_CRYPTO + help + Enable MbedTLS hashing alternatives and replace them with legacy hashing + libraries in VPL. + This allows user to use U-Boot legacy hashing algorithms together with + other MbedTLS modules. + Mutually incompatible with VPL_MBEDTLS_LIB_CRYPTO. + +config VPL_MBEDTLS_LIB_CRYPTO + bool "Use MbedTLS native crypto libraries for hashing (VPL)" + default y if VPL_MBEDTLS_LIB + select VPL_MD5_MBEDTLS if VPL_MD5 + select VPL_SHA1_MBEDTLS if VPL_SHA1 + select VPL_SHA256_MBEDTLS if VPL_SHA256 + select VPL_SHA512_MBEDTLS if VPL_SHA512 + select VPL_SHA384_MBEDTLS if VPL_SHA384 + help + Enable MbedTLS native crypto libraries in VPL. + +if VPL_MBEDTLS_LIB_CRYPTO + +config VPL_SHA1_MBEDTLS + bool "Enable SHA1 support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO && VPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with MbedTLS crypto library in VPL. + +config VPL_SHA256_MBEDTLS + bool "Enable SHA256 support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO && VPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with MbedTLS crypto library in VPL. + +config VPL_SHA512_MBEDTLS + bool "Enable SHA512 support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO && VPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with MbedTLS crypto library in VPL. + +config VPL_SHA384_MBEDTLS + bool "Enable SHA384 support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO && VPL_SHA384 + select VPL_SHA512 + help + This option enables support of hashing using SHA384 algorithm + with MbedTLS crypto library in VPL. + +config VPL_MD5_MBEDTLS + bool "Enable MD5 support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO && VPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with MbedTLS crypto library in VPL. + +config VPL_HKDF_MBEDTLS + bool "Enable HKDF support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO + help + This option enables support of key derivation using HKDF algorithm + with MbedTLS crypto library in VPL. + +endif # VPL_MBEDTLS_LIB_CRYPTO + +endif # VPL_MBEDTLS_LIB + +endif # VPL diff --git a/lib/mbedtls/Makefile b/lib/mbedtls/Makefile index e66c2018d97..4bbe7ceec45 100644 --- a/lib/mbedtls/Makefile +++ b/lib/mbedtls/Makefile @@ -6,60 +6,60 @@ MBEDTLS_LIB_DIR = external/mbedtls/library # shim layer for hash -obj-$(CONFIG_$(SPL_)MD5_MBEDTLS) += md5.o -obj-$(CONFIG_$(SPL_)SHA1_MBEDTLS) += sha1.o -obj-$(CONFIG_$(SPL_)SHA256_MBEDTLS) += sha256.o -obj-$(CONFIG_$(SPL_)SHA512_MBEDTLS) += sha512.o +obj-$(CONFIG_$(XPL_)MD5_MBEDTLS) += md5.o +obj-$(CONFIG_$(XPL_)SHA1_MBEDTLS) += sha1.o +obj-$(CONFIG_$(XPL_)SHA256_MBEDTLS) += sha256.o +obj-$(CONFIG_$(XPL_)SHA512_MBEDTLS) += sha512.o # x509 libraries -obj-$(CONFIG_$(SPL_)ASYMMETRIC_PUBLIC_KEY_MBEDTLS) += \ +obj-$(CONFIG_$(XPL_)ASYMMETRIC_PUBLIC_KEY_MBEDTLS) += \ public_key.o -obj-$(CONFIG_$(SPL_)X509_CERTIFICATE_PARSER_MBEDTLS) += \ +obj-$(CONFIG_$(XPL_)X509_CERTIFICATE_PARSER_MBEDTLS) += \ x509_cert_parser.o -obj-$(CONFIG_$(SPL_)PKCS7_MESSAGE_PARSER_MBEDTLS) += pkcs7_parser.o -obj-$(CONFIG_$(SPL_)MSCODE_PARSER_MBEDTLS) += mscode_parser.o -obj-$(CONFIG_$(SPL_)RSA_PUBLIC_KEY_PARSER_MBEDTLS) += rsa_helper.o +obj-$(CONFIG_$(XPL_)PKCS7_MESSAGE_PARSER_MBEDTLS) += pkcs7_parser.o +obj-$(CONFIG_$(XPL_)MSCODE_PARSER_MBEDTLS) += mscode_parser.o +obj-$(CONFIG_$(XPL_)RSA_PUBLIC_KEY_PARSER_MBEDTLS) += rsa_helper.o # MbedTLS crypto library -obj-$(CONFIG_MBEDTLS_LIB) += mbedtls_lib_crypto.o +obj-$(CONFIG_$(XPL_)MBEDTLS_LIB) += mbedtls_lib_crypto.o mbedtls_lib_crypto-y := \ $(MBEDTLS_LIB_DIR)/platform_util.o \ $(MBEDTLS_LIB_DIR)/constant_time.o \ $(MBEDTLS_LIB_DIR)/md.o -mbedtls_lib_crypto-$(CONFIG_$(SPL_)MD5_MBEDTLS) += $(MBEDTLS_LIB_DIR)/md5.o -mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA1_MBEDTLS) += $(MBEDTLS_LIB_DIR)/sha1.o -mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA256_MBEDTLS) += \ +mbedtls_lib_crypto-$(CONFIG_$(XPL_)MD5_MBEDTLS) += $(MBEDTLS_LIB_DIR)/md5.o +mbedtls_lib_crypto-$(CONFIG_$(XPL_)SHA1_MBEDTLS) += $(MBEDTLS_LIB_DIR)/sha1.o +mbedtls_lib_crypto-$(CONFIG_$(XPL_)SHA256_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/sha256.o -mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA512_MBEDTLS) += \ +mbedtls_lib_crypto-$(CONFIG_$(XPL_)SHA512_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/sha512.o -mbedtls_lib_crypto-$(CONFIG_$(SPL_)HKDF_MBEDTLS) += \ +mbedtls_lib_crypto-$(CONFIG_$(XPL_)HKDF_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/hkdf.o # MbedTLS X509 library -obj-$(CONFIG_MBEDTLS_LIB_X509) += mbedtls_lib_x509.o +obj-$(CONFIG_$(XPL_)MBEDTLS_LIB_X509) += mbedtls_lib_x509.o mbedtls_lib_x509-y := $(MBEDTLS_LIB_DIR)/x509.o -mbedtls_lib_x509-$(CONFIG_$(SPL_)ASN1_DECODER_MBEDTLS) += \ +mbedtls_lib_x509-$(CONFIG_$(XPL_)ASN1_DECODER_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/asn1parse.o \ $(MBEDTLS_LIB_DIR)/asn1write.o \ $(MBEDTLS_LIB_DIR)/oid.o -mbedtls_lib_x509-$(CONFIG_$(SPL_)RSA_PUBLIC_KEY_PARSER_MBEDTLS) += \ +mbedtls_lib_x509-$(CONFIG_$(XPL_)RSA_PUBLIC_KEY_PARSER_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/bignum.o \ $(MBEDTLS_LIB_DIR)/bignum_core.o \ $(MBEDTLS_LIB_DIR)/rsa.o \ $(MBEDTLS_LIB_DIR)/rsa_alt_helpers.o -mbedtls_lib_x509-$(CONFIG_$(SPL_)ASYMMETRIC_PUBLIC_KEY_MBEDTLS) += \ +mbedtls_lib_x509-$(CONFIG_$(XPL_)ASYMMETRIC_PUBLIC_KEY_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/pk.o \ $(MBEDTLS_LIB_DIR)/pk_wrap.o \ $(MBEDTLS_LIB_DIR)/pkparse.o -mbedtls_lib_x509-$(CONFIG_$(SPL_)X509_CERTIFICATE_PARSER_MBEDTLS) += \ +mbedtls_lib_x509-$(CONFIG_$(XPL_)X509_CERTIFICATE_PARSER_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/x509_crl.o \ $(MBEDTLS_LIB_DIR)/x509_crt.o -mbedtls_lib_x509-$(CONFIG_$(SPL_)PKCS7_MESSAGE_PARSER_MBEDTLS) += \ +mbedtls_lib_x509-$(CONFIG_$(XPL_)PKCS7_MESSAGE_PARSER_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/pkcs7.o #mbedTLS TLS support -obj-$(CONFIG_MBEDTLS_LIB_TLS) += mbedtls_lib_tls.o +obj-$(CONFIG_$(XPL_)MBEDTLS_LIB_TLS) += mbedtls_lib_tls.o mbedtls_lib_tls-y := \ $(MBEDTLS_LIB_DIR)/mps_reader.o \ $(MBEDTLS_LIB_DIR)/mps_trace.o \ diff --git a/lib/mbedtls/mbedtls_def_config.h b/lib/mbedtls/mbedtls_def_config.h index fd440c392f9..dda3f4dd6e4 100644 --- a/lib/mbedtls/mbedtls_def_config.h +++ b/lib/mbedtls/mbedtls_def_config.h @@ -11,12 +11,12 @@ * Author: Raymond Mao <raymond.mao@linaro.org> */ -#if defined CONFIG_MBEDTLS_LIB +#if CONFIG_IS_ENABLED(MBEDTLS_LIB) #if CONFIG_IS_ENABLED(MD5) #define MBEDTLS_MD_C #define MBEDTLS_MD5_C -#if defined CONFIG_MBEDTLS_LIB_CRYPTO_ALT +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_HASHING_ALT) #define MBEDTLS_MD5_ALT #endif #endif @@ -24,7 +24,7 @@ #if CONFIG_IS_ENABLED(SHA1) #define MBEDTLS_MD_C #define MBEDTLS_SHA1_C -#if defined CONFIG_MBEDTLS_LIB_CRYPTO_ALT +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_HASHING_ALT) #define MBEDTLS_SHA1_ALT #endif #endif @@ -32,7 +32,7 @@ #if CONFIG_IS_ENABLED(SHA256) #define MBEDTLS_MD_C #define MBEDTLS_SHA256_C -#if defined CONFIG_MBEDTLS_LIB_CRYPTO_ALT +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_HASHING_ALT) #define MBEDTLS_SHA256_ALT #endif #if CONFIG_IS_ENABLED(SHA256_SMALLER) @@ -48,7 +48,7 @@ #if CONFIG_IS_ENABLED(SHA512) #define MBEDTLS_MD_C #define MBEDTLS_SHA512_C -#if defined CONFIG_MBEDTLS_LIB_CRYPTO_ALT +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_HASHING_ALT) #define MBEDTLS_SHA512_ALT #endif #if CONFIG_IS_ENABLED(SHA512_SMALLER) @@ -60,7 +60,7 @@ #define MBEDTLS_HKDF_C #endif -#if defined CONFIG_MBEDTLS_LIB_X509 +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_X509) #if CONFIG_IS_ENABLED(X509_CERTIFICATE_PARSER) #define MBEDTLS_X509_USE_C @@ -89,9 +89,9 @@ #define MBEDTLS_ASN1_WRITE_C #endif -#endif /* #if defined CONFIG_MBEDTLS_LIB_X509 */ +#endif /* #if CONFIG_IS_ENABLED(MBEDTLS_LIB_X509) */ -#if IS_ENABLED(CONFIG_MBEDTLS_LIB_TLS) +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_TLS) #include "rtc.h" /* Generic options */ @@ -106,25 +106,36 @@ #define MBEDTLS_ENTROPY_C #define MBEDTLS_NO_PLATFORM_ENTROPY #define MBEDTLS_SSL_PROTO_TLS1_2 +#if CONFIG_IS_ENABLED(X509_CERTIFICATE_PARSER) #define MBEDTLS_SSL_SERVER_NAME_INDICATION +#endif #define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED /* RSA */ +#if CONFIG_IS_ENABLED(X509_CERTIFICATE_PARSER) && \ + CONFIG_IS_ENABLED(RSA_PUBLIC_KEY_PARSER) #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED #define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#endif #define MBEDTLS_GCM_C /* ECDSA */ +#if CONFIG_IS_ENABLED(ASN1_DECODER) #define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C #define MBEDTLS_ECDH_C +#endif #define MBEDTLS_ECDSA_DETERMINISTIC #define MBEDTLS_HMAC_DRBG_C -#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + #define MBEDTLS_CAN_ECDH #define MBEDTLS_PK_CAN_ECDSA_SIGN -#define MBEDTLS_ECP_C +#if CONFIG_IS_ENABLED(X509_CERTIFICATE_PARSER) +#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif + #define MBEDTLS_ECP_DP_SECP256K1_ENABLED #define MBEDTLS_ECP_DP_SECP192R1_ENABLED #define MBEDTLS_ECP_DP_SECP224R1_ENABLED @@ -138,6 +149,6 @@ #define MBEDTLS_ECP_DP_BP384R1_ENABLED #define MBEDTLS_ECP_DP_BP512R1_ENABLED -#endif /* #if defined CONFIG_MBEDTLS_LIB_TLS */ +#endif /* #if CONFIG_IS_ENABLED(MBEDTLS_LIB_TLS) */ -#endif /* #if defined CONFIG_MBEDTLS_LIB */ +#endif /* #if CONFIG_IS_ENABLED(MBEDTLS_LIB) */ diff --git a/lib/mbedtls/port/mbedtls_options.h b/lib/mbedtls/port/mbedtls_options.h new file mode 100644 index 00000000000..885ed6990b6 --- /dev/null +++ b/lib/mbedtls/port/mbedtls_options.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Internal build options for MbedTLS + * + * Copyright (c) 2025 Linaro Limited + * Author: Raymond Mao <raymond.mao@linaro.org> + */ + +#ifndef _MBEDTLS_OPT_H +#define _MBEDTLS_OPT_H + +/* + * FIXME: + * U-Boot/MbedTLS port requires to access a few of members which are defined + * as private in MbedTLS context. + * E.g: x509_internal.h, mbedtls_sha256_context and mbedtls_sha1_context. + * MBEDTLS_ALLOW_PRIVATE_ACCESS needs to be enabled to allow the external + * access, but directly including <external/mbedtls/library/common.h> is not + * allowed, since this will include <malloc.h> and break the sandbox test. + */ +#define MBEDTLS_ALLOW_PRIVATE_ACCESS + +#endif /* _MBEDTLS_OPT_H */ diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index d3b4f71d6be..b74aaf86e6d 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -565,6 +565,11 @@ int rsa_verify(struct image_sign_info *info, uint8_t hash[info->crypto->key_len]; int ret; +#ifdef USE_HOSTCC + if (!info->fdt_blob) + return rsa_verify_openssl(info, region, region_count, sig, sig_len); +#endif + /* * Verify that the checksum-length does not exceed the * rsa-signature-length diff --git a/lib/smbios.c b/lib/smbios.c index 78cee8c0c26..7c9701a57f9 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -429,6 +429,8 @@ static int smbios_write_type1(ulong *current, int handle, struct smbios_type1 *t; int len = sizeof(*t); char *serial_str = env_get("serial#"); + size_t uuid_len; + void *uuid; t = map_sysmem(*current, len); memset(t, 0, len); @@ -450,6 +452,10 @@ static int smbios_write_type1(ulong *current, int handle, SYSID_SM_SYSTEM_SERIAL, NULL); } + if (!sysinfo_get_data(ctx->dev, SYSID_SM_SYSTEM_UUID, &uuid, + &uuid_len) && + uuid_len == sizeof(t->uuid)) + memcpy(t->uuid, uuid, sizeof(t->uuid)); t->wakeup_type = smbios_get_val_si(ctx, "wakeup-type", SYSID_SM_SYSTEM_WAKEUP, SMBIOS_WAKEUP_TYPE_UNKNOWN); diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index 0503c17341f..faf55d7f327 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -211,6 +211,7 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) bool lz = false; int width = 0; bool islong = false; + bool force_char = false; ch = *(fmt++); if (ch == '-') @@ -300,6 +301,8 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) break; case 'c': out(info, (char)(va_arg(va, int))); + /* For the case when it's \0 char */ + force_char = true; break; case 's': p = va_arg(va, char*); @@ -317,8 +320,10 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) while (width-- > 0) info->putc(info, lz ? '0' : ' '); if (p) { - while ((ch = *p++)) + while ((ch = *p++) || force_char) { info->putc(info, ch); + force_char = false; + } } } } diff --git a/net/eth_common.c b/net/eth_common.c index 89b5bb37189..ba57d836b0b 100644 --- a/net/eth_common.c +++ b/net/eth_common.c @@ -31,11 +31,6 @@ int eth_env_set_enetaddr_by_index(const char *base_name, int index, void eth_common_init(void) { bootstage_mark(BOOTSTAGE_ID_NET_ETH_START); -#if CONFIG_IS_ENABLED(ETH) -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) - miiphy_init(); -#endif -#endif } int eth_mac_skip(int index) diff --git a/net/lwip/Kconfig b/net/lwip/Kconfig index 40345ced9c9..d28a8a7df94 100644 --- a/net/lwip/Kconfig +++ b/net/lwip/Kconfig @@ -10,6 +10,12 @@ config LWIP_DEBUG Prints messages to the console regarding network packets that go in and out of the lwIP library. +config LWIP_DEBUG_RXTX + bool "Dump packets sent and received by lwIP" + help + Performs an hexadecimal & ASCII dump of the data received and sent by + the lwIP network stack. + config LWIP_ASSERT bool "Enable assertions in the lwIP library" help diff --git a/net/lwip/Makefile b/net/lwip/Makefile index 79dd6b3fb50..950c5316bb9 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -6,3 +6,9 @@ obj-$(CONFIG_CMD_DNS) += dns.o obj-$(CONFIG_CMD_PING) += ping.o obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o obj-$(CONFIG_WGET) += wget.o + +ifeq (y,$(CONFIG_WGET_BUILTIN_CACERT)) +$(obj)/builtin_cacert.c: $(CONFIG_WGET_BUILTIN_CACERT_PATH:"%"=%) FORCE + $(call if_changed,bin2c,builtin_cacert) +obj-y += builtin_cacert.o +endif diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c index cab1dd7d483..c00a7fe97cd 100644 --- a/net/lwip/net-lwip.c +++ b/net/lwip/net-lwip.c @@ -5,6 +5,7 @@ #include <command.h> #include <dm/device.h> #include <dm/uclass.h> +#include <hexdump.h> #include <lwip/ip4_addr.h> #include <lwip/err.h> #include <lwip/netif.h> @@ -30,12 +31,18 @@ char *pxelinux_configfile; struct in_addr net_ip; char net_boot_file_name[1024]; -static err_t linkoutput(struct netif *netif, struct pbuf *p) +static err_t net_lwip_tx(struct netif *netif, struct pbuf *p) { struct udevice *udev = netif->state; void *pp = NULL; int err; + if (CONFIG_IS_ENABLED(LWIP_DEBUG_RXTX)) { + printf("net_lwip_tx: %u bytes, udev %s\n", p->len, udev->name); + print_hex_dump("net_lwip_tx: ", 0, 16, 1, p->payload, p->len, + true); + } + if ((unsigned long)p->payload % PKTALIGN) { /* * Some net drivers have strict alignment requirements and may @@ -60,7 +67,7 @@ static err_t linkoutput(struct netif *netif, struct pbuf *p) static err_t net_lwip_if_init(struct netif *netif) { netif->output = etharp_output; - netif->linkoutput = linkoutput; + netif->linkoutput = net_lwip_tx; netif->mtu = 1500; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; @@ -265,6 +272,13 @@ int net_lwip_rx(struct udevice *udev, struct netif *netif) flags = 0; if (len > 0) { + if (CONFIG_IS_ENABLED(LWIP_DEBUG_RXTX)) { + printf("net_lwip_tx: %u bytes, udev %s \n", len, + udev->name); + print_hex_dump("net_lwip_rx: ", 0, 16, 1, + packet, len, true); + } + pbuf = alloc_pbuf_and_copy(packet, len); if (pbuf) netif->input(pbuf, netif); diff --git a/net/lwip/wget.c b/net/lwip/wget.c index 14f27d42998..ec098148835 100644 --- a/net/lwip/wget.c +++ b/net/lwip/wget.c @@ -285,9 +285,96 @@ static err_t httpc_headers_done_cb(httpc_state_t *connection, void *arg, struct return ERR_OK; } +#if CONFIG_IS_ENABLED(WGET_HTTPS) +enum auth_mode { + AUTH_NONE, + AUTH_OPTIONAL, + AUTH_REQUIRED, +}; + +static char *cacert; +static size_t cacert_size; +static enum auth_mode cacert_auth_mode = AUTH_OPTIONAL; +#endif + +#if CONFIG_IS_ENABLED(WGET_CACERT) +static int set_auth(enum auth_mode auth) +{ + cacert_auth_mode = auth; + + return CMD_RET_SUCCESS; +} +#endif + +#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) +extern const char builtin_cacert[]; +extern const size_t builtin_cacert_size; +static bool cacert_initialized; +#endif + +#if CONFIG_IS_ENABLED(WGET_CACERT) || CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) +static int _set_cacert(const void *addr, size_t sz) +{ + mbedtls_x509_crt crt; + void *p; + int ret; + + if (cacert) + free(cacert); + + if (!addr) { + cacert = NULL; + cacert_size = 0; + return CMD_RET_SUCCESS; + } + + p = malloc(sz); + if (!p) + return CMD_RET_FAILURE; + cacert = p; + cacert_size = sz; + + memcpy(cacert, (void *)addr, sz); + + mbedtls_x509_crt_init(&crt); + ret = mbedtls_x509_crt_parse(&crt, cacert, cacert_size); + if (ret) { + printf("Could not parse certificates (%d)\n", ret); + free(cacert); + cacert = NULL; + cacert_size = 0; + return CMD_RET_FAILURE; + } + +#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) + cacert_initialized = true; +#endif + return CMD_RET_SUCCESS; +} + +#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) +static int set_cacert_builtin(void) +{ + return _set_cacert(builtin_cacert, builtin_cacert_size); +} +#endif + +#if CONFIG_IS_ENABLED(WGET_CACERT) +static int set_cacert(char * const saddr, char * const ssz) +{ + ulong addr, sz; + + addr = hextoul(saddr, NULL); + sz = hextoul(ssz, NULL); + + return _set_cacert((void *)addr, sz); +} +#endif +#endif /* CONFIG_WGET_CACERT || CONFIG_WGET_BUILTIN_CACERT */ + static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) { -#if defined CONFIG_WGET_HTTPS +#if CONFIG_IS_ENABLED(WGET_HTTPS) altcp_allocator_t tls_allocator; #endif httpc_connection_t conn; @@ -312,11 +399,41 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) return -1; memset(&conn, 0, sizeof(conn)); -#if defined CONFIG_WGET_HTTPS +#if CONFIG_IS_ENABLED(WGET_HTTPS) if (is_https) { + char *ca; + size_t ca_sz; + +#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) + if (!cacert_initialized) + set_cacert_builtin(); +#endif + ca = cacert; + ca_sz = cacert_size; + + if (cacert_auth_mode == AUTH_REQUIRED) { + if (!ca || !ca_sz) { + printf("Error: cacert authentication mode is " + "'required' but no CA certificates " + "given\n"); + return CMD_RET_FAILURE; + } + } else if (cacert_auth_mode == AUTH_NONE) { + ca = NULL; + ca_sz = 0; + } else if (cacert_auth_mode == AUTH_OPTIONAL) { + /* + * Nothing to do, this is the default behavior of + * altcp_tls to check server certificates against CA + * certificates when the latter are provided and proceed + * with no verification if not. + */ + } + tls_allocator.alloc = &altcp_tls_alloc; tls_allocator.arg = - altcp_tls_create_config_client(NULL, 0, ctx.server_name); + altcp_tls_create_config_client(ca, ca_sz, + ctx.server_name); if (!tls_allocator.arg) { log_err("error: Cannot create a TLS connection\n"); @@ -369,6 +486,24 @@ int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) ulong dst_addr; char nurl[1024]; +#if CONFIG_IS_ENABLED(WGET_CACERT) + if (argc == 4 && !strncmp(argv[1], "cacert", strlen("cacert"))) + return set_cacert(argv[2], argv[3]); + if (argc == 3 && !strncmp(argv[1], "cacert", strlen("cacert"))) { +#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) + if (!strncmp(argv[2], "builtin", strlen("builtin"))) + return set_cacert_builtin(); +#endif + if (!strncmp(argv[2], "none", strlen("none"))) + return set_auth(AUTH_NONE); + if (!strncmp(argv[2], "optional", strlen("optional"))) + return set_auth(AUTH_OPTIONAL); + if (!strncmp(argv[2], "required", strlen("required"))) + return set_auth(AUTH_REQUIRED); + return CMD_RET_USAGE; + } +#endif + if (argc < 2 || argc > 3) return CMD_RET_USAGE; diff --git a/net/wget.c b/net/wget.c index 0b082c61947..c73836cbc9d 100644 --- a/net/wget.c +++ b/net/wget.c @@ -53,6 +53,9 @@ static inline int store_block(uchar *src, unsigned int offset, unsigned int len) ulong store_addr = image_load_addr + offset; uchar *ptr; + // Avoid overflow + if (wget_info->buffer_size && wget_info->buffer_size < offset + len) + return -1; if (CONFIG_IS_ENABLED(LMB) && wget_info->set_bootdev) { if (store_addr < image_load_addr || lmb_read_check(store_addr, len)) { @@ -98,12 +101,6 @@ static void tcp_stream_on_closed(struct tcp_stream *tcp) net_set_state(wget_loop_state); if (wget_loop_state != NETLOOP_SUCCESS) { net_boot_file_size = 0; - if (wget_info->status_code == HTTP_STATUS_OK) { - wget_info->status_code = HTTP_STATUS_BAD; - wget_info->hdr_cont_len = 0; - if (wget_info->headers) - wget_info->headers[0] = 0; - } printf("\nwget: Transfer Fail, TCP status - %d\n", tcp->status); return; } @@ -212,6 +209,11 @@ static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes) "wget: Connected Len %lu\n", content_length); wget_info->hdr_cont_len = content_length; + if (wget_info->buffer_size && wget_info->buffer_size < wget_info->hdr_cont_len){ + tcp_stream_reset(tcp); + goto end; + } + } net_boot_file_size = rx_bytes - http_hdr_size; @@ -227,7 +229,9 @@ static int tcp_stream_rx(struct tcp_stream *tcp, u32 rx_offs, void *buf, int len if ((max_rx_pos == (u32)(-1)) || (max_rx_pos < rx_offs + len - 1)) max_rx_pos = rx_offs + len - 1; - store_block(buf, rx_offs - http_hdr_size, len); + // Avoid overflow + if (store_block(buf, rx_offs - http_hdr_size, len) < 0) + return -1; return len; } diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index b8eb57f38c7..f9f8891c0c4 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -7205,8 +7205,8 @@ sub process { # check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too) if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) { - WARN("IS_ENABLED_CONFIG", - "IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr); + ERROR("IS_ENABLED_CONFIG", + "IS_ENABLED($1) must be used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr); } # check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE diff --git a/test/dm/Makefile b/test/dm/Makefile index e44f3d89e77..3afcc26ca57 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_SOUND) += i2s.o obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o obj-$(CONFIG_IOMMU) += iommu.o obj-$(CONFIG_LED) += led.o +obj-$(CONFIG_VIDEO_BRIDGE_LVDS_CODEC) += video_bridge.o obj-$(CONFIG_DM_MAILBOX) += mailbox.o obj-$(CONFIG_DM_MDIO) += mdio.o obj-$(CONFIG_DM_MDIO_MUX) += mdio_mux.o diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index cc8b444ff9a..0f60c2a6281 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -23,6 +23,7 @@ #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/of_extra.h> +#include <dm/ofnode_graph.h> #include <dm/root.h> #include <dm/test.h> #include <dm/uclass-internal.h> @@ -1651,3 +1652,56 @@ static int dm_test_bool(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_bool, UTF_SCAN_FDT); + +/* test all helpers found in drivers/core/ofnode_graph.c */ +static int dm_test_ofnode_graph(struct unit_test_state *uts) +{ + /* 3 ports with 5 endpoints (2-1-2) */ + ofnode graph1 = ofnode_path("/graph1"); + /* 1 port with 1 endpoint */ + ofnode graph2 = ofnode_path("/graph2"); + ofnode node; + u32 id; + + ut_asserteq(ofnode_graph_get_endpoint_count(graph1), 5); + ut_asserteq(ofnode_graph_get_endpoint_count(graph2), 1); + + ut_asserteq(ofnode_graph_get_port_count(graph1), 3); + ut_asserteq(ofnode_graph_get_port_count(graph2), 1); + + /* Request port with reg 2 */ + node = ofnode_graph_get_port_by_id(graph1, 2); + ofnode_read_u32(node, "reg", &id); + ut_asserteq(id, 2); + + /* Reqest parent from prev requested endpoint */ + node = ofnode_graph_get_port_parent(node); + ut_asserteq_str(ofnode_get_name(node), "graph1"); + + /* Request endpoint under port 1 */ + node = ofnode_graph_get_endpoint_by_regs(graph1, 1, -1); + ut_assert(ofnode_has_property(node, "test-property-0")); + + /* Reqest remote endpoint from graph2 in graph1 */ + node = ofnode_graph_get_endpoint_by_regs(graph2, -1, -1); + node = ofnode_graph_get_remote_endpoint(node); + ut_assert(ofnode_has_property(node, "test-property-1")); + + /* Reqest remote parent from graph2 linked endpoint */ + node = ofnode_graph_get_endpoint_by_regs(graph2, -1, -1); + node = ofnode_graph_get_remote_port_parent(node); + ut_asserteq_str(ofnode_get_name(node), "graph1"); + + /* Reqest remote port from graph2 linked endpoint */ + node = ofnode_graph_get_endpoint_by_regs(graph2, -1, -1); + node = ofnode_graph_get_remote_port(node); + ofnode_read_u32(node, "reg", &id); + ut_asserteq(id, 2); + + /* Reqest remote parent from graph2 linked endpoint */ + node = ofnode_graph_get_remote_node(graph2, -1, -1); + ut_asserteq_str(ofnode_get_name(node), "graph1"); + + return 0; +} +DM_TEST(dm_test_ofnode_graph, UTF_SCAN_FDT); diff --git a/test/dm/video_bridge.c b/test/dm/video_bridge.c new file mode 100644 index 00000000000..f55a333c0b8 --- /dev/null +++ b/test/dm/video_bridge.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for video bridge uclass + * + * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <backlight.h> +#include <dm.h> +#include <panel.h> +#include <video.h> +#include <video_bridge.h> +#include <asm/gpio.h> +#include <asm/test.h> +#include <dm/test.h> +#include <power/regulator.h> +#include <test/test.h> +#include <test/ut.h> + +/* Basic test of the video uclass, test is based on driven panel */ +static int dm_test_video_bridge(struct unit_test_state *uts) +{ + struct udevice *dev, *pwm, *gpio, *reg; + uint period_ns, duty_ns; + bool enable, polarity; + struct display_timing timing; + + ut_assertok(uclass_first_device_err(UCLASS_VIDEO_BRIDGE, &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_PWM, "pwm", &pwm)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio)); + ut_assertok(regulator_get_by_platname("VDD_EMMC_1.8V", ®)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(false, enable); + ut_asserteq(true, regulator_get_enable(reg)); + + /* bridge calls panel_enable_backlight() of panel */ + ut_assertok(video_bridge_attach(dev)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(1000, period_ns); + ut_asserteq(170 * 1000 / 255, duty_ns); + ut_asserteq(true, enable); + ut_asserteq(false, polarity); + ut_asserteq(1, sandbox_gpio_get_value(gpio, 1)); + ut_asserteq(true, regulator_get_enable(reg)); + + /* bridge calls panel_set_backlight() of panel */ + ut_assertok(video_bridge_set_backlight(dev, BACKLIGHT_DEFAULT)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(true, enable); + ut_asserteq(170 * 1000 / 255, duty_ns); + + /* bridge should be active */ + ut_assertok(video_bridge_set_active(dev, true)); + + /* bridge is internal and has no hotplug gpio */ + ut_asserteq(-ENOENT, video_bridge_check_attached(dev)); + + /* check passing timings and EDID */ + ut_assertok(video_bridge_get_display_timing(dev, &timing)); + ut_assertok(video_bridge_read_edid(dev, NULL, 0)); + + return 0; +} +DM_TEST(dm_test_video_bridge, UTF_SCAN_PDATA | UTF_SCAN_FDT); diff --git a/test/lib/kconfig.c b/test/lib/kconfig.c index a3645abf946..2f47af9acf1 100644 --- a/test/lib/kconfig.c +++ b/test/lib/kconfig.c @@ -22,10 +22,10 @@ static int lib_test_is_enabled(struct unit_test_state *uts) ut_asserteq(0, CONFIG_IS_ENABLED(_UNDEFINED)); if (IS_ENABLED(CONFIG_BLOBLIST)) { - ut_asserteq(0xb000, IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, - CONFIG_BLOBLIST_ADDR)); - ut_asserteq(0xb000, CONFIG_IF_ENABLED_INT(BLOBLIST_FIXED, - BLOBLIST_ADDR)); + ut_asserteq(0x100, IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, + CONFIG_BLOBLIST_ADDR)); + ut_asserteq(0x100, CONFIG_IF_ENABLED_INT(BLOBLIST_FIXED, + BLOBLIST_ADDR)); } /* diff --git a/test/lib/longjmp.c b/test/lib/longjmp.c index 79d889bdd5f..74c3465b8c2 100644 --- a/test/lib/longjmp.c +++ b/test/lib/longjmp.c @@ -5,10 +5,10 @@ * Copyright (c) 2021, Heinrich Schuchardt <xypron.glpk@gmx.de> */ +#include <setjmp.h> #include <test/lib.h> #include <test/test.h> #include <test/ut.h> -#include <asm/setjmp.h> struct test_jmp_buf { jmp_buf env; diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py index af2adaf1645..7bfcf41ed6f 100644 --- a/test/py/tests/test_fs/conftest.py +++ b/test/py/tests/test_fs/conftest.py @@ -18,6 +18,7 @@ supported_fs_fat = ['fat12', 'fat16'] supported_fs_mkdir = ['fat12', 'fat16', 'fat32'] supported_fs_unlink = ['fat12', 'fat16', 'fat32'] supported_fs_symlink = ['ext4'] +supported_fs_rename = ['fat12', 'fat16', 'fat32'] # # Filesystem test specific setup @@ -55,6 +56,7 @@ def pytest_configure(config): global supported_fs_mkdir global supported_fs_unlink global supported_fs_symlink + global supported_fs_rename def intersect(listA, listB): return [x for x in listA if x in listB] @@ -68,6 +70,7 @@ def pytest_configure(config): supported_fs_mkdir = intersect(supported_fs, supported_fs_mkdir) supported_fs_unlink = intersect(supported_fs, supported_fs_unlink) supported_fs_symlink = intersect(supported_fs, supported_fs_symlink) + supported_fs_rename = intersect(supported_fs, supported_fs_rename) def pytest_generate_tests(metafunc): """Parametrize fixtures, fs_obj_xxx @@ -99,6 +102,9 @@ def pytest_generate_tests(metafunc): if 'fs_obj_symlink' in metafunc.fixturenames: metafunc.parametrize('fs_obj_symlink', supported_fs_symlink, indirect=True, scope='module') + if 'fs_obj_rename' in metafunc.fixturenames: + metafunc.parametrize('fs_obj_rename', supported_fs_rename, + indirect=True, scope='module') # # Helper functions @@ -528,6 +534,121 @@ def fs_obj_symlink(request, u_boot_config): call('rm -f %s' % fs_img, shell=True) # +# Fixture for rename test +# +@pytest.fixture() +def fs_obj_rename(request, u_boot_config): + """Set up a file system to be used in rename tests. + + Args: + request: Pytest request object. + u_boot_config: U-Boot configuration. + + Return: + A fixture for rename tests, i.e. a triplet of file system type, + volume file name, and dictionary of test identifier and md5val. + """ + def new_rand_file(path): + check_call('dd if=/dev/urandom of=%s bs=1K count=1' % path, shell=True) + + def file_hash(path): + out = check_output( + 'dd if=%s bs=1K skip=0 count=1 2> /dev/null | md5sum' % path, + shell=True + ) + return out.decode().split()[0] + + fs_type = request.param + fs_img = '' + + fs_ubtype = fstype_to_ubname(fs_type) + check_ubconfig(u_boot_config, fs_ubtype) + + mount_dir = u_boot_config.persistent_data_dir + '/scratch' + + try: + check_call('mkdir -p %s' % mount_dir, shell=True) + except CalledProcessError as err: + pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err)) + call('rm -f %s' % fs_img, shell=True) + return + + try: + md5val = {} + # Test Case 1 + check_call('mkdir %s/test1' % mount_dir, shell=True) + new_rand_file('%s/test1/file1' % mount_dir) + md5val['test1'] = file_hash('%s/test1/file1' % mount_dir) + + # Test Case 2 + check_call('mkdir %s/test2' % mount_dir, shell=True) + new_rand_file('%s/test2/file1' % mount_dir) + new_rand_file('%s/test2/file_exist' % mount_dir) + md5val['test2'] = file_hash('%s/test2/file1' % mount_dir) + + # Test Case 3 + check_call('mkdir -p %s/test3/dir1' % mount_dir, shell=True) + new_rand_file('%s/test3/dir1/file1' % mount_dir) + md5val['test3'] = file_hash('%s/test3/dir1/file1' % mount_dir) + + # Test Case 4 + check_call('mkdir -p %s/test4/dir1' % mount_dir, shell=True) + check_call('mkdir -p %s/test4/dir2/dir1' % mount_dir, shell=True) + new_rand_file('%s/test4/dir1/file1' % mount_dir) + md5val['test4'] = file_hash('%s/test4/dir1/file1' % mount_dir) + + # Test Case 5 + check_call('mkdir -p %s/test5/dir1' % mount_dir, shell=True) + new_rand_file('%s/test5/file2' % mount_dir) + md5val['test5'] = file_hash('%s/test5/file2' % mount_dir) + + # Test Case 6 + check_call('mkdir -p %s/test6/dir2/existing' % mount_dir, shell=True) + new_rand_file('%s/test6/existing' % mount_dir) + md5val['test6'] = file_hash('%s/test6/existing' % mount_dir) + + # Test Case 7 + check_call('mkdir -p %s/test7/dir1' % mount_dir, shell=True) + check_call('mkdir -p %s/test7/dir2/dir1' % mount_dir, shell=True) + new_rand_file('%s/test7/dir2/dir1/file1' % mount_dir) + md5val['test7'] = file_hash('%s/test7/dir2/dir1/file1' % mount_dir) + + # Test Case 8 + check_call('mkdir -p %s/test8/dir1' % mount_dir, shell=True) + new_rand_file('%s/test8/dir1/file1' % mount_dir) + md5val['test8'] = file_hash('%s/test8/dir1/file1' % mount_dir) + + # Test Case 9 + check_call('mkdir -p %s/test9/dir1/nested/inner' % mount_dir, shell=True) + new_rand_file('%s/test9/dir1/nested/inner/file1' % mount_dir) + + # Test Case 10 + check_call('mkdir -p %s/test10' % mount_dir, shell=True) + new_rand_file('%s/test10/file1' % mount_dir) + md5val['test10'] = file_hash('%s/test10/file1' % mount_dir) + + # Test Case 11 + check_call('mkdir -p %s/test11/dir1' % mount_dir, shell=True) + new_rand_file('%s/test11/dir1/file1' % mount_dir) + md5val['test11'] = file_hash('%s/test11/dir1/file1' % mount_dir) + + try: + # 128MiB volume + fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB', mount_dir) + except CalledProcessError as err: + pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err)) + return + + except CalledProcessError: + pytest.skip('Setup failed for filesystem: ' + fs_type) + return + else: + yield [fs_ubtype, fs_img, md5val] + finally: + call('rm -rf %s' % mount_dir, shell=True) + call('rm -f %s' % fs_img, shell=True) + +# # Fixture for fat test # @pytest.fixture() diff --git a/test/py/tests/test_fs/fstest_helpers.py b/test/py/tests/test_fs/fstest_helpers.py index faec2982489..c1447b4d43e 100644 --- a/test/py/tests/test_fs/fstest_helpers.py +++ b/test/py/tests/test_fs/fstest_helpers.py @@ -9,5 +9,7 @@ def assert_fs_integrity(fs_type, fs_img): try: if fs_type == 'ext4': check_call('fsck.ext4 -n -f %s' % fs_img, shell=True) + elif fs_type in ['fat12', 'fat16', 'fat32']: + check_call('fsck.fat -n %s' % fs_img, shell=True) except CalledProcessError: raise diff --git a/test/py/tests/test_fs/test_rename.py b/test/py/tests/test_fs/test_rename.py new file mode 100644 index 00000000000..df2b2fd2945 --- /dev/null +++ b/test/py/tests/test_fs/test_rename.py @@ -0,0 +1,372 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2025 Gabriel Dalimonte <gabriel.dalimonte@gmail.com> +# +# U-Boot File System:rename Test + + +import pytest + +from fstest_defs import * +from fstest_helpers import assert_fs_integrity + +@pytest.mark.boardspec('sandbox') +@pytest.mark.slow +class TestRename(object): + def test_rename1(self, u_boot_console, fs_obj_rename): + """ + Test Case 1 - rename a file (successful mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 1 - rename a file'): + d = 'test1' + src = '%s/file1' % d + dst = '%s/file2' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, dst), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'load host 0:0 %x /%s' % (ADDR, dst), + 'printenv filesize']) + assert('filesize=400' in output) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (d), + ]) + assert('file1' not in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(md5val['test1'] in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) + + def test_rename2(self, u_boot_console, fs_obj_rename): + """ + Test Case 2 - rename a file to an existing file (successful mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 2 - rename a file to an existing file'): + d = 'test2' + src = '%s/file1' % d + dst = '%s/file_exist' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, dst), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'load host 0:0 %x /%s' % (ADDR, dst), + 'printenv filesize']) + assert('filesize=400' in output) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (d), + ]) + assert('file1' not in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(md5val['test2'] in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) + + def test_rename3(self, u_boot_console, fs_obj_rename): + """ + Test Case 3 - rename a directory (successful mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 3 - rename a directory'): + d = 'test3' + src = '%s/dir1' % d + dst = '%s/dir2' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, dst), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'load host 0:0 %x /%s/file1' % (ADDR, dst), + 'printenv filesize']) + assert('filesize=400' in output) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (d), + ]) + assert('dir1' not in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(md5val['test3'] in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) + + def test_rename4(self, u_boot_console, fs_obj_rename): + """ + Test Case 4 - rename a directory to an existing directory (successful + mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 4 - rename a directory to an existing directory'): + d = 'test4' + src = '%s/dir1' % d + dst = '%s/dir2' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, dst), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'load host 0:0 %x /%s/dir1/file1' % (ADDR, dst), + 'printenv filesize']) + assert('filesize=400' in output) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (d), + ]) + assert('dir1' not in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(md5val['test4'] in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) + + def test_rename5(self, u_boot_console, fs_obj_rename): + """ + Test Case 5 - rename a directory to an existing file (failed mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 5 - rename a directory to an existing file'): + d = 'test5' + src = '%s/dir1' % d + dst = '%s/file2' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, dst), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (d), + ]) + assert('dir1' in ''.join(output)) + assert('file2' in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'load host 0:0 %x /%s' % (ADDR, dst), + 'printenv filesize']) + assert('filesize=400' in output) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(md5val['test5'] in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) + + def test_rename6(self, u_boot_console, fs_obj_rename): + """ + Test Case 6 - rename a file to an existing empty directory (failed mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 6 - rename a file to an existing empty directory'): + d = 'test6' + src = '%s/existing' % d + dst = '%s/dir2' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, dst), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'load host 0:0 %x /%s' % (ADDR, src), + 'printenv filesize']) + assert('filesize=400' in output) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (d), + ]) + assert('dir2' in ''.join(output)) + assert('existing' in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(md5val['test6'] in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) + + def test_rename7(self, u_boot_console, fs_obj_rename): + """ + Test Case 7 - rename a directory to a non-empty directory (failed mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 7 - rename a directory to a non-empty directory'): + d = 'test7' + src = '%s/dir1' % d + dst = '%s/dir2' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, dst), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'load host 0:0 %x /%s/dir1/file1' % (ADDR, dst), + 'printenv filesize']) + assert('filesize=400' in output) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (d), + ]) + assert('dir1' in ''.join(output)) + assert('dir2' in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(md5val['test7'] in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) + + def test_rename8(self, u_boot_console, fs_obj_rename): + """ + Test Case 8 - rename a directory inside itself (failed mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 8 - rename a directory inside itself'): + d = 'test8' + src = '%s/dir1' % d + dst = '%s/dir1/dir1' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, dst), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'load host 0:0 %x /%s/file1' % (ADDR, src), + 'printenv filesize']) + assert('filesize=400' in output) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (d), + ]) + assert('dir1' in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (src), + ]) + assert('file1' in ''.join(output)) + assert('dir1' not in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(md5val['test8'] in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) + + def test_rename9(self, u_boot_console, fs_obj_rename): + """ + Test Case 9 - rename a directory inside itself with backtracks (failed + mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 9 - rename a directory inside itself with backtracks'): + d = 'test9' + src = '%s/dir1/nested' % d + dst = '%s/dir1/nested/inner/./../../../dir1/nested/inner/another' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, dst), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s/dir1' % (d), + ]) + assert('nested' in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (src), + ]) + assert('inner' in ''.join(output)) + assert('nested' not in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) + + def test_rename10(self, u_boot_console, fs_obj_rename): + """ + Test Case 10 - rename a file to itself (successful mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 10 - rename a file to itself'): + d = 'test10' + src = '%s/file1' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, src), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'load host 0:0 %x /%s' % (ADDR, src), + 'printenv filesize']) + assert('filesize=400' in output) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (d), + ]) + assert('file1' in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(md5val['test10'] in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) + + def test_rename11(self, u_boot_console, fs_obj_rename): + """ + Test Case 11 - rename a directory to itself (successful mv) + """ + fs_type, fs_img, md5val = fs_obj_rename + with u_boot_console.log.section('Test Case 11 - rename a directory to itself'): + # / at the end here is intentional. Ensures trailing / doesn't + # affect mv producing an updated dst path for fs_rename + d = 'test11/' + src = '%sdir1' % d + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % fs_img, + 'setenv filesize', + 'mv host 0:0 %s %s' % (src, d), + ]) + assert('' == ''.join(output)) + + output = u_boot_console.run_command_list([ + 'load host 0:0 %x /%s/file1' % (ADDR, src), + 'printenv filesize']) + assert('filesize=400' in output) + + output = u_boot_console.run_command_list([ + 'ls host 0:0 %s' % (d), + ]) + assert('dir1' in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'md5sum %x $filesize' % ADDR, + 'setenv filesize']) + assert(md5val['test11'] in ''.join(output)) + assert_fs_integrity(fs_type, fs_img) diff --git a/tools/.gitignore b/tools/.gitignore index 0108c567309..6a5c613f772 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -29,6 +29,7 @@ /mxsboot /ncb /prelink-riscv +/preload_check_sign /printinitialenv /proftool /relocate-rela diff --git a/tools/Kconfig b/tools/Kconfig index 01ff0fcf748..8e272ee99a8 100644 --- a/tools/Kconfig +++ b/tools/Kconfig @@ -9,6 +9,11 @@ config MKIMAGE_DTC_PATH some cases the system dtc may not support all required features and the path to a different version should be given here. +config TOOLS_IMAGE_PRE_LOAD + def_bool y + help + Enable pre-load signature support in the tools builds. + config TOOLS_CRC16 def_bool y help diff --git a/tools/Makefile b/tools/Makefile index 237fa900a24..e5f5eea47c7 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -66,6 +66,7 @@ mkenvimage-objs := mkenvimage.o os_support.o generated/lib/crc32.o hostprogs-y += dumpimage mkimage hostprogs-$(CONFIG_TOOLS_LIBCRYPTO) += fit_info fit_check_sign hostprogs-$(CONFIG_TOOLS_LIBCRYPTO) += fdt_add_pubkey +hostprogs-$(CONFIG_TOOLS_LIBCRYPTO) += preload_check_sign ifneq ($(CONFIG_CMD_BOOTEFI_SELFTEST)$(CONFIG_FWU_MDATA_GPT_BLK),) hostprogs-y += file2include @@ -89,6 +90,8 @@ ECDSA_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := $(addprefix generated/lib/ecdsa/, ecdsa- AES_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := $(addprefix generated/lib/aes/, \ aes-encrypt.o aes-decrypt.o) +PRELOAD_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := generated/boot/image-pre-load.o + # Cryptographic helpers and image types that depend on openssl/libcrypto LIBCRYPTO_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := \ generated/lib/fdt-libcrypto.o \ @@ -158,6 +161,7 @@ fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o fdt_add_pubkey-objs := $(dumpimage-mkimage-objs) fdt_add_pubkey.o file2include-objs := file2include.o +preload_check_sign-objs := $(dumpimage-mkimage-objs) $(PRELOAD_OBJS-y) preload_check_sign.o ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_TOOLS_LIBCRYPTO),) # Add CFG_MXS into host CFLAGS, so we can check whether or not register @@ -195,6 +199,7 @@ HOSTLDLIBS_dumpimage := $(HOSTLDLIBS_mkimage) HOSTLDLIBS_fit_info := $(HOSTLDLIBS_mkimage) HOSTLDLIBS_fit_check_sign := $(HOSTLDLIBS_mkimage) HOSTLDLIBS_fdt_add_pubkey := $(HOSTLDLIBS_mkimage) +HOSTLDLIBS_preload_check_sign := $(HOSTLDLIBS_mkimage) hostprogs-$(CONFIG_EXYNOS5250) += mkexynosspl hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst index 990fc295770..84b1331df5c 100644 --- a/tools/binman/binman.rst +++ b/tools/binman/binman.rst @@ -823,24 +823,6 @@ multiple-images: }; }; -end-at-4gb: - For x86 machines the ROM offsets start just before 4GB and extend - up so that the image finished at the 4GB boundary. This boolean - option can be enabled to support this. The image size must be - provided so that binman knows when the image should start. For an - 8MB ROM, the offset of the first entry would be 0xfff80000 with - this option, instead of 0 without this option. - -skip-at-start: - This property specifies the entry offset of the first entry. - - For PowerPC mpc85xx based CPU, CONFIG_TEXT_BASE is the entry - offset of the first entry. It can be 0xeff40000 or 0xfff40000 for - nor flash boot, 0x201000 for sd boot etc. - - 'end-at-4gb' property is not applicable where CONFIG_TEXT_BASE + - Image size != 4gb. - align-default: Specifies the default alignment for entries in this section if they do not specify an alignment. Note that this only applies to top-level entries @@ -957,6 +939,35 @@ filename: section in different image, since there is currently no way to share data between images other than through files. +end-at-4gb: + For x86 machines the ROM offsets start just before 4GB and extend + up so that the image finished at the 4GB boundary. This boolean + option can be enabled to support this. The image size must be + provided so that binman knows when the image should start. For an + 8MB ROM, the offset of the first entry would be 0xfff80000 with + this option, instead of 0 without this option. + +skip-at-start: + This property specifies the entry offset of the first entry in the section. + It is useful when the Binman image is written to a particular offset in the + media. It allows the offset of the first entry to be the media offset, even + though it is at the start of the image. It effectively creates a hole at the + start of the image, an implied, empty area. + + For example, if the image is written to offset 4K on the media, set + skip-at-start to 0x1000. At runtime, the Binman image will assume that it + has be written at offset 4K and all symbols and offsets will take account of + that. The image-pos values will also be adjusted. The effect is similar to + adding an empty 4K region at the start, except that Binman does not actually + output it. + + For PowerPC mpc85xx based CPU, CONFIG_TEXT_BASE is the entry + offset of the first entry. It can be 0xeff40000 or 0xfff40000 for + nor flash boot, 0x201000 for sd boot etc. + + 'end-at-4gb' property is not applicable where CONFIG_TEXT_BASE + + Image size != 4gb. + Image Properties ---------------- diff --git a/tools/binman/bintool.py b/tools/binman/bintool.py index 3c4ad1adbb9..81872db377f 100644 --- a/tools/binman/bintool.py +++ b/tools/binman/bintool.py @@ -328,7 +328,8 @@ class Bintool: return result.stdout @classmethod - def build_from_git(cls, git_repo, make_targets, bintool_path, flags=None): + def build_from_git(cls, git_repo, make_targets, bintool_path, + flags=None, git_branch=None, make_path=None): """Build a bintool from a git repo This clones the repo in a temporary directory, builds it with 'make', @@ -341,6 +342,9 @@ class Bintool: bintool_path (str): Relative path of the tool in the repo, after build is complete flags (list of str): Flags or variables to pass to make, or None + git_branch (str): Branch of git repo, or None to use the default + make_path (str): Relative path inside git repo containing the + Makefile, or None Returns: tuple: @@ -350,10 +354,17 @@ class Bintool: """ tmpdir = tempfile.mkdtemp(prefix='binmanf.') print(f"- clone git repo '{git_repo}' to '{tmpdir}'") - tools.run('git', 'clone', '--depth', '1', git_repo, tmpdir) + if git_branch: + tools.run('git', 'clone', '--depth', '1', '--branch', git_branch, + git_repo, tmpdir) + else: + tools.run('git', 'clone', '--depth', '1', git_repo, tmpdir) for target in make_targets: print(f"- build target '{target}'") - cmd = ['make', '-C', tmpdir, '-j', f'{multiprocessing.cpu_count()}', + makedir = tmpdir + if make_path: + makedir = os.path.join(tmpdir, make_path) + cmd = ['make', '-C', makedir, '-j', f'{multiprocessing.cpu_count()}', target] if flags: cmd += flags diff --git a/tools/binman/bintool_test.py b/tools/binman/bintool_test.py index f9b16d4c73b..949d6f4c8a9 100644 --- a/tools/binman/bintool_test.py +++ b/tools/binman/bintool_test.py @@ -303,6 +303,7 @@ class TestBintool(unittest.TestCase): # See Bintool.build_from_git() tmpdir = cmd[2] self.fname = os.path.join(tmpdir, 'pathname') + os.makedirs(os.path.dirname(tmpdir), exist_ok=True) tools.write_file(self.fname, b'hello') expected = b'this is a test' diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst index cd05ad8cb26..9f6cab544a5 100644 --- a/tools/binman/bintools.rst +++ b/tools/binman/bintools.rst @@ -52,6 +52,14 @@ Bintool: cst: Image generation for U-Boot This bintool supports running `cst` with some basic parameters as needed by binman. +cst (imx code signing tool) is used for sigining bootloader binaries for +various i.MX SoCs. + +See `Code Signing Tool Users Guide`_ for more information. + +.. _`Code Signing Tool Users Guide`: + https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/imx-processors/202591/1/CST_UG.pdf + Bintool: fdt_add_pubkey: Add public key to control dtb (spl or u-boot proper) diff --git a/tools/binman/btool/cst.py b/tools/binman/btool/cst.py index 30e78bdbbd9..8a3981adc89 100644 --- a/tools/binman/btool/cst.py +++ b/tools/binman/btool/cst.py @@ -12,6 +12,14 @@ class Bintoolcst(bintool.Bintool): This bintool supports running `cst` with some basic parameters as needed by binman. + + cst (imx code signing tool) is used for sigining bootloader binaries for + various i.MX SoCs. + + See `Code Signing Tool Users Guide`_ for more information. + + .. _`Code Signing Tool Users Guide`: + https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/imx-processors/202591/1/CST_UG.pdf """ def __init__(self, name): super().__init__(name, 'Sign NXP i.MX image') @@ -29,20 +37,17 @@ class Bintoolcst(bintool.Bintool): return self.run_cmd(*args) def fetch(self, method): - """Fetch handler for cst - - This installs cst using the apt utility. - - Args: - method (FETCH_...): Method to use - - Returns: - True if the file was fetched and now installed, None if a method - other than FETCH_BIN was requested - - Raises: - Valuerror: Fetching could not be completed - """ - if method != bintool.FETCH_BIN: + """Build cst from git""" + if method != bintool.FETCH_BUILD: return None - return self.apt_install('imx-code-signing-tool') + + from platform import architecture + arch = 'linux64' if architecture()[0] == '64bit' else 'linux32' + result = self.build_from_git( + 'https://gitlab.apertis.org/pkg/imx-code-signing-tool', + ['all'], + f'code/obj.{arch}/cst', + flags=[f'OSTYPE={arch}', 'ENCRYPTION=yes'], + git_branch='debian/unstable', + make_path=f'code/obj.{arch}/') + return result diff --git a/tools/binman/entry.py b/tools/binman/entry.py index 68f8d62bba9..bdc60e47fca 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -392,9 +392,8 @@ class Entry(object): """Set the value of device-tree properties calculated by binman""" state.SetInt(self._node, 'offset', self.offset) state.SetInt(self._node, 'size', self.size) - base = self.section.GetRootSkipAtStart() if self.section else 0 if self.image_pos is not None: - state.SetInt(self._node, 'image-pos', self.image_pos - base) + state.SetInt(self._node, 'image-pos', self.image_pos) if self.GetImage().allow_repack: if self.orig_offset is not None: state.SetInt(self._node, 'orig-offset', self.orig_offset, True) @@ -722,7 +721,7 @@ class Entry(object): is_elf = self.GetDefaultFilename() == self.elf_fname symbols_base = self.symbols_base - if symbols_base is None and self.GetImage()._end_4gb: + if symbols_base is None and self.GetImage()._end_at_4gb: symbols_base = 0 elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage(), diff --git a/tools/binman/etype/fmap.py b/tools/binman/etype/fmap.py index 3669d91a0bc..35ca8490f79 100644 --- a/tools/binman/etype/fmap.py +++ b/tools/binman/etype/fmap.py @@ -65,7 +65,7 @@ class Entry_fmap(Entry): if entry.image_pos is None: pos = 0 else: - pos = entry.image_pos - entry.GetRootSkipAtStart() + pos = entry.image_pos # Drop @ symbols in name name = entry.name.replace('@', '') @@ -75,8 +75,6 @@ class Entry_fmap(Entry): _AddEntries(areas, subentry) else: pos = entry.image_pos - if pos is not None: - pos -= entry.section.GetRootSkipAtStart() areas.append(fmap_util.FmapArea(pos or 0, entry.size or 0, entry.name, flags)) diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index f4f48c00e87..5e11cf58d28 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -165,7 +165,7 @@ class Entry_section(Entry): self._pad_byte = 0 self._sort = False self._skip_at_start = None - self._end_4gb = False + self._end_at_4gb = False self._ignore_missing = False self._filename = None self.align_default = 0 @@ -187,9 +187,9 @@ class Entry_section(Entry): super().ReadNode() self._pad_byte = fdt_util.GetInt(self._node, 'pad-byte', 0) self._sort = fdt_util.GetBool(self._node, 'sort-by-offset') - self._end_4gb = fdt_util.GetBool(self._node, 'end-at-4gb') + self._end_at_4gb = fdt_util.GetBool(self._node, 'end-at-4gb') self._skip_at_start = fdt_util.GetInt(self._node, 'skip-at-start') - if self._end_4gb: + if self._end_at_4gb: if not self.size: self.Raise("Section size must be provided when using end-at-4gb") if self._skip_at_start is not None: @@ -801,7 +801,7 @@ class Entry_section(Entry): if not entry: self._Raise("Unable to set offset/size for unknown entry '%s'" % name) - entry.SetOffsetSize(self._skip_at_start + offset if offset is not None + entry.SetOffsetSize(offset + self._skip_at_start if offset is not None else None, size) def GetEntryOffsets(self): diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index d2802f67e2d..1a92a99b511 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -303,7 +303,7 @@ class TestFunctional(unittest.TestCase): def setUp(self): # Enable this to turn on debugging output # tout.init(tout.DEBUG) - command.test_result = None + command.TEST_RESULT = None def tearDown(self): """Remove the temporary output directory""" @@ -345,8 +345,9 @@ class TestFunctional(unittest.TestCase): Arguments to pass, as a list of strings kwargs: Arguments to pass to Command.RunPipe() """ - result = command.run_pipe([[self._binman_pathname] + list(args)], - capture=True, capture_stderr=True, raise_on_error=False) + all_args = [self._binman_pathname] + list(args) + result = command.run_one(*all_args, capture=True, capture_stderr=True, + raise_on_error=False) if result.return_code and kwargs.get('raise_on_error', True): raise Exception("Error running '%s': %s" % (' '.join(args), result.stdout + result.stderr)) @@ -762,6 +763,16 @@ class TestFunctional(unittest.TestCase): return False return True + def _CheckPreload(self, image, key, algo="sha256,rsa2048", + padding="pkcs-1.5"): + try: + tools.run('preload_check_sign', '-k', key, '-a', algo, '-p', + padding, '-f', image) + except: + self.fail('Expected image signed with a pre-load') + return False + return True + def testRun(self): """Test a basic run with valid args""" result = self._RunBinman('-h') @@ -780,11 +791,11 @@ class TestFunctional(unittest.TestCase): def testFullHelpInternal(self): """Test that the full help is displayed with -H""" try: - command.test_result = command.CommandResult() + command.TEST_RESULT = command.CommandResult() result = self._DoBinman('-H') help_file = os.path.join(self._binman_dir, 'README.rst') finally: - command.test_result = None + command.TEST_RESULT = None def testHelp(self): """Test that the basic help is displayed with -h""" @@ -1872,7 +1883,7 @@ class TestFunctional(unittest.TestCase): def testGbb(self): """Test for the Chromium OS Google Binary Block""" - command.test_result = self._HandleGbbCommand + command.TEST_RESULT = self._HandleGbbCommand entry_args = { 'keydir': 'devkeys', 'bmpblk': 'bmpblk.bin', @@ -1941,7 +1952,7 @@ class TestFunctional(unittest.TestCase): def testVblock(self): """Test for the Chromium OS Verified Boot Block""" self._hash_data = False - command.test_result = self._HandleVblockCommand + command.TEST_RESULT = self._HandleVblockCommand entry_args = { 'keydir': 'devkeys', } @@ -1974,7 +1985,7 @@ class TestFunctional(unittest.TestCase): def testVblockContent(self): """Test that the vblock signs the right data""" self._hash_data = True - command.test_result = self._HandleVblockCommand + command.TEST_RESULT = self._HandleVblockCommand entry_args = { 'keydir': 'devkeys', } @@ -2297,16 +2308,17 @@ class TestFunctional(unittest.TestCase): fhdr, fentries = fmap_util.DecodeFmap(data[32:]) self.assertEqual(0x100, fhdr.image_size) + base = (1 << 32) - 0x100 - self.assertEqual(0, fentries[0].offset) + self.assertEqual(base, fentries[0].offset) self.assertEqual(4, fentries[0].size) self.assertEqual(b'U_BOOT', fentries[0].name) - self.assertEqual(4, fentries[1].offset) + self.assertEqual(base + 4, fentries[1].offset) self.assertEqual(3, fentries[1].size) self.assertEqual(b'INTEL_MRC', fentries[1].name) - self.assertEqual(32, fentries[2].offset) + self.assertEqual(base + 32, fentries[2].offset) self.assertEqual(fmap_util.FMAP_HEADER_LEN + fmap_util.FMAP_AREA_LEN * 3, fentries[2].size) self.assertEqual(b'FMAP', fentries[2].name) @@ -2319,27 +2331,28 @@ class TestFunctional(unittest.TestCase): fhdr, fentries = fmap_util.DecodeFmap(data[36:]) self.assertEqual(0x180, fhdr.image_size) + base = (1 << 32) - 0x180 expect_size = fmap_util.FMAP_HEADER_LEN + fmap_util.FMAP_AREA_LEN * 4 fiter = iter(fentries) fentry = next(fiter) self.assertEqual(b'U_BOOT', fentry.name) - self.assertEqual(0, fentry.offset) + self.assertEqual(base, fentry.offset) self.assertEqual(4, fentry.size) fentry = next(fiter) self.assertEqual(b'SECTION', fentry.name) - self.assertEqual(4, fentry.offset) + self.assertEqual(base + 4, fentry.offset) self.assertEqual(0x20 + expect_size, fentry.size) fentry = next(fiter) self.assertEqual(b'INTEL_MRC', fentry.name) - self.assertEqual(4, fentry.offset) + self.assertEqual(base + 4, fentry.offset) self.assertEqual(3, fentry.size) fentry = next(fiter) self.assertEqual(b'FMAP', fentry.name) - self.assertEqual(36, fentry.offset) + self.assertEqual(base + 36, fentry.offset) self.assertEqual(expect_size, fentry.size) def testElf(self): @@ -3535,8 +3548,8 @@ class TestFunctional(unittest.TestCase): image = control.images['image'] entries = image.GetEntries() desc = entries['intel-descriptor'] - self.assertEqual(0xff800000, desc.offset); - self.assertEqual(0xff800000, desc.image_pos); + self.assertEqual(0xff800000, desc.offset) + self.assertEqual(0xff800000, desc.image_pos) def testReplaceCbfs(self): """Test replacing a single file in CBFS without changing the size""" @@ -3778,8 +3791,8 @@ class TestFunctional(unittest.TestCase): image = control.images['image'] entries = image.GetEntries() - expected_ptr = entries['intel-fit'].image_pos - (1 << 32) - self.assertEqual(expected_ptr, ptr) + expected_ptr = entries['intel-fit'].image_pos #- (1 << 32) + self.assertEqual(expected_ptr, ptr + (1 << 32)) def testPackIntelFitMissing(self): """Test detection of a FIT pointer with not FIT region""" @@ -4773,7 +4786,7 @@ class TestFunctional(unittest.TestCase): entry = image.GetEntries()['fdtmap'] self.assertEqual(orig_entry.offset, entry.offset) self.assertEqual(orig_entry.size, entry.size) - self.assertEqual(16, entry.image_pos) + self.assertEqual((1 << 32) - 0x400 + 16, entry.image_pos) u_boot = image.GetEntries()['section'].GetEntries()['u-boot'] @@ -5496,7 +5509,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testFitSubentryUsesBintool(self): """Test that binman FIT subentries can use bintools""" - command.test_result = self._HandleGbbCommand + command.TEST_RESULT = self._HandleGbbCommand entry_args = { 'keydir': 'devkeys', 'bmpblk': 'bmpblk.bin', @@ -5781,9 +5794,14 @@ fdt fdtmap Extract the devicetree blob from the fdtmap data = self._DoReadFileDtb( '230_pre_load.dts', entry_args=entry_args, extra_indirs=[os.path.join(self._binman_dir, 'test')])[0] + + image_fname = tools.get_output_filename('image.bin') + is_signed = self._CheckPreload(image_fname, self.TestFile("dev.key")) + self.assertEqual(PRE_LOAD_MAGIC, data[:len(PRE_LOAD_MAGIC)]) self.assertEqual(PRE_LOAD_VERSION, data[4:4 + len(PRE_LOAD_VERSION)]) self.assertEqual(PRE_LOAD_HDR_SIZE, data[8:8 + len(PRE_LOAD_HDR_SIZE)]) + self.assertEqual(is_signed, True) def testPreLoadNoKey(self): """Test an image with a pre-load heade0r with missing key""" diff --git a/tools/buildman/boards.py b/tools/buildman/boards.py index e7aa0d85a58..2fe43c3fc89 100644 --- a/tools/buildman/boards.py +++ b/tools/buildman/boards.py @@ -251,9 +251,9 @@ class KconfigScanner: '-undef', '-x', 'assembler-with-cpp', defconfig] - result = command.run_pipe([cmd], capture=True, capture_stderr=True) + stdout = command.output(*cmd, capture_stderr=True) temp = tempfile.NamedTemporaryFile(prefix='buildman-') - tools.write_file(temp.name, result.stdout, False) + tools.write_file(temp.name, stdout, False) fname = temp.name tout.info(f'Processing #include to produce {defconfig}') else: diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index 23b1016d0f9..4bea0a02b78 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -510,7 +510,7 @@ class Builder: stage: Stage that we are at (mrproper, config, oldconfig, build) cwd: Directory where make should be run args: Arguments to pass to make - kwargs: Arguments to pass to command.run_pipe() + kwargs: Arguments to pass to command.run_one() """ def check_output(stream, data): @@ -531,11 +531,12 @@ class Builder: return False self._restarting_config = False - self._terminated = False + self._terminated = False cmd = [self.gnu_make] + list(args) - result = command.run_pipe([cmd], capture=True, capture_stderr=True, - cwd=cwd, raise_on_error=False, infile='/dev/null', - output_func=check_output, **kwargs) + result = command.run_one(*cmd, capture=True, capture_stderr=True, + cwd=cwd, raise_on_error=False, + infile='/dev/null', output_func=check_output, + **kwargs) if self._terminated: # Try to be helpful diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py index 78c95a67095..b8578d5b97b 100644 --- a/tools/buildman/builderthread.py +++ b/tools/buildman/builderthread.py @@ -179,13 +179,12 @@ class BuilderThread(threading.Thread): cwd (str): Working directory to set, or None to leave it alone *args (list of str): Arguments to pass to 'make' **kwargs (dict): A list of keyword arguments to pass to - command.run_pipe() + command.run_one() Returns: CommandResult object """ - return self.builder.do_make(commit, brd, stage, cwd, *args, - **kwargs) + return self.builder.do_make(commit, brd, stage, cwd, *args, **kwargs) def _build_args(self, brd, out_dir, out_rel_dir, work_dir, commit_upto): """Set up arguments to the args list based on the settings @@ -588,9 +587,10 @@ class BuilderThread(threading.Thread): lines = [] for fname in BASE_ELF_FILENAMES: cmd = [f'{self.toolchain.cross}nm', '--size-sort', fname] - nm_result = command.run_pipe([cmd], capture=True, - capture_stderr=True, cwd=result.out_dir, - raise_on_error=False, env=env) + nm_result = command.run_one(*cmd, capture=True, + capture_stderr=True, + cwd=result.out_dir, + raise_on_error=False, env=env) if nm_result.stdout: nm_fname = self.builder.get_func_sizes_file( result.commit_upto, result.brd.target, fname) @@ -598,9 +598,10 @@ class BuilderThread(threading.Thread): print(nm_result.stdout, end=' ', file=outf) cmd = [f'{self.toolchain.cross}objdump', '-h', fname] - dump_result = command.run_pipe([cmd], capture=True, - capture_stderr=True, cwd=result.out_dir, - raise_on_error=False, env=env) + dump_result = command.run_one(*cmd, capture=True, + capture_stderr=True, + cwd=result.out_dir, + raise_on_error=False, env=env) rodata_size = '' if dump_result.stdout: objdump = self.builder.get_objdump_file(result.commit_upto, @@ -613,9 +614,10 @@ class BuilderThread(threading.Thread): rodata_size = fields[2] cmd = [f'{self.toolchain.cross}size', fname] - size_result = command.run_pipe([cmd], capture=True, - capture_stderr=True, cwd=result.out_dir, - raise_on_error=False, env=env) + size_result = command.run_one(*cmd, capture=True, + capture_stderr=True, + cwd=result.out_dir, + raise_on_error=False, env=env) if size_result.stdout: lines.append(size_result.stdout.splitlines()[1] + ' ' + rodata_size) @@ -624,9 +626,8 @@ class BuilderThread(threading.Thread): cmd = [f'{self.toolchain.cross}objcopy', '-O', 'binary', '-j', '.rodata.default_environment', 'env/built-in.o', 'uboot.env'] - command.run_pipe([cmd], capture=True, - capture_stderr=True, cwd=result.out_dir, - raise_on_error=False, env=env) + command.run_one(*cmd, capture=True, capture_stderr=True, + cwd=result.out_dir, raise_on_error=False, env=env) if not work_in_output: copy_files(result.out_dir, build_dir, '', ['uboot.env']) diff --git a/tools/buildman/func_test.py b/tools/buildman/func_test.py index c7c4f506a65..d779040c74e 100644 --- a/tools/buildman/func_test.py +++ b/tools/buildman/func_test.py @@ -187,7 +187,7 @@ class TestFunctional(unittest.TestCase): self._git_dir = os.path.join(self._base_dir, 'src') self._buildman_pathname = sys.argv[0] self._buildman_dir = os.path.dirname(os.path.realpath(sys.argv[0])) - command.test_result = self._HandleCommand + command.TEST_RESULT = self._HandleCommand bsettings.setup(None) bsettings.add_file(settings_data) self.setupToolchains() @@ -232,8 +232,8 @@ class TestFunctional(unittest.TestCase): self._toolchains.Add('gcc', test=False) def _RunBuildman(self, *args): - return command.run_pipe([[self._buildman_pathname] + list(args)], - capture=True, capture_stderr=True) + all_args = [self._buildman_pathname] + list(args) + return command.run_one(*all_args, capture=True, capture_stderr=True) def _RunControl(self, *args, brds=False, clean_dir=False, test_thread_exceptions=False, get_builder=True): @@ -266,7 +266,7 @@ class TestFunctional(unittest.TestCase): return result def testFullHelp(self): - command.test_result = None + command.TEST_RESULT = None result = self._RunBuildman('-H') help_file = os.path.join(self._buildman_dir, 'README.rst') # Remove possible extraneous strings @@ -277,7 +277,7 @@ class TestFunctional(unittest.TestCase): self.assertEqual(0, result.return_code) def testHelp(self): - command.test_result = None + command.TEST_RESULT = None result = self._RunBuildman('-h') help_file = os.path.join(self._buildman_dir, 'README.rst') self.assertTrue(len(result.stdout) > 1000) @@ -286,11 +286,11 @@ class TestFunctional(unittest.TestCase): def testGitSetup(self): """Test gitutils.Setup(), from outside the module itself""" - command.test_result = command.CommandResult(return_code=1) + command.TEST_RESULT = command.CommandResult(return_code=1) gitutil.setup() self.assertEqual(gitutil.use_no_decorate, False) - command.test_result = command.CommandResult(return_code=0) + command.TEST_RESULT = command.CommandResult(return_code=0) gitutil.setup() self.assertEqual(gitutil.use_no_decorate, True) @@ -445,7 +445,7 @@ class TestFunctional(unittest.TestCase): stage: Stage that we are at (mrproper, config, build) cwd: Directory where make should be run args: Arguments to pass to make - kwargs: Arguments to pass to command.run_pipe() + kwargs: Arguments to pass to command.run_one() """ self._make_calls += 1 out_dir = '' diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py index 958f36f9f61..5d051e005da 100644 --- a/tools/buildman/toolchain.py +++ b/tools/buildman/toolchain.py @@ -100,7 +100,7 @@ class Toolchain: else: self.priority = priority if test: - result = command.run_pipe([cmd], capture=True, env=env, + result = command.run_one(*cmd, capture=True, env=env, raise_on_error=False) self.ok = result.return_code == 0 if verbose: diff --git a/tools/image-host.c b/tools/image-host.c index 14e8bd52a65..a9b86902763 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -19,6 +19,11 @@ #include <openssl/evp.h> #endif +#if CONFIG_IS_ENABLED(IMAGE_PRE_LOAD) +#include <openssl/rsa.h> +#include <openssl/err.h> +#endif + /** * fit_set_hash_value - set hash value in requested has node * @fit: pointer to the FIT format image header @@ -1410,3 +1415,139 @@ int fit_check_sign(const void *fit, const void *key, return ret; } #endif + +#if CONFIG_IS_ENABLED(IMAGE_PRE_LOAD) +/** + * rsa_verify_openssl() - Verify a signature against some data with openssl API + * + * Verify a RSA PKCS1.5/PSS signature against an expected hash. + * + * @info: Specifies the key and algorithms + * @region: Pointer to the input data + * @region_count: Number of region + * @sig: Signature + * @sig_len: Number of bytes in the signature + * Return: 0 if verified, -ve on error + */ +int rsa_verify_openssl(struct image_sign_info *info, + const struct image_region region[], int region_count, + uint8_t *sig, uint sig_len) +{ + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ckey = NULL; + EVP_MD_CTX *ctx = NULL; + int pad; + int size; + int i; + int ret = 0; + + if (!info) { + fprintf(stderr, "No info provided\n"); + ret = -EINVAL; + goto out; + } + + if (!info->key) { + fprintf(stderr, "No key provided\n"); + ret = -EINVAL; + goto out; + } + + if (!info->checksum) { + fprintf(stderr, "No checksum information\n"); + ret = -EINVAL; + goto out; + } + + if (!info->padding) { + fprintf(stderr, "No padding information\n"); + ret = -EINVAL; + goto out; + } + + if (region_count < 1) { + fprintf(stderr, "Invalid value for region_count: %d\n", region_count); + ret = -EINVAL; + goto out; + } + + pkey = (EVP_PKEY *)info->key; + + ckey = EVP_PKEY_CTX_new(pkey, NULL); + if (!ckey) { + ret = -ENOMEM; + fprintf(stderr, "EVK key context setup failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + goto out; + } + + size = EVP_PKEY_size(pkey); + if (size > sig_len) { + fprintf(stderr, "Invalid signature size (%d bytes)\n", + size); + ret = -EINVAL; + goto out; + } + + ctx = EVP_MD_CTX_new(); + if (!ctx) { + ret = -ENOMEM; + fprintf(stderr, "EVP context creation failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + goto out; + } + EVP_MD_CTX_init(ctx); + + if (EVP_DigestVerifyInit(ctx, &ckey, + EVP_get_digestbyname(info->checksum->name), + NULL, pkey) <= 0) { + ret = -EINVAL; + fprintf(stderr, "Verifier setup failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + goto out; + } + + if (!strcmp(info->padding->name, "pkcs-1.5")) { + pad = RSA_PKCS1_PADDING; + } else if (!strcmp(info->padding->name, "pss")) { + pad = RSA_PKCS1_PSS_PADDING; + } else { + ret = -ENOMSG; + fprintf(stderr, "Unsupported padding: %s\n", + info->padding->name); + goto out; + } + + if (EVP_PKEY_CTX_set_rsa_padding(ckey, pad) <= 0) { + ret = -EINVAL; + fprintf(stderr, "padding setup has failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + goto out; + } + + for (i=0 ; i < region_count ; ++i) { + if (EVP_DigestVerifyUpdate(ctx, region[i].data, + region[i].size) <= 0) { + ret = -EINVAL; + fprintf(stderr, "Hashing data failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + goto out; + } + } + + if (EVP_DigestVerifyFinal(ctx, sig, sig_len) <= 0) { + ret = -EINVAL; + fprintf(stderr, "Verifying digest failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + goto out; + } +out: + if (ctx) + EVP_MD_CTX_free(ctx); + + if (ret) + fprintf(stderr, "Failed to verify signature\n"); + + return ret; +} +#endif diff --git a/tools/mkimage.h b/tools/mkimage.h index 15741f250fd..5d6bcc9301a 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -37,6 +37,10 @@ static inline void *map_sysmem(ulong paddr, unsigned long len) return (void *)(uintptr_t)paddr; } +static inline void unmap_sysmem(const void *vaddr) +{ +} + static inline ulong map_to_sysmem(const void *ptr) { return (ulong)(uintptr_t)ptr; diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py index 08795c4a0a8..490d382045b 100644 --- a/tools/patman/patchstream.py +++ b/tools/patman/patchstream.py @@ -711,7 +711,7 @@ def get_list(commit_range, git_dir=None, count=None): """ params = gitutil.log_cmd(commit_range, reverse=True, count=count, git_dir=git_dir) - return command.run_pipe([params], capture=True).stdout + return command.run_one(*params, capture=True).stdout def get_metadata_for_list(commit_range, git_dir=None, count=None, series=None, allow_overwrite=False): diff --git a/tools/preload_check_sign.c b/tools/preload_check_sign.c new file mode 100644 index 00000000000..ebead459273 --- /dev/null +++ b/tools/preload_check_sign.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Check a file including a preload header including a signature + * + * Copyright (c) 2025 Paul HENRYS <paul.henrys_ext@softathome.com> + * + * Binman makes it possible to generate a preload header signing part or the + * complete file. The tool preload_check_sign allows to verify and authenticate + * a file starting with a preload header. + */ +#include <stdio.h> +#include <unistd.h> +#include <openssl/pem.h> +#include <openssl/evp.h> +#include <openssl/err.h> +#include <image.h> + +extern void image_pre_load_sig_set_info(struct image_sig_info *info); +extern int image_pre_load_sig(ulong addr); + +static void usage(char *cmdname) +{ + fprintf(stderr, "Usage: %s -f file -k PEM key file\n" + " -f ==> set file which should be checked\n" + " -k ==> PEM key file\n" + " -a ==> algo (default: sha256,rsa2048)\n" + " -p ==> padding (default: pkcs-1.5)\n" + " -h ==> help\n", + cmdname); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + int ret = 0; + char cmdname[256]; + char *file = NULL; + char *keyfile = NULL; + int c; + FILE *fp = NULL; + FILE *fp_key = NULL; + size_t bytes; + long filesize; + void *buffer = NULL; + EVP_PKEY *pkey = NULL; + char *algo = "sha256,rsa2048"; + char *padding = "pkcs-1.5"; + struct image_sig_info info = {0}; + + strncpy(cmdname, *argv, sizeof(cmdname) - 1); + cmdname[sizeof(cmdname) - 1] = '\0'; + while ((c = getopt(argc, argv, "f:k:a:p:h")) != -1) + switch (c) { + case 'f': + file = optarg; + break; + case 'k': + keyfile = optarg; + break; + case 'a': + algo = optarg; + break; + case 'p': + padding = optarg; + break; + default: + usage(cmdname); + break; + } + + if (!file) { + fprintf(stderr, "%s: Missing file\n", *argv); + usage(*argv); + } + + if (!keyfile) { + fprintf(stderr, "%s: Missing key file\n", *argv); + usage(*argv); + } + + fp = fopen(file, "r"); + if (!fp) { + fprintf(stderr, "Error opening file: %s\n", file); + ret = EXIT_FAILURE; + goto out; + } + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + rewind(fp); + + buffer = malloc(filesize); + if (!buffer) { + fprintf(stderr, "Memory allocation failed"); + ret = EXIT_FAILURE; + goto out; + } + + bytes = fread(buffer, 1, filesize, fp); + if (bytes != filesize) { + fprintf(stderr, "Error reading file\n"); + ret = EXIT_FAILURE; + goto out; + } + + fp_key = fopen(keyfile, "r"); + if (!fp_key) { + fprintf(stderr, "Error opening file: %s\n", keyfile); + ret = EXIT_FAILURE; + goto out; + } + + /* Attempt to read the private key */ + pkey = PEM_read_PrivateKey(fp_key, NULL, NULL, NULL); + if (!pkey) { + /* If private key reading fails, try reading as a public key */ + fseek(fp_key, 0, SEEK_SET); + pkey = PEM_read_PUBKEY(fp_key, NULL, NULL, NULL); + } + if (!pkey) { + fprintf(stderr, "Unable to retrieve the public key: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + ret = EXIT_FAILURE; + goto out; + } + + info.algo_name = algo; + info.padding_name = padding; + info.key = (uint8_t *)pkey; + info.mandatory = 1; + info.sig_size = EVP_PKEY_size(pkey); + if (info.sig_size < 0) { + fprintf(stderr, "Fail to retrieve the signature size: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + ret = EXIT_FAILURE; + goto out; + } + + /* Compute signature information */ + info.sig_info.name = info.algo_name; + info.sig_info.padding = image_get_padding_algo(info.padding_name); + info.sig_info.checksum = image_get_checksum_algo(info.sig_info.name); + info.sig_info.crypto = image_get_crypto_algo(info.sig_info.name); + info.sig_info.key = info.key; + info.sig_info.keylen = info.key_len; + + /* Check the signature */ + image_pre_load_sig_set_info(&info); + ret = image_pre_load_sig((ulong)buffer); +out: + if (fp) + fclose(fp); + if (fp_key) + fclose(fp_key); + if (info.key) + EVP_PKEY_free(pkey); + free(buffer); + + exit(ret); +} diff --git a/tools/rmboard.py b/tools/rmboard.py index 0c56b149e0f..594fd89b8d7 100755 --- a/tools/rmboard.py +++ b/tools/rmboard.py @@ -43,18 +43,16 @@ def rm_kconfig_include(path): Args: path: Path to search for and remove """ - cmd = ['git', 'grep', path] - stdout = command.run_pipe([cmd], capture=True, raise_on_error=False).stdout + stdout = command.output('git', 'grep', path, raise_on_error=False) if not stdout: return fname = stdout.split(':')[0] print("Fixing up '%s' to remove reference to '%s'" % (fname, path)) - cmd = ['sed', '-i', '\|%s|d' % path, fname] - stdout = command.run_pipe([cmd], capture=True).stdout + stdout = command.run_one('sed', '-i', rf'\|{path}|d', fname, + capture=True).stdout - cmd = ['git', 'add', fname] - stdout = command.run_pipe([cmd], capture=True).stdout + stdout = command.output('git', 'add', fname) def rm_board(board): """Create a commit which removes a single board @@ -68,8 +66,7 @@ def rm_board(board): """ # Find all MAINTAINERS and Kconfig files which mention the board - cmd = ['git', 'grep', '-l', board] - stdout = command.run_pipe([cmd], capture=True).stdout + stdout = command.output('git', 'grep', '-l', board) maintain = [] kconfig = [] for line in stdout.splitlines(): @@ -109,16 +106,14 @@ def rm_board(board): # Search for Kconfig files in the resulting list. Remove any 'source' lines # which reference Kconfig files we want to remove for path in real: - cmd = ['find', path] - stdout = (command.run_pipe([cmd], capture=True, raise_on_error=False). - stdout) + stdout = command.output('find', path, raise_on_error=False) for fname in stdout.splitlines(): if fname.endswith('Kconfig'): rm_kconfig_include(fname) # Remove unwanted files cmd = ['git', 'rm', '-r'] + real - stdout = command.run_pipe([cmd], capture=True).stdout + stdout = command.output(*cmd, capture=True) ## Change the messages as needed msg = '''arm: Remove %s board @@ -131,13 +126,11 @@ Remove it. msg += 'Patch-cc: %s\n' % name # Create the commit - cmd = ['git', 'commit', '-s', '-m', msg] - stdout = command.run_pipe([cmd], capture=True).stdout + stdout = command.output('git', 'commit', '-s', '-m', msg) # Check if the board is mentioned anywhere else. The user will need to deal # with this - cmd = ['git', 'grep', '-il', board] - print(command.run_pipe([cmd], capture=True, raise_on_error=False).stdout) + print(command.output('git', 'grep', '-il', board, raise_on_error=False)) print(' '.join(cmd)) for board in sys.argv[1:]: diff --git a/tools/u_boot_pylib/command.py b/tools/u_boot_pylib/command.py index bbe95d86122..0e247355ef6 100644 --- a/tools/u_boot_pylib/command.py +++ b/tools/u_boot_pylib/command.py @@ -1,21 +1,44 @@ # SPDX-License-Identifier: GPL-2.0+ -# Copyright (c) 2011 The Chromium OS Authors. -# +""" +Shell command ease-ups for Python -import os +Copyright (c) 2011 The Chromium OS Authors. +""" + +import subprocess from u_boot_pylib import cros_subprocess -"""Shell command ease-ups for Python.""" +# This permits interception of RunPipe for test purposes. If it is set to +# a function, then that function is called with the pipe list being +# executed. Otherwise, it is assumed to be a CommandResult object, and is +# returned as the result for every run_pipe() call. +# When this value is None, commands are executed as normal. +TEST_RESULT = None + + +class CommandExc(Exception): + """Reports an exception to the caller""" + def __init__(self, msg, result): + """Set up a new exception object + + Args: + result (CommandResult): Execution result so far + """ + super().__init__(msg) + self.result = result + class CommandResult: """A class which captures the result of executing a command. Members: - stdout: stdout obtained from command, as a string - stderr: stderr obtained from command, as a string - return_code: Return code from command - exception: Exception received, or None if all ok + stdout (bytes): stdout obtained from command, as a string + stderr (bytes): stderr obtained from command, as a string + combined (bytes): stdout and stderr interleaved + return_code (int): Return code from command + exception (Exception): Exception received, or None if all ok + output (str or None): Returns output as a single line if requested """ def __init__(self, stdout='', stderr='', combined='', return_code=0, exception=None): @@ -24,8 +47,16 @@ class CommandResult: self.combined = combined self.return_code = return_code self.exception = exception + self.output = None def to_output(self, binary): + """Converts binary output to its final form + + Args: + binary (bool): True to report binary output, False to use strings + Returns: + self + """ if not binary: self.stdout = self.stdout.decode('utf-8') self.stderr = self.stderr.decode('utf-8') @@ -33,49 +64,47 @@ class CommandResult: return self -# This permits interception of RunPipe for test purposes. If it is set to -# a function, then that function is called with the pipe list being -# executed. Otherwise, it is assumed to be a CommandResult object, and is -# returned as the result for every run_pipe() call. -# When this value is None, commands are executed as normal. -test_result = None - -def run_pipe(pipe_list, infile=None, outfile=None, - capture=False, capture_stderr=False, oneline=False, - raise_on_error=True, cwd=None, binary=False, - output_func=None, **kwargs): +def run_pipe(pipe_list, infile=None, outfile=None, capture=False, + capture_stderr=False, oneline=False, raise_on_error=True, cwd=None, + binary=False, output_func=None, **kwargs): """ Perform a command pipeline, with optional input/output filenames. Args: - pipe_list: List of command lines to execute. Each command line is - piped into the next, and is itself a list of strings. For + pipe_list (list of list): List of command lines to execute. Each command + line is piped into the next, and is itself a list of strings. For example [ ['ls', '.git'] ['wc'] ] will pipe the output of 'ls .git' into 'wc'. - infile: File to provide stdin to the pipeline - outfile: File to store stdout - capture: True to capture output - capture_stderr: True to capture stderr - oneline: True to strip newline chars from output - output_func: Output function to call with each output fragment - (if it returns True the function terminates) - kwargs: Additional keyword arguments to cros_subprocess.Popen() + infile (str): File to provide stdin to the pipeline + outfile (str): File to store stdout + capture (bool): True to capture output + capture_stderr (bool): True to capture stderr + oneline (bool): True to strip newline chars from output + raise_on_error (bool): True to raise on an error, False to return it in + the CommandResult + cwd (str or None): Directory to run the command in + binary (bool): True to report binary output, False to use strings + output_func (function): Output function to call with each output + fragment (if it returns True the function terminates) + **kwargs: Additional keyword arguments to cros_subprocess.Popen() Returns: CommandResult object + Raises: + CommandExc if an exception happens """ - if test_result: - if hasattr(test_result, '__call__'): + if TEST_RESULT: + if hasattr(TEST_RESULT, '__call__'): # pylint: disable=E1102 - result = test_result(pipe_list=pipe_list) + result = TEST_RESULT(pipe_list=pipe_list) if result: return result else: - return test_result + return TEST_RESULT # No result: fall through to normal processing result = CommandResult(b'', b'', b'') last_pipe = None pipeline = list(pipe_list) - user_pipestr = '|'.join([' '.join(pipe) for pipe in pipe_list]) + user_pipestr = '|'.join([' '.join(pipe) for pipe in pipe_list]) kwargs['stdout'] = None kwargs['stderr'] = None while pipeline: @@ -96,7 +125,8 @@ def run_pipe(pipe_list, infile=None, outfile=None, except Exception as err: result.exception = err if raise_on_error: - raise Exception("Error running '%s': %s" % (user_pipestr, str)) + raise CommandExc(f"Error running '{user_pipestr}': {err}", + result) from err result.return_code = 255 return result.to_output(binary) @@ -107,31 +137,84 @@ def run_pipe(pipe_list, infile=None, outfile=None, result.output = result.stdout.rstrip(b'\r\n') result.return_code = last_pipe.wait() if raise_on_error and result.return_code: - raise Exception("Error running '%s'" % user_pipestr) + raise CommandExc(f"Error running '{user_pipestr}'", result) return result.to_output(binary) + def output(*cmd, **kwargs): + """Run a command and return its output + + Args: + *cmd (list of str): Command to run + **kwargs (dict of args): Extra arguments to pass in + + Returns: + str: command output + """ kwargs['raise_on_error'] = kwargs.get('raise_on_error', True) return run_pipe([cmd], capture=True, **kwargs).stdout + def output_one_line(*cmd, **kwargs): """Run a command and output it as a single-line string - The command us expected to produce a single line of output + The command is expected to produce a single line of output + + Args: + *cmd (list of str): Command to run + **kwargs (dict of args): Extra arguments to pass in Returns: - String containing output of command + str: output of command with all newlines removed """ raise_on_error = kwargs.pop('raise_on_error', True) result = run_pipe([cmd], capture=True, oneline=True, - raise_on_error=raise_on_error, **kwargs).stdout.strip() + raise_on_error=raise_on_error, **kwargs).stdout.strip() return result + def run(*cmd, **kwargs): + """Run a command + + Note that you must add 'capture' to kwargs to obtain non-empty output + + Args: + *cmd (list of str): Command to run + **kwargs (dict of args): Extra arguments to pass in + + Returns: + str: output of command + """ return run_pipe([cmd], **kwargs).stdout + +def run_one(*cmd, **kwargs): + """Run a single command + + Note that you must add 'capture' to kwargs to obtain non-empty output + + Args: + *cmd (list of str): Command to run + **kwargs (dict of args): Extra arguments to pass in + + Returns: + CommandResult: output of command + """ + return run_pipe([cmd], **kwargs) + + def run_list(cmd): + """Run a command and return its output + + Args: + cmd (list of str): Command to run + + Returns: + str: output of command + """ return run_pipe([cmd], capture=True).stdout + def stop_all(): + """Stop all subprocesses initiated with cros_subprocess""" cros_subprocess.stay_alive = False diff --git a/tools/u_boot_pylib/gitutil.py b/tools/u_boot_pylib/gitutil.py index 10ea5ff39f5..6d6a7eedecc 100644 --- a/tools/u_boot_pylib/gitutil.py +++ b/tools/u_boot_pylib/gitutil.py @@ -65,9 +65,9 @@ def count_commits_to_branch(branch): rev_range = '%s..%s' % (us, branch) else: rev_range = '@{upstream}..' - pipe = [log_cmd(rev_range, oneline=True)] - result = command.run_pipe(pipe, capture=True, capture_stderr=True, - oneline=True, raise_on_error=False) + cmd = log_cmd(rev_range, oneline=True) + result = command.run_one(*cmd, capture=True, capture_stderr=True, + oneline=True, raise_on_error=False) if result.return_code: raise ValueError('Failed to determine upstream: %s' % result.stderr.strip()) @@ -84,8 +84,7 @@ def name_revision(commit_hash): Return: Name of revision, if any, else None """ - pipe = ['git', 'name-rev', commit_hash] - stdout = command.run_pipe([pipe], capture=True, oneline=True).stdout + stdout = command.output_one_line('git', 'name-rev', commit_hash) # We expect a commit, a space, then a revision name name = stdout.split(' ')[1].strip() @@ -108,9 +107,9 @@ def guess_upstream(git_dir, branch): Name of upstream branch (e.g. 'upstream/master') or None if none Warning/error message, or None if none """ - pipe = [log_cmd(branch, git_dir=git_dir, oneline=True, count=100)] - result = command.run_pipe(pipe, capture=True, capture_stderr=True, - raise_on_error=False) + cmd = log_cmd(branch, git_dir=git_dir, oneline=True, count=100) + result = command.run_one(*cmd, capture=True, capture_stderr=True, + raise_on_error=False) if result.return_code: return None, "Branch '%s' not found" % branch for line in result.stdout.splitlines()[1:]: @@ -140,7 +139,7 @@ def get_upstream(git_dir, branch): 'branch.%s.remote' % branch) merge = command.output_one_line('git', '--git-dir', git_dir, 'config', 'branch.%s.merge' % branch) - except Exception: + except command.CommandExc: upstream, msg = guess_upstream(git_dir, branch) return upstream, msg @@ -183,9 +182,9 @@ def count_commits_in_range(git_dir, range_expr): Number of patches that exist in the supplied range or None if none were found """ - pipe = [log_cmd(range_expr, git_dir=git_dir, oneline=True)] - result = command.run_pipe(pipe, capture=True, capture_stderr=True, - raise_on_error=False) + cmd = log_cmd(range_expr, git_dir=git_dir, oneline=True) + result = command.run_one(*cmd, capture=True, capture_stderr=True, + raise_on_error=False) if result.return_code: return None, "Range '%s' not found or is invalid" % range_expr patch_count = len(result.stdout.splitlines()) @@ -250,9 +249,8 @@ def clone(git_dir, output_dir): Args: commit_hash: Commit hash to check out """ - pipe = ['git', 'clone', git_dir, '.'] - result = command.run_pipe([pipe], capture=True, cwd=output_dir, - capture_stderr=True) + result = command.run_one('git', 'clone', git_dir, '.', capture=True, + cwd=output_dir, capture_stderr=True) if result.return_code != 0: raise OSError('git clone: %s' % result.stderr) @@ -263,13 +261,13 @@ def fetch(git_dir=None, work_tree=None): Args: commit_hash: Commit hash to check out """ - pipe = ['git'] + cmd = ['git'] if git_dir: - pipe.extend(['--git-dir', git_dir]) + cmd.extend(['--git-dir', git_dir]) if work_tree: - pipe.extend(['--work-tree', work_tree]) - pipe.append('fetch') - result = command.run_pipe([pipe], capture=True, capture_stderr=True) + cmd.extend(['--work-tree', work_tree]) + cmd.append('fetch') + result = command.run_one(*cmd, capture=True, capture_stderr=True) if result.return_code != 0: raise OSError('git fetch: %s' % result.stderr) @@ -283,9 +281,9 @@ def check_worktree_is_available(git_dir): Returns: True if git-worktree commands will work, False otherwise. """ - pipe = ['git', '--git-dir', git_dir, 'worktree', 'list'] - result = command.run_pipe([pipe], capture=True, capture_stderr=True, - raise_on_error=False) + result = command.run_one('git', '--git-dir', git_dir, 'worktree', 'list', + capture=True, capture_stderr=True, + raise_on_error=False) return result.return_code == 0 @@ -298,11 +296,11 @@ def add_worktree(git_dir, output_dir, commit_hash=None): commit_hash: Commit hash to checkout """ # We need to pass --detach to avoid creating a new branch - pipe = ['git', '--git-dir', git_dir, 'worktree', 'add', '.', '--detach'] + cmd = ['git', '--git-dir', git_dir, 'worktree', 'add', '.', '--detach'] if commit_hash: - pipe.append(commit_hash) - result = command.run_pipe([pipe], capture=True, cwd=output_dir, - capture_stderr=True) + cmd.append(commit_hash) + result = command.run_one(*cmd, capture=True, cwd=output_dir, + capture_stderr=True) if result.return_code != 0: raise OSError('git worktree add: %s' % result.stderr) @@ -313,8 +311,8 @@ def prune_worktrees(git_dir): Args: git_dir: The repository whose deleted worktrees should be pruned """ - pipe = ['git', '--git-dir', git_dir, 'worktree', 'prune'] - result = command.run_pipe([pipe], capture=True, capture_stderr=True) + result = command.run_one('git', '--git-dir', git_dir, 'worktree', 'prune', + capture=True, capture_stderr=True) if result.return_code != 0: raise OSError('git worktree prune: %s' % result.stderr) @@ -687,7 +685,7 @@ def setup(): if alias_fname: settings.ReadGitAliases(alias_fname) cmd = log_cmd(None, count=0) - use_no_decorate = (command.run_pipe([cmd], raise_on_error=False) + use_no_decorate = (command.run_one(*cmd, raise_on_error=False) .return_code == 0) diff --git a/tools/u_boot_pylib/tools.py b/tools/u_boot_pylib/tools.py index 0499a75526f..1afd289eadd 100644 --- a/tools/u_boot_pylib/tools.py +++ b/tools/u_boot_pylib/tools.py @@ -376,7 +376,7 @@ def run_result(name, *args, **kwargs): args = tuple(extra_args) + args name = os.path.expanduser(name) # Expand paths containing ~ all_args = (name,) + args - result = command.run_pipe([all_args], capture=True, capture_stderr=True, + result = command.run_one(*all_args, capture=True, capture_stderr=True, env=env, raise_on_error=False, binary=binary) if result.return_code: if raise_on_error: |