From 5c9b420ada3b4f2a08da4789571f0ea373881565 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sun, 27 Feb 2022 13:20:32 +0100 Subject: [PATCH 01/20] qemu-arm: Enable NVMe for distro boot We already support the NVMe commands and PCIe backend in the QEMU target, so let's make it easy for anyone to consume them and enable NVMe distro boot along the way! With this patch, I can put an NVMe backed disk image into my QEMU VM and have it automatically load a UEFI target blob. Signed-off-by: Alexander Graf Reviewed-by: Mark Kettenis --- include/configs/qemu-arm.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/configs/qemu-arm.h b/include/configs/qemu-arm.h index 4f042e52cb7..3ad1cf3232d 100644 --- a/include/configs/qemu-arm.h +++ b/include/configs/qemu-arm.h @@ -39,6 +39,12 @@ # define BOOT_TARGET_VIRTIO(func) #endif +#if CONFIG_IS_ENABLED(CMD_NVME) +# define BOOT_TARGET_NVME(func) func(NVME, nvme, 0) +#else +# define BOOT_TARGET_NVME(func) +#endif + #if CONFIG_IS_ENABLED(CMD_DHCP) # define BOOT_TARGET_DHCP(func) func(DHCP, dhcp, na) #else @@ -49,6 +55,7 @@ BOOT_TARGET_USB(func) \ BOOT_TARGET_SCSI(func) \ BOOT_TARGET_VIRTIO(func) \ + BOOT_TARGET_NVME(func) \ BOOT_TARGET_DHCP(func) #include From 12a3e1ada06c702c403cf1eebb063ef7a34688cd Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Tue, 22 Feb 2022 21:49:52 +0300 Subject: [PATCH 02/20] arm: init: save previous bootloader data When u-boot is used as a chain-loaded bootloader (replacing OS kernel), previous bootloader leaves data in RAM, that can be reused. For example, on recent arm linux system, when chainloading u-boot, there are initramfs and fdt in RAM prepared for OS booting. Initramfs may be modified to store u-boot's payload, thus providing the ability to use chainloaded u-boot to boot OS without any storage support. Two config options added: - SAVE_PREV_BL_INITRAMFS_START_ADDR saves initramfs start address to 'prevbl_initrd_start_addr' environment variable - SAVE_PREV_BL_FDT_ADDR saves fdt address to 'prevbl_fdt_addr' environment variable Signed-off-by: Dzmitry Sankouski Cc: Tom Rini --- arch/arm/lib/Makefile | 5 ++ arch/arm/lib/save_prev_bl_data.c | 91 ++++++++++++++++++++++++++++++++ boot/Kconfig | 24 +++++++++ common/board_r.c | 5 ++ include/init.h | 13 +++++ 5 files changed, 138 insertions(+) create mode 100644 arch/arm/lib/save_prev_bl_data.c diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 594fc1228ae..c603fe61bc4 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -48,6 +48,11 @@ obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o endif obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o +ifneq ($(filter y,$(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR) $(CONFIG_SAVE_PREV_BL_FDT_ADDR)),) +obj-y += save_prev_bl_data.o +endif + +# obj-$(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR) += save_prev_bl_data.o obj-y += bdinfo.o obj-y += sections.o CFLAGS_REMOVE_sections.o := $(LTO_CFLAGS) diff --git a/arch/arm/lib/save_prev_bl_data.c b/arch/arm/lib/save_prev_bl_data.c new file mode 100644 index 00000000000..f4ee86a89c6 --- /dev/null +++ b/arch/arm/lib/save_prev_bl_data.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * save_prev_bl_data - saving previous bootloader data + * to environment variables. + * + * Copyright (c) 2022 Dzmitry Sankouski (dsankouski@gmail.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ulong reg0 __section(".data"); + +/** + * Save x0 register value, assuming previous bootloader set it to + * point on loaded fdt or (for older linux kernels)atags. + */ +void save_boot_params(ulong r0) +{ + reg0 = r0; + save_boot_params_ret(); +} + +bool is_addr_accessible(phys_addr_t addr) +{ + struct mm_region *mem = mem_map; + phys_addr_t bank_start; + phys_addr_t bank_end; + + while (mem->size) { + bank_start = mem->phys; + bank_end = bank_start + mem->size; + debug("check if block %pap - %pap includes %pap\n", &bank_start, &bank_end, &addr); + if (addr > bank_start && addr < bank_end) + return true; + mem++; + } + + return false; +} + +int save_prev_bl_data(void) +{ + struct fdt_header *fdt_blob; + int node; + u64 initrd_start_prop; + + if (!is_addr_accessible((phys_addr_t)reg0)) + return -ENODATA; + + fdt_blob = (struct fdt_header *)reg0; + if (!fdt_valid(&fdt_blob)) { + pr_warn("%s: address 0x%lx is not a valid fdt\n", __func__, reg0); + return -ENODATA; + } + + if (CONFIG_IS_ENABLED(SAVE_PREV_BL_FDT_ADDR)) + env_set_addr("prevbl_fdt_addr", (void *)reg0); + if (!CONFIG_IS_ENABLED(SAVE_PREV_BL_INITRAMFS_START_ADDR)) + return 0; + + node = fdt_path_offset(fdt_blob, "/chosen"); + if (!node) { + pr_warn("%s: chosen node not found in device tree at addr: 0x%lx\n", + __func__, reg0); + return -ENODATA; + } + /* + * linux,initrd-start property might be either 64 or 32 bit, + * depending on primary bootloader implementation. + */ + initrd_start_prop = fdtdec_get_uint64(fdt_blob, node, "linux,initrd-start", 0); + if (!initrd_start_prop) { + debug("%s: attempt to get uint64 linux,initrd-start property failed, trying uint\n", + __func__); + initrd_start_prop = fdtdec_get_uint(fdt_blob, node, "linux,initrd-start", 0); + if (!initrd_start_prop) { + debug("%s: attempt to get uint failed, too\n", __func__); + return -ENODATA; + } + } + env_set_addr("prevbl_initrd_start_addr", (void *)initrd_start_prop); + + return 0; +} diff --git a/boot/Kconfig b/boot/Kconfig index 394b26f246a..ec5b956490d 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -1192,4 +1192,28 @@ config DEFAULT_FDT_FILE help This option is used to set the default fdt file to boot OS. +config SAVE_PREV_BL_FDT_ADDR + depends on ARM + bool "Saves fdt address, passed by the previous bootloader, to env var" + help + When u-boot is used as a chain-loaded bootloader (replacing OS kernel), + enable this option to save fdt address, passed by the + previous bootloader for future use. + Address is saved to `prevbl_fdt_addr` environment variable. + + If no fdt was provided by previous bootloader, no env variables + will be created. + +config SAVE_PREV_BL_INITRAMFS_START_ADDR + depends on ARM + bool "Saves initramfs address, passed by the previous bootloader, to env var" + help + When u-boot is used as a chain-loaded bootloader(replacing OS kernel), + enable this option to save initramfs address, passed by the + previous bootloader for future use. + Address is saved to `prevbl_initrd_start_addr` environment variable. + + If no initramfs was provided by previous bootloader, no env variables + will be created. + endmenu # Booting diff --git a/common/board_r.c b/common/board_r.c index b92c1bb0be1..8dc87ed2be4 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -445,6 +445,11 @@ static int initr_env(void) env_set_hex("fdtcontroladdr", (unsigned long)map_to_sysmem(gd->fdt_blob)); + #if (CONFIG_IS_ENABLED(SAVE_PREV_BL_INITRAMFS_START_ADDR) || \ + CONFIG_IS_ENABLED(SAVE_PREV_BL_FDT_ADDR)) + save_prev_bl_data(); + #endif + /* Initialize from environment */ image_load_addr = env_get_ulong("loadaddr", 16, image_load_addr); diff --git a/include/init.h b/include/init.h index 74496500d29..7b8f62c1218 100644 --- a/include/init.h +++ b/include/init.h @@ -155,6 +155,19 @@ int arch_setup_bdinfo(void); */ int setup_bdinfo(void); +#if defined(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR) || \ +defined(CONFIG_SAVE_PREV_BL_FDT_ADDR) +/** + * save_prev_bl_data - Save prev bl data in env vars. + * + * When u-boot is chain-loaded, save previous bootloader data, + * like initramfs address to environment variables. + * + * Return: 0 if ok; -ENODATA on error + */ +int save_prev_bl_data(void); +#endif + /** * cpu_secondary_init_r() - CPU-specific secondary initialization * From f8a1b33889a2ed880062d9960a68718463093de6 Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Tue, 22 Feb 2022 21:49:53 +0300 Subject: [PATCH 03/20] board: starqltechn: get board usable - add bootcmd and docs U-boot is intended to replace linux kernel in android boot image(ABL), and it's FIT payload to replace initramfs file. The boot process is similar to boot image with linux: - android bootloader (ABL) unpacks android boot image - ABL sets `linux,initrd-start property` in chosen node in unpacked FDT - ABL sets x0 register to FDT address, and passes control to u-boot - u-boot reads x0 register, and stores it in `prevbl_fdt_addr` env variable - u-boot reads `linux,initrd-start` property, and stores it in `prevbl_initrd_start_addr` In this way, u-boot bootcmd relies on `prevbl_initrd_start_addr` env variable, and boils down to `bootm $prevbl_initrd_start_addr`. If more control on boot process is desired, pack a boot script in FIT image, and put it to default configuration What done: - strip unneeded config options - add FIT image support - add framebuffer node, u-boot logo and video console - increase LMB_MAX_REGIONS, to store all linux dtb reserved memory regions - add linux kernel image header Uart driver causes hang, when u-boot is used in android boot image instead of linux. Temporary disable console driver, until investigated and fixed. Signed-off-by: Dzmitry Sankouski Cc: Ramon Fried --- arch/arm/dts/sdm845.dtsi | 6 ++-- arch/arm/dts/starqltechn-uboot.dtsi | 9 ++++-- arch/arm/dts/starqltechn.dts | 13 ++++++-- configs/starqltechn_defconfig | 21 ++++++++++--- doc/board/qualcomm/sdm845.rst | 47 ++++++++++++++++++++++++++++- include/configs/sdm845.h | 8 +++++ 6 files changed, 90 insertions(+), 14 deletions(-) diff --git a/arch/arm/dts/sdm845.dtsi b/arch/arm/dts/sdm845.dtsi index 1185b712169..6f2fb20d68b 100644 --- a/arch/arm/dts/sdm845.dtsi +++ b/arch/arm/dts/sdm845.dtsi @@ -48,10 +48,8 @@ /* DEBUG UART */ qup_uart9: qup-uart9-default { - pinmux { - pins = "GPIO_4", "GPIO_5"; - function = "qup9"; - }; + pins = "GPIO_4", "GPIO_5"; + function = "gpio"; }; }; diff --git a/arch/arm/dts/starqltechn-uboot.dtsi b/arch/arm/dts/starqltechn-uboot.dtsi index d8d75e018a2..b55cccfe141 100644 --- a/arch/arm/dts/starqltechn-uboot.dtsi +++ b/arch/arm/dts/starqltechn-uboot.dtsi @@ -8,15 +8,18 @@ / { + framebuffer@9D400000 { + u-boot,dm-pre-reloc; + }; soc { u-boot,dm-pre-reloc; + serial@a84000 { + u-boot,dm-pre-reloc; + }; gcc { clock-controller@100000 { u-boot,dm-pre-reloc; }; - serial@0xa84000 { - u-boot,dm-pre-reloc; - }; gpio_north@3900000 { u-boot,dm-pre-reloc; }; diff --git a/arch/arm/dts/starqltechn.dts b/arch/arm/dts/starqltechn.dts index 387420f30b5..0261388319e 100644 --- a/arch/arm/dts/starqltechn.dts +++ b/arch/arm/dts/starqltechn.dts @@ -34,9 +34,18 @@ method = "smc"; }; + framebuffer: framebuffer@9D400000 { + compatible = "simple-framebuffer"; + reg = <0 0x9D400000 0 (2960 * 1440 * 4)>;//2400000 + width = <1440>; + height = <2960>; + stride = <(1440 * 4)>; + format = "a8r8g8b8"; + }; + soc: soc { - serial@0xa84000 { - status = "ok"; + serial@a84000 { + status = "okay"; }; pinctrl@3900000 { diff --git a/configs/starqltechn_defconfig b/configs/starqltechn_defconfig index f57bb859ccb..75e8409c4dc 100644 --- a/configs/starqltechn_defconfig +++ b/configs/starqltechn_defconfig @@ -2,16 +2,18 @@ CONFIG_ARM=y CONFIG_SKIP_LOWLEVEL_INIT=y CONFIG_POSITION_INDEPENDENT=y CONFIG_ARCH_SNAPDRAGON=y -CONFIG_SYS_TEXT_BASE=0x80000000 -CONFIG_SYS_MALLOC_LEN=0x81f000 CONFIG_DEFAULT_DEVICE_TREE="starqltechn" +CONFIG_BOOTDELAY=0 +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y CONFIG_TARGET_STARQLTECHN=y CONFIG_IDENT_STRING="\nSamsung S9 SM-G9600" CONFIG_SYS_LOAD_ADDR=0x80000000 -CONFIG_USE_PREBOOT=y +CONFIG_LMB_MAX_REGIONS=64 # CONFIG_DISPLAY_CPUINFO is not set CONFIG_HUSH_PARSER=y CONFIG_CMD_GPIO=y +# CONFIG_REQUIRE_SERIAL_CONSOLE is not set # CONFIG_NET is not set # CONFIG_DM_STDIO is not set CONFIG_CLK=y @@ -20,5 +22,16 @@ CONFIG_PM8916_GPIO=y CONFIG_PINCTRL=y CONFIG_DM_PMIC=y CONFIG_PMIC_PM8916=y -CONFIG_MSM_GENI_SERIAL=y +# CONFIG_MSM_GENI_SERIAL is not set CONFIG_SPMI_MSM=y +CONFIG_LINUX_KERNEL_IMAGE_HEADER=y +CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y +CONFIG_SAVE_PREV_BL_FDT_ADDR=y +CONFIG_DM_VIDEO=y +CONFIG_VIDEO_LOGO=y +CONFIG_CMD_VIDCONSOLE=y +CONFIG_CONSOLE_NORMAL=y +CONFIG_SYS_WHITE_ON_BLACK=y +CONFIG_VIDEO_DT_SIMPLEFB=y +CONFIG_VIDEO_SIMPLE=y +CONFIG_CMD_BMP=y diff --git a/doc/board/qualcomm/sdm845.rst b/doc/board/qualcomm/sdm845.rst index cd46cbe9cf1..b6642c95790 100644 --- a/doc/board/qualcomm/sdm845.rst +++ b/doc/board/qualcomm/sdm845.rst @@ -17,7 +17,9 @@ It is loaded as an Android boot image through ABL Installation ------------ -First, setup ``CROSS_COMPILE`` for aarch64. Then, build U-Boot for your board:: +Build +^^^^^ +Setup ``CROSS_COMPILE`` for aarch64 and build U-Boot for your board:: $ export CROSS_COMPILE= $ make _defconfig @@ -25,6 +27,49 @@ First, setup ``CROSS_COMPILE`` for aarch64. Then, build U-Boot for your board:: This will build ``u-boot.bin`` in the configured output directory. +Generate FIT image +^^^^^^^^^^^^^^^^^^ +See doc/uImage.FIT for more details + +Pack android boot image +^^^^^^^^^^^^^^^^^^^^^^^ +We'll assemble android boot image with ``u-boot.bin`` instead of linux kernel, +and FIT image instead of ``initramfs``. Android bootloader expect gzipped kernel +with appended dtb, so let's mimic linux to satisfy stock bootloader: + +- create dump dtb:: + + workdir=/tmp/prepare_payload + mkdir -p "$workdir" + cd "$workdir" + mock_dtb="$workdir"/payload_mock.dtb + + dtc -I dts -O dtb -o "$mock_dtb" << EOF + /dts-v1/; + / { + memory { + /* We expect the bootloader to fill in the size */ + reg = <0 0 0 0>; + }; + + chosen { }; + }; + EOF + +- gzip u-boot ``gzip u-boot.bin`` +- append dtb to gzipped u-boot: ``cat u-boot.bin.gz "$mock_dtb" > u-boot.bin.gz-dtb`` + +Now we've got everything to build android boot image::: + + mkbootimg --base 0x0 --kernel_offset 0x00008000 \ + --ramdisk_offset 0x02000000 --tags_offset 0x01e00000 \ + --pagesize 4096 --second_offset 0x00f00000 \ + --ramdisk "$fit_image" \ + --kernel u-boot.bin.gz-dtb \ + -o boot.img + +Flash image with your phone's flashing method. + Boards ------------ starqlte diff --git a/include/configs/sdm845.h b/include/configs/sdm845.h index af9ba197d49..ba57323c74b 100644 --- a/include/configs/sdm845.h +++ b/include/configs/sdm845.h @@ -16,6 +16,14 @@ /* Generic Timer Definitions */ #define COUNTER_FREQUENCY 19000000 +#define CONFIG_EXTRA_ENV_SETTINGS \ + "bootm_size=0x4000000\0" \ + "bootm_low=0x80000000\0" \ + "stdout=vidconsole\0" \ + "stderr=vidconsole\0" \ + "preboot=source $prevbl_initrd_start_addr:prebootscript\0" \ + "bootcmd=source $prevbl_initrd_start_addr:bootscript\0" + /* Size of malloc() pool */ #define CONFIG_SYS_BOOTM_LEN SZ_64M From d5c4ec4aa3aaa833cb535daa64a583a14304fc95 Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Tue, 22 Feb 2022 21:49:54 +0300 Subject: [PATCH 04/20] board: axy17lte: get board usable - add bootcmd and docs U-boot is intended to replace linux kernel in android boot image(ABL), and it's FIT payload to replace initramfs file. The boot process is similar to boot image with linux: - android bootloader (ABL) unpacks android boot image - ABL sets `linux,initrd-start property` in chosen node in unpacked FDT - ABL sets x0 register to FDT address, and passes control to u-boot - u-boot reads x0 register, and stores it in `prevbl_fdt_addr` env variable - u-boot reads `linux,initrd-start` property, and stores it in `prevbl_initrd_start_addr` In this way, u-boot bootcmd relies on `prevbl_initrd_start_addr` env variable, and boils down to `bootm $prevbl_initrd_start_addr`. If more control on boot process is desired, pack a boot script in FIT image, and put it to default configuration What done: - Rearrange defconfig option order - Add CONFIG_SAVE_PREV_BL_* options - Doc updates: - remove wrong SBOOT memory corruption note, because memory is changed during u-boot bringup process, not by SBOOT - put payload on ramdisk place in abl boot image creation step Signed-off-by: Dzmitry Sankouski --- configs/a3y17lte_defconfig | 3 +++ configs/a5y17lte_defconfig | 3 +++ configs/a7y17lte_defconfig | 3 +++ doc/board/samsung/axy17lte.rst | 15 +++------------ include/configs/exynos78x0-common.h | 4 ++++ 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/configs/a3y17lte_defconfig b/configs/a3y17lte_defconfig index b433da36302..7ca7ce0daf2 100644 --- a/configs/a3y17lte_defconfig +++ b/configs/a3y17lte_defconfig @@ -11,8 +11,11 @@ CONFIG_SYS_LOAD_ADDR=0x40001000 CONFIG_FIT=y CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="echo Read pressed buttons status;KEY_VOLUMEUP=gpa20;KEY_HOME=gpa17;KEY_VOLUMEDOWN=gpa21;KEY_POWER=gpa00;PRESSED=0;RELEASED=1;if gpio input $KEY_VOLUMEUP; then setenv VOLUME_UP $PRESSED; else setenv VOLUME_UP $RELEASED; fi;if gpio input $KEY_VOLUMEDOWN; then setenv VOLUME_DOWN $PRESSED; else setenv VOLUME_DOWN $RELEASED; fi;if gpio input $KEY_HOME; then setenv HOME $PRESSED; else setenv HOME $RELEASED; fi;if gpio input $KEY_POWER; then setenv POWER $PRESSED; else setenv POWER $RELEASED; fi;" +CONFIG_SAVE_PREV_BL_FDT_ADDR=y +CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_HUSH_PARSER=y CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_DM_I2C_GPIO=y +CONFIG_LMB_MAX_REGIONS=64 diff --git a/configs/a5y17lte_defconfig b/configs/a5y17lte_defconfig index 2534ab05737..793389eb735 100644 --- a/configs/a5y17lte_defconfig +++ b/configs/a5y17lte_defconfig @@ -11,8 +11,11 @@ CONFIG_SYS_LOAD_ADDR=0x40001000 CONFIG_FIT=y CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="echo Read pressed buttons status;KEY_VOLUMEUP=gpa20;KEY_HOME=gpa17;KEY_VOLUMEDOWN=gpa21;KEY_POWER=gpa00;PRESSED=0;RELEASED=1;if gpio input $KEY_VOLUMEUP; then setenv VOLUME_UP $PRESSED; else setenv VOLUME_UP $RELEASED; fi;if gpio input $KEY_VOLUMEDOWN; then setenv VOLUME_DOWN $PRESSED; else setenv VOLUME_DOWN $RELEASED; fi;if gpio input $KEY_HOME; then setenv HOME $PRESSED; else setenv HOME $RELEASED; fi;if gpio input $KEY_POWER; then setenv POWER $PRESSED; else setenv POWER $RELEASED; fi;" +CONFIG_SAVE_PREV_BL_FDT_ADDR=y +CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_HUSH_PARSER=y CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_DM_I2C_GPIO=y +CONFIG_LMB_MAX_REGIONS=64 diff --git a/configs/a7y17lte_defconfig b/configs/a7y17lte_defconfig index a2d76377ab0..eaa448d84d2 100644 --- a/configs/a7y17lte_defconfig +++ b/configs/a7y17lte_defconfig @@ -11,8 +11,11 @@ CONFIG_SYS_LOAD_ADDR=0x40001000 CONFIG_FIT=y CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="echo Read pressed buttons status;KEY_VOLUMEUP=gpa20;KEY_HOME=gpa17;KEY_VOLUMEDOWN=gpa21;KEY_POWER=gpa00;PRESSED=0;RELEASED=1;if gpio input $KEY_VOLUMEUP; then setenv VOLUME_UP $PRESSED; else setenv VOLUME_UP $RELEASED; fi;if gpio input $KEY_VOLUMEDOWN; then setenv VOLUME_DOWN $PRESSED; else setenv VOLUME_DOWN $RELEASED; fi;if gpio input $KEY_HOME; then setenv HOME $PRESSED; else setenv HOME $RELEASED; fi;if gpio input $KEY_POWER; then setenv POWER $PRESSED; else setenv POWER $RELEASED; fi;" +CONFIG_SAVE_PREV_BL_FDT_ADDR=y +CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_HUSH_PARSER=y CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_DM_I2C_GPIO=y +CONFIG_LMB_MAX_REGIONS=64 diff --git a/doc/board/samsung/axy17lte.rst b/doc/board/samsung/axy17lte.rst index e84fefec707..b7f299d1c7d 100644 --- a/doc/board/samsung/axy17lte.rst +++ b/doc/board/samsung/axy17lte.rst @@ -66,26 +66,17 @@ and is therefore SBOOT's payload. It may be pure u-boot (with loading u-boot's payload from flash in mind), or u-boot + u-boot's payload. -It should be kept in mind, that SBOOT binary patches it's payload after loading -in address range 0x401f8550-0x401f9280. Given SBOOT loads payload to 0x40001000, -a range of 0x1f7550-0x1f8280 (2061648-2065024) in a payload file -will be corrupted after loading to RAM. - Creating payload file """"""""""""""""""""" - Assemble FIT image for your kernel -- Create a file for u-boot payload ``touch sboot-payload`` -- Write zeroes till 0x200000 address to be sure SBOOT won't corrupt your info - ``dd if=/dev/zero of=sboot-payload bs=$((0x200000)) count=1`` -- Write u-boot to the start of the payload ``dd if= of=sboot-payload`` -- Write FIT image to payload from 0x200000 address - ``dd if= of=sboot-payload seek=1 bs=2M`` Creating android boot image """"""""""""""""""""""""""" Once payload created, it's time for android image:: - mkbootimg --base 0x40000000 --kernel_offset 0x00000000 --ramdisk_offset 0x01000000 --tags_offset 0x00000100 --pagesize 2048 --second_offset 0x00f00000 --kernel -o uboot.img + uboot= + ramdisk= + mkbootimg --base 0x40000000 --kernel_offset 0x00000000 --ramdisk_offset 0x01000000 --tags_offset 0x00000100 --pagesize 2048 --second_offset 0x00f00000 --kernel "$uboot" --ramdisk "$ramdisk" -o uboot.img Note, that stock Samsung bootloader ignores offsets, set in mkbootimg. diff --git a/include/configs/exynos78x0-common.h b/include/configs/exynos78x0-common.h index 53396aa4229..457057ce71f 100644 --- a/include/configs/exynos78x0-common.h +++ b/include/configs/exynos78x0-common.h @@ -35,6 +35,7 @@ #define CONFIG_SYS_SDRAM_BASE 0x40000000 #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + SZ_2M - GENERATED_GBL_DATA_SIZE) +#define CONFIG_SYS_BOOTM_LEN SZ_32M /* DRAM Memory Banks */ #define SDRAM_BANK_SIZE (256UL << 20UL) /* 256 MB */ #define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE @@ -79,7 +80,10 @@ #define EXYNOS_FDTFILE_SETTING #endif +/* Cannot use bootdelay > 0, because timer is not working */ #define EXTRA_ENV_SETTINGS \ + "bootdelay=0\0" \ + "bootcmd=source $prevbl_initrd_start_addr:bootscript\0" \ EXYNOS_DEVICE_SETTINGS \ EXYNOS_FDTFILE_SETTING \ MEM_LAYOUT_ENV_SETTINGS From 162a6f53a175e89a2a7ec8d42a2ef10d246be4e2 Mon Sep 17 00:00:00 2001 From: Hari Nagalla Date: Wed, 9 Mar 2022 14:42:28 -0600 Subject: [PATCH 05/20] misc: k3_esm: Add functionality to set and route error events within K3SoC Add functionality to enable, set priority to the input events and to route to MCU ESM. On AM64x/AM62x devices, it is possible to route Main ESM0 error events to MCU ESM. When these error events are routed to MCU ESM high output, it can trigger the reset logic to reset the device, when CTRLMMR_MCU_RST_CTRL:MCU_ESM_ERROR_RESET_EN_Z is set to '0'. K3 based J7 devices (ex: J721e) also have ESM modules, and the changes to the driver does not impact those devices. Signed-off-by: Hari Nagalla Reviewed-by: Christian Gmeiner --- drivers/misc/k3_esm.c | 53 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/drivers/misc/k3_esm.c b/drivers/misc/k3_esm.c index cc2a23dd663..41faeb3d858 100644 --- a/drivers/misc/k3_esm.c +++ b/drivers/misc/k3_esm.c @@ -16,17 +16,57 @@ #define ESM_SFT_RST 0x0c #define ESM_SFT_RST_KEY 0x0f +#define ESM_EN 0x08 +#define ESM_EN_KEY 0x0f #define ESM_STS(i) (0x404 + (i) / 32 * 0x20) +#define ESM_STS_MASK(i) (1 << ((i) % 32)) #define ESM_PIN_EN_SET_OFFSET(i) (0x414 + (i) / 32 * 0x20) -#define ESM_PIN_MASK(i) BIT((i) & 0x1f) +#define ESM_PIN_MASK(i) (1 << ((i) % 32)) +#define ESM_INTR_EN_SET_OFFSET(i) (0x408 + (i) / 32 * 0x20) +#define ESM_INTR_MASK(i) (1 << ((i) % 32)) +#define ESM_INTR_PRIO_SET_OFFSET(i) (0x410 + (i) / 32 * 0x20) +#define ESM_INTR_PRIO_MASK(i) (1 << ((i) % 32)) static void esm_pin_enable(void __iomem *base, int pin) { + u32 value; + + value = readl(base + ESM_PIN_EN_SET_OFFSET(pin)); + value |= ESM_PIN_MASK(pin); /* Enable event */ - writel(ESM_PIN_MASK(pin), base + ESM_PIN_EN_SET_OFFSET(pin)); + writel(value, base + ESM_PIN_EN_SET_OFFSET(pin)); } +static void esm_intr_enable(void __iomem *base, int pin) +{ + u32 value; + + value = readl(base + ESM_INTR_EN_SET_OFFSET(pin)); + value |= ESM_INTR_MASK(pin); + /* Enable Interrupt event */ + writel(value, base + ESM_INTR_EN_SET_OFFSET(pin)); +} + +static void esm_intr_prio_set(void __iomem *base, int pin) +{ + u32 value; + + value = readl(base + ESM_INTR_PRIO_SET_OFFSET(pin)); + value |= ESM_INTR_PRIO_MASK(pin); + /* Set to priority */ + writel(value, base + ESM_INTR_PRIO_SET_OFFSET(pin)); +} + +static void esm_clear_raw_status(void __iomem *base, int pin) +{ + u32 value; + + value = readl(base + ESM_STS(pin)); + value |= ESM_STS_MASK(pin); + /* Clear Event status */ + writel(value, base + ESM_STS(pin)); +} /** * k3_esm_probe: configures ESM based on DT data * @@ -67,8 +107,15 @@ static int k3_esm_probe(struct udevice *dev) /* Clear any pending events */ writel(ESM_SFT_RST_KEY, base + ESM_SFT_RST); - for (i = 0; i < num_pins; i++) + for (i = 0; i < num_pins; i++) { + esm_intr_prio_set(base, pins[i]); + esm_clear_raw_status(base, pins[i]); esm_pin_enable(base, pins[i]); + esm_intr_enable(base, pins[i]); + } + + /* Enable ESM */ + writel(ESM_EN_KEY, base + ESM_EN); free_pins: kfree(pins); From 3d64cffa91333f7bc5e7b9b8c88e1ad5eafd7a3f Mon Sep 17 00:00:00 2001 From: Hari Nagalla Date: Wed, 9 Mar 2022 14:42:29 -0600 Subject: [PATCH 06/20] arm: dts: k3-am64: Add support for ESM device nodes Enable access to ESM0 configuration space and add Main ESM0 and MCU ESM nodes to the AM64 device tree. Signed-off-by: Hari Nagalla Reviewed-by: Christian Gmeiner --- arch/arm/dts/k3-am64.dtsi | 1 + arch/arm/dts/k3-am642-r5-evm.dts | 19 +++++++++++++++++++ arch/arm/dts/k3-am642-r5-sk.dts | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/arch/arm/dts/k3-am64.dtsi b/arch/arm/dts/k3-am64.dtsi index de6805b0c72..7aa94d5a6e0 100644 --- a/arch/arm/dts/k3-am64.dtsi +++ b/arch/arm/dts/k3-am64.dtsi @@ -64,6 +64,7 @@ #address-cells = <2>; #size-cells = <2>; ranges = <0x00 0x000f4000 0x00 0x000f4000 0x00 0x000002d0>, /* PINCTRL */ + <0x00 0x00420000 0x00 0x00420000 0x00 0x00001000>, /* ESM0 */ <0x00 0x00600000 0x00 0x00600000 0x00 0x00001100>, /* GPIO */ <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* Timesync router */ <0x00 0x01000000 0x00 0x01000000 0x00 0x02330400>, /* First peripheral window */ diff --git a/arch/arm/dts/k3-am642-r5-evm.dts b/arch/arm/dts/k3-am642-r5-evm.dts index cc48fd4cb60..3ea6471e943 100644 --- a/arch/arm/dts/k3-am642-r5-evm.dts +++ b/arch/arm/dts/k3-am642-r5-evm.dts @@ -82,6 +82,25 @@ }; }; +&cbass_main { + main_esm: esm@420000 { + compatible = "ti,j721e-esm"; + reg = <0x0 0x420000 0x0 0x1000>; + ti,esm-pins = <160>, <161>; + u-boot,dm-spl; + }; +}; + +&cbass_mcu { + u-boot,dm-spl; + mcu_esm: esm@4100000 { + compatible = "ti,j721e-esm"; + reg = <0x0 0x4100000 0x0 0x1000>; + ti,esm-pins = <0>, <1>; + u-boot,dm-spl; + }; +}; + &main_pmx0 { u-boot,dm-spl; main_uart0_pins_default: main-uart0-pins-default { diff --git a/arch/arm/dts/k3-am642-r5-sk.dts b/arch/arm/dts/k3-am642-r5-sk.dts index 7d1cb856156..1f96e3fcacf 100644 --- a/arch/arm/dts/k3-am642-r5-sk.dts +++ b/arch/arm/dts/k3-am642-r5-sk.dts @@ -75,6 +75,25 @@ }; }; +&cbass_main { + main_esm: esm@420000 { + compatible = "ti,j721e-esm"; + reg = <0x0 0x420000 0x0 0x1000>; + ti,esm-pins = <160>, <161>; + u-boot,dm-spl; + }; +}; + +&cbass_mcu { + u-boot,dm-spl; + mcu_esm: esm@4100000 { + compatible = "ti,j721e-esm"; + reg = <0x0 0x4100000 0x0 0x1000>; + ti,esm-pins = <0>, <1>; + u-boot,dm-spl; + }; +}; + &main_pmx0 { u-boot,dm-spl; main_uart0_pins_default: main-uart0-pins-default { From 92e46092f2cfebe4d622c9120db9660927a4297a Mon Sep 17 00:00:00 2001 From: Hari Nagalla Date: Wed, 9 Mar 2022 14:42:30 -0600 Subject: [PATCH 07/20] arch: arm: mach-k3: am642_init: Probe ESM nodes On AM64x devices, it is possible to route Main ESM0 error events to MCU ESM. MCU ESM high error output can trigger the reset logic to reset the device. So, for these devices we expect two ESM device nodes in the device tree, one for Main ESM and the another MCU ESM in the device tree. When these ESM device nodes are properly configired it is possible to route the Main RTI0 WWDT output to the MCU ESM high output through Main ESM and trigger a device reset when CTRLMMR_MCU_RST_CTRL:MCU_ESM_ERROR_RESET_EN_Z is set to '0'. On K3 AM64x devices, the R5 SPL u-boot handles the ESM device node configurations. Signed-off-by: Hari Nagalla Reviewed-by: Christian Gmeiner --- arch/arm/mach-k3/am642_init.c | 40 +++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-k3/am642_init.c b/arch/arm/mach-k3/am642_init.c index 543dea02bca..3a75dcea351 100644 --- a/arch/arm/mach-k3/am642_init.c +++ b/arch/arm/mach-k3/am642_init.c @@ -24,12 +24,22 @@ #include #if defined(CONFIG_SPL_BUILD) +#define MCU_CTRL_MMR0_BASE 0x04500000 +#define CTRLMMR_MCU_RST_CTRL 0x04518170 static void ctrl_mmr_unlock(void) { /* Unlock all PADCFG_MMR1 module registers */ mmr_unlock(PADCFG_MMR1_BASE, 1); + /* Unlock all MCU_CTRL_MMR0 module registers */ + mmr_unlock(MCU_CTRL_MMR0_BASE, 0); + mmr_unlock(MCU_CTRL_MMR0_BASE, 1); + mmr_unlock(MCU_CTRL_MMR0_BASE, 2); + mmr_unlock(MCU_CTRL_MMR0_BASE, 3); + mmr_unlock(MCU_CTRL_MMR0_BASE, 4); + mmr_unlock(MCU_CTRL_MMR0_BASE, 6); + /* Unlock all CTRL_MMR0 module registers */ mmr_unlock(CTRL_MMR0_BASE, 0); mmr_unlock(CTRL_MMR0_BASE, 1); @@ -37,9 +47,6 @@ static void ctrl_mmr_unlock(void) mmr_unlock(CTRL_MMR0_BASE, 3); mmr_unlock(CTRL_MMR0_BASE, 5); mmr_unlock(CTRL_MMR0_BASE, 6); - - /* Unlock all MCU_PADCFG_MMR1 module registers */ - mmr_unlock(MCU_PADCFG_MMR1_BASE, 1); } /* @@ -142,9 +149,20 @@ int fdtdec_board_setup(const void *fdt_blob) } #endif +#if defined(CONFIG_ESM_K3) +static 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 &= 0xFFFDFFFF; + writel(stat, CTRLMMR_MCU_RST_CTRL); +} +#endif + void board_init_f(ulong dummy) { -#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM64_DDRSS) +#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM64_DDRSS) || defined(CONFIG_ESM_K3) struct udevice *dev; int ret; #endif @@ -194,6 +212,20 @@ void board_init_f(ulong dummy) /* Output System Firmware version info */ k3_sysfw_print_ver(); +#if defined(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); + + /* Probe/configure MCUESM */ + ret = uclass_get_device_by_name(UCLASS_MISC, "esm@4100000", &dev); + if (ret) + printf("esm mcu init failed: %d\n", ret); + + enable_mcu_esm_reset(); +#endif + #if defined(CONFIG_K3_AM64_DDRSS) ret = uclass_get_device(UCLASS_RAM, 0, &dev); if (ret) From cf13851be937b3995dca836c431131a12b54211d Mon Sep 17 00:00:00 2001 From: Hari Nagalla Date: Wed, 9 Mar 2022 14:42:31 -0600 Subject: [PATCH 08/20] configs: am64x_evm_r5_defconfig: Add support for ESM Enable ESM driver for AM64x R5 SPL/u-boot builds. Signed-off-by: Hari Nagalla Reviewed-by: Christian Gmeiner --- configs/am64x_evm_r5_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/am64x_evm_r5_defconfig b/configs/am64x_evm_r5_defconfig index 61138dd1a95..e29e99c2d1d 100644 --- a/configs/am64x_evm_r5_defconfig +++ b/configs/am64x_evm_r5_defconfig @@ -103,6 +103,7 @@ CONFIG_DM_I2C=y CONFIG_SYS_I2C_OMAP24XX=y CONFIG_DM_MAILBOX=y CONFIG_K3_SEC_PROXY=y +CONFIG_ESM_K3=y CONFIG_SPL_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ADMA=y From 1e20f571441020329775e1f7766f104bfafae7aa Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Fri, 11 Mar 2022 21:23:21 +0530 Subject: [PATCH 09/20] configs: am64x_evm_a53_defconfig: Switch to per-cpu timer as tick provider On arm64 systems, recommendation is to use per-cpu timer for time keeping. Currently AM64 ends up using DM timer as tick timer as driver is enabled in the config. Drop OMAP DM Timer related configs, this will switch to using armv8 per-cpu timer as tick timer for A53 SPL/U-Boot. Signed-off-by: Vignesh Raghavendra Reviewed-By: Nishanth Menon --- configs/am64x_evm_a53_defconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/configs/am64x_evm_a53_defconfig b/configs/am64x_evm_a53_defconfig index 7397436def6..bceb35f5ec5 100644 --- a/configs/am64x_evm_a53_defconfig +++ b/configs/am64x_evm_a53_defconfig @@ -135,9 +135,6 @@ CONFIG_CADENCE_QSPI=y CONFIG_SYSRESET=y CONFIG_SPL_SYSRESET=y CONFIG_SYSRESET_TI_SCI=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 From 8d1acfd8de0eab57ba8e2cd36fd2769dd745b1fe Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Fri, 11 Mar 2022 21:23:22 +0530 Subject: [PATCH 10/20] ARM: dts: k3-am642: Correct timer frequency Timer0 runs at 200MHz,and the clock-frequency defined in DT is incorrect. Fix it. Signed-off-by: Vignesh Raghavendra Reviewed-By: Nishanth Menon --- arch/arm/dts/k3-am642-evm-u-boot.dtsi | 2 +- arch/arm/dts/k3-am642-sk-u-boot.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/k3-am642-evm-u-boot.dtsi b/arch/arm/dts/k3-am642-evm-u-boot.dtsi index 03688a51a30..0c2d9734091 100644 --- a/arch/arm/dts/k3-am642-evm-u-boot.dtsi +++ b/arch/arm/dts/k3-am642-evm-u-boot.dtsi @@ -16,7 +16,7 @@ compatible = "ti,omap5430-timer"; reg = <0x0 0x2400000 0x0 0x80>; ti,timer-alwon; - clock-frequency = <250000000>; + clock-frequency = <200000000>; u-boot,dm-spl; }; }; diff --git a/arch/arm/dts/k3-am642-sk-u-boot.dtsi b/arch/arm/dts/k3-am642-sk-u-boot.dtsi index e5c26b83264..afe5baba8c4 100644 --- a/arch/arm/dts/k3-am642-sk-u-boot.dtsi +++ b/arch/arm/dts/k3-am642-sk-u-boot.dtsi @@ -20,7 +20,7 @@ compatible = "ti,omap5430-timer"; reg = <0x0 0x2400000 0x0 0x80>; ti,timer-alwon; - clock-frequency = <250000000>; + clock-frequency = <200000000>; u-boot,dm-spl; }; }; From adbe138a903b38ef2e18b0fc0202261418ae2060 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 17 Mar 2022 12:03:39 -0500 Subject: [PATCH 11/20] arm: dts: k3-am642-r5-evm: Mark memory with u-boot, dm-spl Mark the memory node with u-boot,dm-spl so we can use it from early SPL. Signed-off-by: Dave Gerlach --- arch/arm/dts/k3-am642-r5-evm.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/dts/k3-am642-r5-evm.dts b/arch/arm/dts/k3-am642-r5-evm.dts index 3ea6471e943..92a6bfdc011 100644 --- a/arch/arm/dts/k3-am642-r5-evm.dts +++ b/arch/arm/dts/k3-am642-r5-evm.dts @@ -25,6 +25,7 @@ /* 2G RAM */ reg = <0x00000000 0x80000000 0x00000000 0x80000000>; + u-boot,dm-spl; }; a53_0: a53@0 { From dffdb1f8eb2a88290896dd31f9e8d33789ba3757 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 17 Mar 2022 12:03:40 -0500 Subject: [PATCH 12/20] board: ti: am64x: Use fdt functions for ram and bank init Use the appropriate fdtdec_setup_mem_size_base and fdtdec_setup_bank_size calls in dram_init and dram_bank_init to pull these values from DT, where they are already available, instead of hardcoding them. Signed-off-by: Dave Gerlach --- board/ti/am64x/evm.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/board/ti/am64x/evm.c b/board/ti/am64x/evm.c index 8373c768f18..7ea80b82bec 100644 --- a/board/ti/am64x/evm.c +++ b/board/ti/am64x/evm.c @@ -29,19 +29,24 @@ int board_init(void) int dram_init(void) { - gd->ram_size = 0x80000000; + s32 ret; - return 0; + ret = fdtdec_setup_mem_size_base(); + if (ret) + printf("Error setting up mem size and base. %d\n", ret); + + return ret; } int dram_init_banksize(void) { - /* Bank 0 declares the memory available in the DDR low region */ - gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; - gd->bd->bi_dram[0].size = 0x80000000; - gd->ram_size = 0x80000000; + s32 ret; - return 0; + ret = fdtdec_setup_memory_banksize(); + if (ret) + printf("Error setting up memory banksize. %d\n", ret); + + return ret; } #if defined(CONFIG_SPL_LOAD_FIT) From 7b8a96e57e1db60f742184822a7d8dc508605f1f Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 17 Mar 2022 12:03:41 -0500 Subject: [PATCH 13/20] dt-bindings: memory-controller: Add information about ECC bindings Add DT binding documentation for enabling ECC in the DDR sub system present on AM64 device. Signed-off-by: Dave Gerlach --- .../memory-controller/k3-j721e-ddrss.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/device-tree-bindings/memory-controller/k3-j721e-ddrss.txt b/doc/device-tree-bindings/memory-controller/k3-j721e-ddrss.txt index dd0260b3940..df3290a6b9d 100644 --- a/doc/device-tree-bindings/memory-controller/k3-j721e-ddrss.txt +++ b/doc/device-tree-bindings/memory-controller/k3-j721e-ddrss.txt @@ -13,6 +13,7 @@ Required properties: "ti,am64-ddrss" for am642 - reg-names cfg - Map the controller configuration region ctrl_mmr_lp4 - Map LP4 register region in ctrl mmr + ss - Map the DDRSS configuration region - reg: Contains the register map per reg-names. - power-domains: Should contain two entries: - an entry to TISCI DDR CFG device @@ -32,6 +33,13 @@ Required properties: - ti,pi-data: An array containing the phy independent block settings - ti,phy-data: An array containing the ddr phy settings. +Optional properties: +-------------------- +- reg-names ss - Map the DDRSS configuration region +- reg: Must add "ss" to list if the above ss region is included. +- ti,ecc-enable: Boolean flag to enable ECC. This will reduce available DDR + by 1/9. + Example (J721E): ================ From 71eb527476e8bb32f3b9af5e472cb9fde1fdb127 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 17 Mar 2022 12:03:42 -0500 Subject: [PATCH 14/20] ram: k3-ddrss: Rename ddrss_ss_regs to ddrss_ctl_regs The current address being read from dt actually represents the ddrss_ctl memory region, while ddrss_ss region is something else. Introduce ddrss_ctl_regs and use it to free up ddrss_ss_regs for its proper purpose later so that we can avoid confusion. Signed-off-by: Dave Gerlach --- drivers/ram/k3-ddrss/k3-ddrss.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c index 25e3976e656..ffed426b9cc 100644 --- a/drivers/ram/k3-ddrss/k3-ddrss.c +++ b/drivers/ram/k3-ddrss/k3-ddrss.c @@ -106,6 +106,7 @@ struct k3_ddrss_desc { struct udevice *dev; void __iomem *ddrss_ss_cfg; void __iomem *ddrss_ctrl_mmr; + void __iomem *ddrss_ctl_cfg; struct power_domain ddrcfg_pwrdmn; struct power_domain ddrdata_pwrdmn; struct clk ddr_clk; @@ -319,7 +320,7 @@ static int k3_ddrss_ofdata_to_priv(struct udevice *dev) dev_err(dev, "No reg property for DDRSS wrapper logic\n"); return -EINVAL; } - ddrss->ddrss_ss_cfg = (void *)reg; + ddrss->ddrss_ctl_cfg = (void *)reg; reg = dev_read_addr_name(dev, "ctrl_mmr_lp4"); if (reg == FDT_ADDR_T_NONE) { @@ -403,7 +404,7 @@ void k3_lpddr4_init(struct k3_ddrss_desc *ddrss) hang(); } - config->ctlbase = (struct lpddr4_ctlregs_s *)ddrss->ddrss_ss_cfg; + config->ctlbase = (struct lpddr4_ctlregs_s *)ddrss->ddrss_ctl_cfg; config->infohandler = (lpddr4_infocallback) k3_lpddr4_info_handler; status = driverdt->init(pd, config); From f861ce90ca9538fefd76dbd1985f0c69f53e3b77 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 17 Mar 2022 12:03:43 -0500 Subject: [PATCH 15/20] ram: k3-ddrss: Introduce ECC Functionality for full memory space Introduce ECC Functionality for full memory space as implemented in the DDRSS. The following is done to accomplish this: * Introduce a memory region "ss" to allow dt to provide DDRSS region, which is not the same as "ctl" which is the controller region. * Introduce a "ti,ecc-enable" flag which allows a memorycontroller instance to enable ecc. * Introduce functionality to properly program the DDRSS registers to enable ECC for the full DDR memory space if enabled with above flag. * Expose a k3_ddrss_ddr_fdt_fixup call to allow fixup of fdt blob to account from DDR memory that must be reserved for ECC operation. Signed-off-by: Dave Gerlach --- drivers/ram/k3-ddrss/k3-ddrss.c | 133 ++++++++++++++++++++++++++++++++ include/k3-ddrss.h | 16 ++++ 2 files changed, 149 insertions(+) create mode 100644 include/k3-ddrss.h diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c index ffed426b9cc..2467f122a82 100644 --- a/drivers/ram/k3-ddrss/k3-ddrss.c +++ b/drivers/ram/k3-ddrss/k3-ddrss.c @@ -6,9 +6,12 @@ */ #include +#include #include +#include #include #include +#include #include #include #include @@ -30,6 +33,19 @@ #define DDRSS_V2A_R1_MAT_REG 0x0020 #define DDRSS_ECC_CTRL_REG 0x0120 +#define DDRSS_ECC_CTRL_REG_ECC_EN BIT(0) +#define DDRSS_ECC_CTRL_REG_RMW_EN BIT(1) +#define DDRSS_ECC_CTRL_REG_ECC_CK BIT(2) +#define DDRSS_ECC_CTRL_REG_WR_ALLOC BIT(4) + +#define DDRSS_ECC_R0_STR_ADDR_REG 0x0130 +#define DDRSS_ECC_R0_END_ADDR_REG 0x0134 +#define DDRSS_ECC_R1_STR_ADDR_REG 0x0138 +#define DDRSS_ECC_R1_END_ADDR_REG 0x013c +#define DDRSS_ECC_R2_STR_ADDR_REG 0x0140 +#define DDRSS_ECC_R2_END_ADDR_REG 0x0144 +#define DDRSS_ECC_1B_ERR_CNT_REG 0x0150 + #define SINGLE_DDR_SUBSYSTEM 0x1 #define MULTI_DDR_SUBSYSTEM 0x2 @@ -102,6 +118,13 @@ struct k3_msmc { enum emif_active active; }; +#define K3_DDRSS_MAX_ECC_REGIONS 3 + +struct k3_ddrss_ecc_region { + u32 start; + u32 range; +}; + struct k3_ddrss_desc { struct udevice *dev; void __iomem *ddrss_ss_cfg; @@ -119,6 +142,9 @@ struct k3_ddrss_desc { lpddr4_obj *driverdt; lpddr4_config config; lpddr4_privatedata pd; + struct k3_ddrss_ecc_region ecc_regions[K3_DDRSS_MAX_ECC_REGIONS]; + u64 ecc_reserved_space; + bool ti_ecc_enabled; }; struct reginitdata { @@ -329,6 +355,14 @@ static int k3_ddrss_ofdata_to_priv(struct udevice *dev) } ddrss->ddrss_ctrl_mmr = (void *)reg; + reg = dev_read_addr_name(dev, "ss_cfg"); + if (reg == FDT_ADDR_T_NONE) { + dev_dbg(dev, "No reg property for SS Config region, but this is optional so continuing.\n"); + ddrss->ddrss_ss_cfg = NULL; + } else { + ddrss->ddrss_ss_cfg = (void *)reg; + } + ret = power_domain_get_by_index(dev, &ddrss->ddrcfg_pwrdmn, 0); if (ret) { dev_err(dev, "power_domain_get() failed: %d\n", ret); @@ -372,6 +406,8 @@ static int k3_ddrss_ofdata_to_priv(struct udevice *dev) if (ret) dev_err(dev, "ddr fhs cnt not populated %d\n", ret); + ddrss->ti_ecc_enabled = dev_read_bool(dev, "ti,ecc-enable"); + return ret; } @@ -513,6 +549,60 @@ void k3_lpddr4_start(struct k3_ddrss_desc *ddrss) } } +static void k3_ddrss_set_ecc_range_r0(u32 base, u32 start_address, u32 size) +{ + writel((start_address) >> 16, base + DDRSS_ECC_R0_STR_ADDR_REG); + writel((start_address + size - 1) >> 16, base + DDRSS_ECC_R0_END_ADDR_REG); +} + +static void k3_ddrss_preload_ecc_mem_region(u32 *addr, u32 size, u32 word) +{ + int i; + + printf("ECC is enabled, priming DDR which will take several seconds.\n"); + + for (i = 0; i < (size / 4); i++) + addr[i] = word; +} + +static void k3_ddrss_lpddr4_ecc_calc_reserved_mem(struct k3_ddrss_desc *ddrss) +{ + fdtdec_setup_mem_size_base_lowest(); + + ddrss->ecc_reserved_space = gd->ram_size; + do_div(ddrss->ecc_reserved_space, 9); + + /* Round to clean number */ + ddrss->ecc_reserved_space = 1ull << (fls(ddrss->ecc_reserved_space)); +} + +static void k3_ddrss_lpddr4_ecc_init(struct k3_ddrss_desc *ddrss) +{ + u32 ecc_region_start = ddrss->ecc_regions[0].start; + u32 ecc_range = ddrss->ecc_regions[0].range; + u32 base = (u32)ddrss->ddrss_ss_cfg; + u32 val; + + /* Only Program region 0 which covers full ddr space */ + k3_ddrss_set_ecc_range_r0(base, ecc_region_start - gd->ram_base, ecc_range); + + /* Enable ECC, RMW, WR_ALLOC */ + writel(DDRSS_ECC_CTRL_REG_ECC_EN | DDRSS_ECC_CTRL_REG_RMW_EN | + DDRSS_ECC_CTRL_REG_WR_ALLOC, base + DDRSS_ECC_CTRL_REG); + + /* Preload ECC Mem region with 0's */ + k3_ddrss_preload_ecc_mem_region((u32 *)ecc_region_start, ecc_range, + 0x00000000); + + /* Clear Error Count Register */ + writel(0x1, base + DDRSS_ECC_1B_ERR_CNT_REG); + + /* Enable ECC Check */ + val = readl(base + DDRSS_ECC_CTRL_REG); + val |= DDRSS_ECC_CTRL_REG_ECC_CK; + writel(val, base + DDRSS_ECC_CTRL_REG); +} + static int k3_ddrss_probe(struct udevice *dev) { int ret; @@ -547,9 +637,52 @@ static int k3_ddrss_probe(struct udevice *dev) k3_lpddr4_start(ddrss); + if (ddrss->ti_ecc_enabled) { + if (!ddrss->ddrss_ss_cfg) { + printf("%s: ss_cfg is required if ecc is enabled but not provided.", + __func__); + return -EINVAL; + } + + k3_ddrss_lpddr4_ecc_calc_reserved_mem(ddrss); + + /* Always configure one region that covers full DDR space */ + ddrss->ecc_regions[0].start = gd->ram_base; + ddrss->ecc_regions[0].range = gd->ram_size - ddrss->ecc_reserved_space; + k3_ddrss_lpddr4_ecc_init(ddrss); + } + return ret; } +int k3_ddrss_ddr_fdt_fixup(struct udevice *dev, void *blob, struct bd_info *bd) +{ + struct k3_ddrss_desc *ddrss = dev_get_priv(dev); + u64 start[CONFIG_NR_DRAM_BANKS]; + u64 size[CONFIG_NR_DRAM_BANKS]; + int bank; + + if (ddrss->ecc_reserved_space == 0) + return 0; + + for (bank = CONFIG_NR_DRAM_BANKS - 1; bank >= 0; bank--) { + if (ddrss->ecc_reserved_space > bd->bi_dram[bank].size) { + ddrss->ecc_reserved_space -= bd->bi_dram[bank].size; + bd->bi_dram[bank].size = 0; + } else { + bd->bi_dram[bank].size -= ddrss->ecc_reserved_space; + break; + } + } + + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + start[bank] = bd->bi_dram[bank].start; + size[bank] = bd->bi_dram[bank].size; + } + + return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS); +} + static int k3_ddrss_get_info(struct udevice *dev, struct ram_info *info) { return 0; diff --git a/include/k3-ddrss.h b/include/k3-ddrss.h new file mode 100644 index 00000000000..d7b3bf3c330 --- /dev/null +++ b/include/k3-ddrss.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Texas Instruments' K3 DDRSS Driver + * + * Copyright (C) 2021-2022 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#ifndef _K3_DDRSS_ +#define _K3_DDRSS_ + +struct udevice; + +int k3_ddrss_ddr_fdt_fixup(struct udevice *dev, void *blob, struct bd_info *bd); + +#endif From 7ffcff277d13614023feb26356cf17647ac39db9 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 17 Mar 2022 12:03:44 -0500 Subject: [PATCH 16/20] board: ti: am64x: Account for DDR size fixups if ECC is enabled Call into k3-ddrss driver to fixup device tree and resize the available amount of DDR if ECC is enabled. A second fixup is required from A53 SPL to take the fixup as done from R5 SPL and apply it to DT passed to A53 U-boot, which in turn passes this to the OS. Signed-off-by: Dave Gerlach --- board/ti/am64x/evm.c | 55 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/board/ti/am64x/evm.c b/board/ti/am64x/evm.c index 7ea80b82bec..c88139ac7ac 100644 --- a/board/ti/am64x/evm.c +++ b/board/ti/am64x/evm.c @@ -2,13 +2,15 @@ /* * Board specific initialization for AM642 EVM * - * Copyright (C) 2020-2021 Texas Instruments Incorporated - https://www.ti.com/ + * Copyright (C) 2020-2022 Texas Instruments Incorporated - https://www.ti.com/ * Keerthy * */ #include #include +#include +#include #include #include #include @@ -66,7 +68,8 @@ int board_fit_config_name_match(const char *name) } #endif -#if defined(CONFIG_SPL_BUILD) && CONFIG_IS_ENABLED(USB_STORAGE) +#if defined(CONFIG_SPL_BUILD) +#if CONFIG_IS_ENABLED(USB_STORAGE) static int fixup_usb_boot(const void *fdt_blob) { int ret = 0; @@ -90,10 +93,58 @@ static int fixup_usb_boot(const void *fdt_blob) return ret; } +#endif + +#if defined(CONFIG_K3_AM64_DDRSS) +static void fixup_ddr_driver_for_ecc(struct spl_image_info *spl_image) +{ + struct udevice *dev; + int ret; + + dram_init_banksize(); + + ret = uclass_get_device(UCLASS_RAM, 0, &dev); + if (ret) + panic("Cannot get RAM device for ddr size fixup: %d\n", ret); + + ret = k3_ddrss_ddr_fdt_fixup(dev, spl_image->fdt_addr, gd->bd); + if (ret) + printf("Error fixing up ddr node for ECC use! %d\n", ret); +} +#else +static void fixup_memory_node(struct spl_image_info *spl_image) +{ + u64 start[CONFIG_NR_DRAM_BANKS]; + u64 size[CONFIG_NR_DRAM_BANKS]; + int bank; + int ret; + + dram_init(); + dram_init_banksize(); + + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + start[bank] = gd->bd->bi_dram[bank].start; + size[bank] = gd->bd->bi_dram[bank].size; + } + + /* dram_init functions use SPL fdt, and we must fixup u-boot fdt */ + ret = fdt_fixup_memory_banks(spl_image->fdt_addr, start, size, CONFIG_NR_DRAM_BANKS); + if (ret) + printf("Error fixing up memory node! %d\n", ret); +} +#endif void spl_perform_fixups(struct spl_image_info *spl_image) { +#if defined(CONFIG_K3_AM64_DDRSS) + fixup_ddr_driver_for_ecc(spl_image); +#else + fixup_memory_node(spl_image); +#endif + +#if CONFIG_IS_ENABLED(USB_STORAGE) fixup_usb_boot(spl_image->fdt_addr); +#endif } #endif From 1a40ddffecf6ded31d9a5d1a5bbd750aa28e4cf2 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 17 Mar 2022 12:03:45 -0500 Subject: [PATCH 17/20] arm: dts: k3-am64-ddr: Add ss_cfg reg entry Add 'ss_cfg' memory region for memorycontroller node which is required to enable ECC. Signed-off-by: Dave Gerlach --- arch/arm/dts/k3-am64-ddr.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/k3-am64-ddr.dtsi b/arch/arm/dts/k3-am64-ddr.dtsi index 026a547f0e3..8324b389e06 100644 --- a/arch/arm/dts/k3-am64-ddr.dtsi +++ b/arch/arm/dts/k3-am64-ddr.dtsi @@ -7,8 +7,9 @@ memorycontroller: memorycontroller@f300000 { compatible = "ti,am64-ddrss"; reg = <0x00 0x0f308000 0x00 0x4000>, - <0x00 0x43014000 0x00 0x100>; - reg-names = "cfg", "ctrl_mmr_lp4"; + <0x00 0x43014000 0x00 0x100>, + <0x00 0x0f300000 0x00 0x200>; + reg-names = "cfg", "ctrl_mmr_lp4", "ss_cfg"; power-domains = <&k3_pds 138 TI_SCI_PD_SHARED>, <&k3_pds 55 TI_SCI_PD_SHARED>; clocks = <&k3_clks 138 0>, <&k3_clks 16 4>; From ca1d803a4740bb565c05acb5a52491bbd9f6464d Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 17 Mar 2022 12:03:46 -0500 Subject: [PATCH 18/20] configs: am64x_evm_r5: Add CONFIG_NR_DRAM_BANKS as done in a53 defconfig Add CONFIG_NR_DRAM_BANKS from am64x_evm_a53_defconfig as this is needed to calculate the size of DDR that is available. Signed-off-by: Dave Gerlach --- configs/am64x_evm_r5_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/am64x_evm_r5_defconfig b/configs/am64x_evm_r5_defconfig index e29e99c2d1d..985e7df4f78 100644 --- a/configs/am64x_evm_r5_defconfig +++ b/configs/am64x_evm_r5_defconfig @@ -9,6 +9,7 @@ CONFIG_SOC_K3_AM642=y CONFIG_TARGET_AM642_R5_EVM=y CONFIG_ENV_SIZE=0x20000 CONFIG_ENV_OFFSET=0x680000 +CONFIG_NR_DRAM_BANKS=2 CONFIG_DM_GPIO=y CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="k3-am642-r5-evm" From e4901e65910494f39f06654fdde5336633a5d89a Mon Sep 17 00:00:00 2001 From: Dominic Rath Date: Wed, 23 Mar 2022 16:04:27 +0100 Subject: [PATCH 19/20] ram: k3-am654: Write all configuration values Makes it possible to use 16-bit DDR memory. Signed-off-by: Dominic Rath Signed-off-by: Christian Gmeiner --- drivers/ram/k3-am654-ddrss.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/ram/k3-am654-ddrss.c b/drivers/ram/k3-am654-ddrss.c index 4ec12bf42eb..a48ebe6ada8 100644 --- a/drivers/ram/k3-am654-ddrss.c +++ b/drivers/ram/k3-am654-ddrss.c @@ -265,6 +265,16 @@ static void am654_ddrss_phy_configuration(struct am654_ddrss_desc *ddrss) ddrss_phy_writel(DDRSS_DDRPHY_ACIOCR5, ioctl->ddrphy_aciocr5); ddrss_phy_writel(DDRSS_DDRPHY_IOVCR0, ioctl->ddrphy_iovcr0); + ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR0, cfg->ddrphy_dx2gcr0); + ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR1, cfg->ddrphy_dx2gcr1); + ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR2, cfg->ddrphy_dx2gcr2); + ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR3, cfg->ddrphy_dx2gcr3); + + ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR0, cfg->ddrphy_dx3gcr0); + ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR1, cfg->ddrphy_dx3gcr1); + ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR2, cfg->ddrphy_dx3gcr2); + ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR3, cfg->ddrphy_dx3gcr3); + ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR0, cfg->ddrphy_dx4gcr0); ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR1, cfg->ddrphy_dx4gcr1); ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR2, cfg->ddrphy_dx4gcr2); From da61ee662554f98fac0ab19c6b893edd82edb098 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Wed, 23 Mar 2022 16:04:28 +0100 Subject: [PATCH 20/20] ram: k3-am654: Make VTT regulator optional Signed-off-by: Christian Gmeiner --- drivers/ram/k3-am654-ddrss.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/ram/k3-am654-ddrss.c b/drivers/ram/k3-am654-ddrss.c index a48ebe6ada8..4453c247b29 100644 --- a/drivers/ram/k3-am654-ddrss.c +++ b/drivers/ram/k3-am654-ddrss.c @@ -884,9 +884,8 @@ static int am654_ddrss_power_on(struct am654_ddrss_desc *ddrss) device_get_supply_regulator(ddrss->dev, "vtt-supply", &ddrss->vtt_supply); ret = regulator_set_value(ddrss->vtt_supply, 3300000); - if (ret) - return ret; - debug("VTT regulator enabled\n"); + if (ret == 0) + debug("VTT regulator enabled\n"); #endif return 0;