From 9d6ee3e23591f4eb733153aa7776f53d9fef57f1 Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Thu, 15 Aug 2019 15:55:26 -0500 Subject: [PATCH 01/58] spl: ymodem: Fix FIT loading termination handling During FIT reading through ymodem_read_fit() the function xyzModem_stream_read() is being used which returns zero once the end of a stream has been reached. This could lead to an premature exit from ymodem_read_fit() with certain-sized FIT images reporting that zero bytes overall were read. Such a premature exit would then result in an -EIO failure being triggered within the spl_load_simple_fit() caller function and ultimately lead to a boot failure. Fix this logic by simply aborting the stream read loops and continuing with the regular code flow which ultimately would lead to returning the number of bytes to be read ('size') as expected by the callers of ymodem_read_fit(). Fixes: fa715193c083 ("spl: Add an option to load a FIT containing U-Boot from UART") Signed-off-by: Andreas Dannenberg --- common/spl/spl_ymodem.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c index 20f4260062..8ad580d8ae 100644 --- a/common/spl/spl_ymodem.c +++ b/common/spl/spl_ymodem.c @@ -44,7 +44,8 @@ static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset, while (info->image_read < offset) { res = xyzModem_stream_read(buf, BUF_SIZE, &err); if (res <= 0) - return res; + break; + info->image_read += res; } @@ -57,7 +58,7 @@ static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset, while (info->image_read < offset + size) { res = xyzModem_stream_read(buf, BUF_SIZE, &err); if (res <= 0) - return res; + break; memcpy(addr, buf, res); info->image_read += res; From e413033d3553402b313a4e2b1839c2d19e7cdcd3 Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Thu, 15 Aug 2019 15:55:27 -0500 Subject: [PATCH 02/58] spl: ymodem: Make SPL Y-Modem loader framework accessible Expose SPL's Y-Modem core loader function via the common SPL header file so it can be re-used for purposes other than loading U-Boot itself. Signed-off-by: Andreas Dannenberg --- common/spl/spl_ymodem.c | 4 ++-- include/spl.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c index 8ad580d8ae..c02c05624d 100644 --- a/common/spl/spl_ymodem.c +++ b/common/spl/spl_ymodem.c @@ -68,8 +68,8 @@ static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset, return size; } -static int spl_ymodem_load_image(struct spl_image_info *spl_image, - struct spl_boot_device *bootdev) +int spl_ymodem_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) { ulong size = 0; int err; diff --git a/include/spl.h b/include/spl.h index 4359636d87..b5387ef273 100644 --- a/include/spl.h +++ b/include/spl.h @@ -434,6 +434,9 @@ int spl_mmc_load(struct spl_image_info *spl_image, int raw_part, unsigned long raw_sect); +int spl_ymodem_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev); + /** * spl_invoke_atf - boot using an ARM trusted firmware image */ From e630afe1debc71b799548bdc6aa6bfbb02a12953 Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Thu, 15 Aug 2019 15:55:28 -0500 Subject: [PATCH 03/58] arm: K3: common: Allow for early console functionality Implement an early console functionality in SPL that can be used before the main console is being brought up. This helps in situations where the main console is dependent on System Firmware (SYSFW) being up and running, which is usually not the case during the very early stages of boot. Using this early console functionality will allow for an alternate serial port to be used to support things like UART-based boot and early diagnostic messages until the main console is ready to get activated. Signed-off-by: Andreas Dannenberg --- arch/arm/mach-k3/Kconfig | 21 +++++++++++++++++++++ arch/arm/mach-k3/common.c | 26 ++++++++++++++++++++++++++ arch/arm/mach-k3/common.h | 1 + 3 files changed, 48 insertions(+) diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index de1c1cc73f..5583241943 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -66,6 +66,27 @@ config SYS_K3_BOOT_CORE_ID int default 16 +config K3_EARLY_CONS + bool "Activate to allow for an early console during SPL" + depends on SPL + help + Turn this option on to enable an early console functionality in SPL + before the main console is being brought up. This can be useful in + situations where the main console is dependent on System Firmware + (SYSFW) being up and running, which is usually not the case during + the very early stages of boot. Using this early console functionality + will allow for an alternate serial port to be used to support things + like UART-based boot and early diagnostic messages until the main + console is ready to get activated. + +config K3_EARLY_CONS_IDX + depends on K3_EARLY_CONS + int "Index of serial device to use for SPL early console" + default 1 + help + Use this option to set the index of the serial device to be used + for the early console during SPL execution. + config K3_LOAD_SYSFW bool depends on SPL diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index c16afc654f..6c453b9af4 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -27,6 +27,32 @@ struct ti_sci_handle *get_ti_sci_handle(void) return (struct ti_sci_handle *)ti_sci_get_handle_from_sysfw(dev); } +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_K3_EARLY_CONS +int early_console_init(void) +{ + struct udevice *dev; + int ret; + + gd->baudrate = CONFIG_BAUDRATE; + + ret = uclass_get_device_by_seq(UCLASS_SERIAL, CONFIG_K3_EARLY_CONS_IDX, + &dev); + if (ret) { + printf("Error getting serial dev for early console! (%d)\n", + ret); + return ret; + } + + gd->cur_serial_dev = dev; + gd->flags |= GD_FLG_SERIAL_READY; + gd->have_console = 1; + + return 0; +} +#endif + #ifdef CONFIG_SYS_K3_SPL_ATF void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) { diff --git a/arch/arm/mach-k3/common.h b/arch/arm/mach-k3/common.h index ac7e80d9af..ab68e14de8 100644 --- a/arch/arm/mach-k3/common.h +++ b/arch/arm/mach-k3/common.h @@ -9,3 +9,4 @@ #include void setup_k3_mpu_regions(void); +int early_console_init(void); From 921b325854dbd198afd994be886095e94d2d4689 Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Thu, 15 Aug 2019 15:55:29 -0500 Subject: [PATCH 04/58] arm: K3: sysfw-loader: Allow loading SYSFW via Y-Modem In order to allow booting TI K3 family SoCs via Y-Modem add support for loading System Firmware by tapping into the associated SPL core loader function. In this context also make sure a console is available and if not go ahead and activate the early console feature which allows bringing up an alternate full console before the main console is activated. Such an alternate console is typically setup in a way that the associated UART can be fully initialized prior to SYSFW services being available. Signed-off-by: Andreas Dannenberg --- arch/arm/mach-k3/sysfw-loader.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c index 7a482bdc8a..5903bbe12a 100644 --- a/arch/arm/mach-k3/sysfw-loader.c +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -12,6 +12,9 @@ #include #include #include +#include "common.h" + +DECLARE_GLOBAL_DATA_PTR; /* Name of the FIT image nodes for SYSFW and its config data */ #define SYSFW_FIRMWARE "sysfw.bin" @@ -214,6 +217,24 @@ void k3_sysfw_loader(void (*config_pm_done_callback)(void)) 0); #endif break; +#endif +#if CONFIG_IS_ENABLED(YMODEM_SUPPORT) + case BOOT_DEVICE_UART: +#ifdef CONFIG_K3_EARLY_CONS + /* + * Establish a serial console if not yet available as required + * for UART-based boot. For this use the early console feature + * that allows setting up a UART for use before SYSFW has been + * brought up. Note that the associated UART module's clocks + * must have gotten enabled by the ROM bootcode which will be + * the case when continuing to boot serially from the same + * UART that the ROM loaded the initial bootloader from. + */ + if (!gd->have_console) + early_console_init(); +#endif + ret = spl_ymodem_load_image(&spl_image, &bootdev); + break; #endif default: panic("Loading SYSFW image from device %u not supported!\n", From 20a229676e492d0e105d1ab535dba56f9f470ad0 Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Thu, 15 Aug 2019 15:55:30 -0500 Subject: [PATCH 05/58] armv7R: dts: k3: am654: Add MCU_UART0 related definitions Although we currently use the MAIN_UART0 for R5 SPL console output there are cases where we require access to the MCU_UART0 as well for example in case of UART-based Y-Modem boot. To support these scenarios add related DTS definitions to be able to use that UART early on. Signed-off-by: Andreas Dannenberg --- arch/arm/dts/k3-am654-r5-base-board.dts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm/dts/k3-am654-r5-base-board.dts b/arch/arm/dts/k3-am654-r5-base-board.dts index 7ed307f0d8..e31ed4fe64 100644 --- a/arch/arm/dts/k3-am654-r5-base-board.dts +++ b/arch/arm/dts/k3-am654-r5-base-board.dts @@ -16,6 +16,7 @@ aliases { serial0 = &wkup_uart0; + serial1 = &mcu_uart0; serial2 = &main_uart0; }; @@ -118,6 +119,14 @@ status = "okay"; }; +&mcu_uart0 { + u-boot,dm-spl; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_uart0_pins_default>; + clock-frequency = <48000000>; + status = "okay"; +}; + &main_uart0 { power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>; }; @@ -141,6 +150,16 @@ u-boot,dm-spl; }; + mcu_uart0_pins_default: mcu_uart0_pins_default { + pinctrl-single,pins = < + AM65X_WKUP_IOPAD(0x0044, PIN_INPUT, 4) /* (P4) MCU_OSPI1_D1.MCU_UART0_RXD */ + AM65X_WKUP_IOPAD(0x0048, PIN_OUTPUT, 4) /* (P5) MCU_OSPI1_D2.MCU_UART0_TXD */ + AM65X_WKUP_IOPAD(0x004C, PIN_INPUT, 4) /* (P1) MCU_OSPI1_D3.MCU_UART0_CTSn */ + AM65X_WKUP_IOPAD(0x0054, PIN_OUTPUT, 4) /* (N3) MCU_OSPI1_CSn1.MCU_UART0_RTSn */ + >; + u-boot,dm-spl; + }; + wkup_i2c0_pins_default: wkup-i2c0-pins-default { pinctrl-single,pins = < AM65X_WKUP_IOPAD(0x00e0, PIN_INPUT, 0) /* (AC7) WKUP_I2C0_SCL */ From b8cc99a48f7753e58440ce61625327b11dcc149e Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Thu, 15 Aug 2019 15:55:31 -0500 Subject: [PATCH 06/58] configs: am65x_evm_r5: Activate early console functionality Activate early console functionality on AM654x devices to allow for an alternate serial port to be used to support UART-based boot. This is so that System Firmware (SYSFW) can get loaded over the serial port prior to the main console being brought up and made available. Signed-off-by: Andreas Dannenberg --- configs/am65x_evm_r5_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/am65x_evm_r5_defconfig b/configs/am65x_evm_r5_defconfig index 077aa37e00..d0619e9b7a 100644 --- a/configs/am65x_evm_r5_defconfig +++ b/configs/am65x_evm_r5_defconfig @@ -5,6 +5,7 @@ CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_SYS_MALLOC_F_LEN=0x55000 CONFIG_SOC_K3_AM6=y +CONFIG_K3_EARLY_CONS=y CONFIG_TARGET_AM654_R5_EVM=y CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y From bc74163a46208d1f9af8bfd2d06859b62145ef56 Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Thu, 15 Aug 2019 15:55:32 -0500 Subject: [PATCH 07/58] board: ti: am65x: Add UART boot procedure in README am65x ROM support booting over UART. And U-Boot built for am65x EVM supports UART boot as well. Add the UART boot procedure into the README also providing a corresponding example command sequence for execution on a host PC. Signed-off-by: Andreas Dannenberg --- board/ti/am65x/README | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/board/ti/am65x/README b/board/ti/am65x/README index 16384e05ea..2e3fd9c4a8 100644 --- a/board/ti/am65x/README +++ b/board/ti/am65x/README @@ -261,3 +261,35 @@ To boot kernel from eMMC, use the following commands: => setenv mmcdev 0 => setenv bootpart 0 => boot + +UART: +----- +ROM supports booting from MCU_UART0 via X-Modem protocol. The entire UART-based +boot process up to U-Boot (proper) prompt goes through different stages and uses +different UART peripherals as follows: + + WHO | Loading WHAT | HW Module | Protocol +----------+---------------+-------------+------------ +Boot ROM | tiboot3.bin | MCU_UART0 | X-Modem(*) +R5 SPL | sysfw.itb | MCU_UART0 | Y-Modem(*) +R5 SPL | tispl.bin | MAIN_UART0 | Y-Modem +A53 SPL | u-boot.img | MAIN_UART0 | Y-Modem + +(*) Note that in addition to X/Y-Modem related protocol timeouts the DMSC + watchdog timeout of 3min (typ.) needs to be observed until System Firmware + is fully loaded (from sysfw.itb) and started. + +Example bash script sequence for running on a Linux host PC feeding all boot +artifacts needed to the device: + +MCU_DEV=/dev/ttyUSB1 +MAIN_DEV=/dev/ttyUSB0 + +stty -F $MCU_DEV 115200 cs8 -cstopb -parenb +stty -F $MAIN_DEV 115200 cs8 -cstopb -parenb + +sb --xmodem tiboot3.bin > $MCU_DEV < $MCU_DEV +sb --ymodem sysfw.itb > $MCU_DEV < $MCU_DEV +sb --ymodem tispl.bin > $MAIN_DEV < $MAIN_DEV +sleep 1 +sb --xmodem u-boot.img > $MAIN_DEV < $MAIN_DEV From 240b93201007183d5fd651a210ddb4c50ee30980 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:26 +0530 Subject: [PATCH 08/58] dm: core: Add a function to count the children of a device Add a function to count the available children of a device. Signed-off-by: Lokesh Vutla --- drivers/core/device.c | 11 +++++++++++ include/dm/device.h | 9 +++++++++ test/dm/bus.c | 41 +++++++++++++++-------------------------- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/drivers/core/device.c b/drivers/core/device.c index 84f0f0fbf0..ce66c72e5e 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -568,6 +568,17 @@ int device_get_child(struct udevice *parent, int index, struct udevice **devp) return -ENODEV; } +int device_get_child_count(struct udevice *parent) +{ + struct udevice *dev; + int count = 0; + + list_for_each_entry(dev, &parent->child_head, sibling_node) + count++; + + return count; +} + int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq, bool find_req_seq, struct udevice **devp) { diff --git a/include/dm/device.h b/include/dm/device.h index d1210429e9..defda0aebc 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -404,6 +404,15 @@ const char *dev_get_uclass_name(const struct udevice *dev); */ int device_get_child(struct udevice *parent, int index, struct udevice **devp); +/** + * device_get_child_count() - Get the available child count of a device + * + * Returns the number of children to a device. + * + * @parent: Parent device to check + */ +int device_get_child_count(struct udevice *parent); + /** * device_find_child_by_seq() - Find a child device based on a sequence * diff --git a/test/dm/bus.c b/test/dm/bus.c index 93f3acd430..1ad45adb60 100644 --- a/test/dm/bus.c +++ b/test/dm/bus.c @@ -8,6 +8,7 @@ #include #endif #include +#include #include #include #include @@ -371,7 +372,6 @@ static int test_bus_parent_platdata(struct unit_test_state *uts) { struct dm_test_parent_platdata *plat; struct udevice *bus, *dev; - int child_count; /* Check that the bus has no children */ ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); @@ -380,7 +380,7 @@ static int test_bus_parent_platdata(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); - for (device_find_first_child(bus, &dev), child_count = 0; + for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { /* Check that platform data is allocated */ @@ -399,22 +399,20 @@ static int test_bus_parent_platdata(struct unit_test_state *uts) ut_asserteq_ptr(plat, dev_get_parent_platdata(dev)); ut_asserteq(1, plat->count); ut_assertok(device_probe(dev)); - child_count++; } - ut_asserteq(3, child_count); + ut_asserteq(3, device_get_child_count(bus)); /* Removing the bus should also have no effect (it is still bound) */ device_remove(bus, DM_REMOVE_NORMAL); - for (device_find_first_child(bus, &dev), child_count = 0; + for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { /* Check that platform data is allocated */ plat = dev_get_parent_platdata(dev); ut_assert(plat != NULL); ut_asserteq(1, plat->count); - child_count++; } - ut_asserteq(3, child_count); + ut_asserteq(3, device_get_child_count(bus)); /* Unbind all the children */ do { @@ -425,16 +423,15 @@ static int test_bus_parent_platdata(struct unit_test_state *uts) /* Now the child platdata should be removed and re-added */ device_probe(bus); - for (device_find_first_child(bus, &dev), child_count = 0; + for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { /* Check that platform data is allocated */ plat = dev_get_parent_platdata(dev); ut_assert(plat != NULL); ut_asserteq(0, plat->count); - child_count++; } - ut_asserteq(3, child_count); + ut_asserteq(3, device_get_child_count(bus)); return 0; } @@ -480,19 +477,17 @@ static int dm_test_bus_child_post_bind(struct unit_test_state *uts) { struct dm_test_parent_platdata *plat; struct udevice *bus, *dev; - int child_count; ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); - for (device_find_first_child(bus, &dev), child_count = 0; + for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { /* Check that platform data is allocated */ plat = dev_get_parent_platdata(dev); ut_assert(plat != NULL); ut_asserteq(1, plat->bind_flag); - child_count++; } - ut_asserteq(3, child_count); + ut_asserteq(3, device_get_child_count(bus)); return 0; } @@ -503,19 +498,17 @@ static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts) { struct dm_test_parent_platdata *plat; struct udevice *bus, *dev; - int child_count; ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); - for (device_find_first_child(bus, &dev), child_count = 0; + for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { /* Check that platform data is allocated */ plat = dev_get_parent_platdata(dev); ut_assert(plat != NULL); ut_asserteq(2, plat->uclass_bind_flag); - child_count++; } - ut_asserteq(3, child_count); + ut_asserteq(3, device_get_child_count(bus)); return 0; } @@ -529,14 +522,13 @@ DM_TEST(dm_test_bus_child_post_bind_uclass, static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts) { struct udevice *bus, *dev; - int child_count; /* * See testfdt_drv_probe() which effectively checks that the uclass * flag is set before that method is called */ ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); - for (device_find_first_child(bus, &dev), child_count = 0; + for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { struct dm_test_priv *priv = dev_get_priv(dev); @@ -549,9 +541,8 @@ static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts) ut_assert(priv != NULL); ut_asserteq(1, priv->uclass_flag); ut_asserteq(1, priv->uclass_total); - child_count++; } - ut_asserteq(3, child_count); + ut_asserteq(3, device_get_child_count(bus)); return 0; } @@ -565,14 +556,13 @@ DM_TEST(dm_test_bus_child_pre_probe_uclass, static int dm_test_bus_child_post_probe_uclass(struct unit_test_state *uts) { struct udevice *bus, *dev; - int child_count; /* * See testfdt_drv_probe() which effectively initializes that * the uclass postp flag is set to a value */ ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); - for (device_find_first_child(bus, &dev), child_count = 0; + for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { struct dm_test_priv *priv = dev_get_priv(dev); @@ -584,9 +574,8 @@ static int dm_test_bus_child_post_probe_uclass(struct unit_test_state *uts) priv = dev_get_priv(dev); ut_assert(priv != NULL); ut_asserteq(0, priv->uclass_postp); - child_count++; } - ut_asserteq(3, child_count); + ut_asserteq(3, device_get_child_count(bus)); return 0; } From c08eb936263c67312cb55c354277f9dc3433b194 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:27 +0530 Subject: [PATCH 09/58] remoteproc: ops: Add elf section size as input parameter to device_to_virt api Introduce a new parameter "size" that accepts size of the region to remoteproc ops callback device_to_virt(). This can enforce more checks on the region that device_to_virt() is dealing with. Signed-off-by: Lokesh Vutla Tested-by: Fabien Dessenne Reviewed-by: Fabien Dessenne --- drivers/remoteproc/rproc-elf-loader.c | 3 ++- drivers/remoteproc/sandbox_testproc.c | 4 +++- drivers/remoteproc/stm32_copro.c | 12 ++++++++++-- include/remoteproc.h | 3 ++- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c index 67937a7595..7574ba3fb3 100644 --- a/drivers/remoteproc/rproc-elf-loader.c +++ b/drivers/remoteproc/rproc-elf-loader.c @@ -86,7 +86,8 @@ int rproc_elf32_load_image(struct udevice *dev, unsigned long addr) continue; if (ops->device_to_virt) - dst = ops->device_to_virt(dev, (ulong)dst); + dst = ops->device_to_virt(dev, (ulong)dst, + phdr->p_memsz); dev_dbg(dev, "Loading phdr %i to 0x%p (%i bytes)\n", i, dst, phdr->p_filesz); diff --git a/drivers/remoteproc/sandbox_testproc.c b/drivers/remoteproc/sandbox_testproc.c index 5f35119ab7..eeee49c4dd 100644 --- a/drivers/remoteproc/sandbox_testproc.c +++ b/drivers/remoteproc/sandbox_testproc.c @@ -306,9 +306,11 @@ static int sandbox_testproc_ping(struct udevice *dev) * sandbox_testproc_device_to_virt() - Convert device address to virtual address * @dev: device to operate upon * @da: device address + * @size: Size of the memory region @da is pointing to * @return converted virtual address */ -static void *sandbox_testproc_device_to_virt(struct udevice *dev, ulong da) +static void *sandbox_testproc_device_to_virt(struct udevice *dev, ulong da, + ulong size) { u64 paddr; diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c index ad941f67e8..71895daf9c 100644 --- a/drivers/remoteproc/stm32_copro.c +++ b/drivers/remoteproc/stm32_copro.c @@ -107,11 +107,13 @@ static int stm32_copro_set_hold_boot(struct udevice *dev, bool hold) * stm32_copro_device_to_virt() - Convert device address to virtual address * @dev: corresponding STM32 remote processor device * @da: device address + * @size: Size of the memory region @da is pointing to * @return converted virtual address */ -static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da) +static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da, + ulong size) { - fdt32_t in_addr = cpu_to_be32(da); + fdt32_t in_addr = cpu_to_be32(da), end_addr; u64 paddr; paddr = dev_translate_dma_address(dev, &in_addr); @@ -120,6 +122,12 @@ static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da) return NULL; } + end_addr = cpu_to_be32(da + size - 1); + if (dev_translate_dma_address(dev, &end_addr) == OF_BAD_ADDR) { + dev_err(dev, "Unable to convert address %ld\n", da + size - 1); + return NULL; + } + return phys_to_virt(paddr); } diff --git a/include/remoteproc.h b/include/remoteproc.h index 4987194905..dbff1ce3cf 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -122,9 +122,10 @@ struct dm_rproc_ops { * * @dev: Remote proc device * @da: Device address + * @size: Size of the memory region @da is pointing to * @return virtual address. */ - void * (*device_to_virt)(struct udevice *dev, ulong da); + void * (*device_to_virt)(struct udevice *dev, ulong da, ulong size); }; /* Accessor */ From 14d963d1b51fc7a57b8d561588f163d7cae8ed81 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:28 +0530 Subject: [PATCH 10/58] remoteproc: elf_loader: Always check the validity of the image before loading rproc_elf32_load_image() rely on user to send a valid address for elf loading. Instead do a sanity check on the address passed by user. This will help all rproc elf users to not call sanity_check explicitly before calling elf_loading. Signed-off-by: Lokesh Vutla Reviewed-by: Fabien Dessenne --- drivers/remoteproc/rproc-elf-loader.c | 11 ++++++++--- drivers/remoteproc/stm32_copro.c | 9 +-------- include/remoteproc.h | 6 ++++-- test/dm/remoteproc.c | 5 +---- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c index 7574ba3fb3..238f51d3b5 100644 --- a/drivers/remoteproc/rproc-elf-loader.c +++ b/drivers/remoteproc/rproc-elf-loader.c @@ -64,13 +64,18 @@ int rproc_elf32_sanity_check(ulong addr, ulong size) return 0; } -/* A very simple elf loader, assumes the image is valid */ -int rproc_elf32_load_image(struct udevice *dev, unsigned long addr) +int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size) { Elf32_Ehdr *ehdr; /* Elf header structure pointer */ Elf32_Phdr *phdr; /* Program header structure pointer */ const struct dm_rproc_ops *ops; - unsigned int i; + unsigned int i, ret; + + ret = rproc_elf32_sanity_check(addr, size); + if (ret) { + dev_err(dev, "Invalid ELF32 Image %d\n", ret); + return ret; + } ehdr = (Elf32_Ehdr *)addr; phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c index 71895daf9c..40bba37211 100644 --- a/drivers/remoteproc/stm32_copro.c +++ b/drivers/remoteproc/stm32_copro.c @@ -155,14 +155,7 @@ static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) return ret; } - /* Support only ELF32 image */ - ret = rproc_elf32_sanity_check(addr, size); - if (ret) { - dev_err(dev, "Invalid ELF32 image (%d)\n", ret); - return ret; - } - - return rproc_elf32_load_image(dev, addr); + return rproc_elf32_load_image(dev, addr, size); } /** diff --git a/include/remoteproc.h b/include/remoteproc.h index dbff1ce3cf..1ef88be7f7 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -218,9 +218,10 @@ int rproc_elf32_sanity_check(ulong addr, ulong size); * rproc_elf32_load_image() - load an ELF32 image * @dev: device loading the ELF32 image * @addr: valid ELF32 image address + * @size: size of the image * @return 0 if the image is successfully loaded, else appropriate error value. */ -int rproc_elf32_load_image(struct udevice *dev, unsigned long addr); +int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size); #else static inline int rproc_init(void) { return -ENOSYS; } static inline int rproc_dev_init(int id) { return -ENOSYS; } @@ -234,7 +235,8 @@ static inline int rproc_is_running(int id) { return -ENOSYS; } static inline int rproc_elf32_sanity_check(ulong addr, ulong size) { return -ENOSYS; } static inline int rproc_elf32_load_image(struct udevice *dev, - unsigned long addr) { return -ENOSYS; } + unsigned long addr, ulong size) +{ return -ENOSYS; } #endif #endif /* _RPROC_H_ */ diff --git a/test/dm/remoteproc.c b/test/dm/remoteproc.c index a2c4be7c27..c77361c8f4 100644 --- a/test/dm/remoteproc.c +++ b/test/dm/remoteproc.c @@ -171,11 +171,8 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) ut_assertnonnull(loaded_firmware); memset(loaded_firmware, 0, loaded_firmware_size); - /* Verify valid ELF format */ - ut_assertok(rproc_elf32_sanity_check((ulong)valid_elf32, size)); - /* Load firmware in loaded_firmware, and verify it */ - ut_assertok(rproc_elf32_load_image(dev, (unsigned long)valid_elf32)); + ut_assertok(rproc_elf32_load_image(dev, (ulong)valid_elf32, size)); ut_assertok(memcmp(loaded_firmware, valid_elf32, loaded_firmware_size)); unmap_physmem(loaded_firmware, MAP_NOCACHE); From e3c4d6f01fb5c86ee8a67d28cc3a0eb708954e40 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:29 +0530 Subject: [PATCH 11/58] remoteproc: elf-loader: Add 64 bit elf loading support The current rproc-elf-loader supports loading of only 32 bit elf files. Introduce support for loading of 64 bit elf files in rproc-elf-loader. Signed-off-by: Lokesh Vutla Reviewed-by: Fabien Dessenne --- drivers/remoteproc/rproc-elf-loader.c | 110 ++++++++++++++++++++++++++ include/remoteproc.h | 26 ++++++ 2 files changed, 136 insertions(+) diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c index 238f51d3b5..1aece2fc31 100644 --- a/drivers/remoteproc/rproc-elf-loader.c +++ b/drivers/remoteproc/rproc-elf-loader.c @@ -64,6 +64,62 @@ int rproc_elf32_sanity_check(ulong addr, ulong size) return 0; } +/* Basic function to verify ELF64 image format */ +int rproc_elf64_sanity_check(ulong addr, ulong size) +{ + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)addr; + char class; + + if (!addr) { + pr_debug("Invalid fw address?\n"); + return -EFAULT; + } + + if (size < sizeof(Elf64_Ehdr)) { + pr_debug("Image is too small\n"); + return -ENOSPC; + } + + class = ehdr->e_ident[EI_CLASS]; + + if (!IS_ELF(*ehdr) || ehdr->e_type != ET_EXEC || class != ELFCLASS64) { + pr_debug("Not an executable ELF64 image\n"); + return -EPROTONOSUPPORT; + } + + /* We assume the firmware has the same endianness as the host */ +# ifdef __LITTLE_ENDIAN + if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) { +# else /* BIG ENDIAN */ + if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) { +# endif + pr_debug("Unsupported firmware endianness\n"); + return -EILSEQ; + } + + if (size < ehdr->e_shoff + sizeof(Elf64_Shdr)) { + pr_debug("Image is too small\n"); + return -ENOSPC; + } + + if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { + pr_debug("Image is corrupted (bad magic)\n"); + return -EBADF; + } + + if (ehdr->e_phnum == 0) { + pr_debug("No loadable segments\n"); + return -ENOEXEC; + } + + if (ehdr->e_phoff > size) { + pr_debug("Firmware size is too small\n"); + return -ENOSPC; + } + + return 0; +} + int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size) { Elf32_Ehdr *ehdr; /* Elf header structure pointer */ @@ -110,3 +166,57 @@ int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size) return 0; } + +int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size) +{ + const struct dm_rproc_ops *ops = rproc_get_ops(dev); + u64 da, memsz, filesz, offset; + Elf64_Ehdr *ehdr; + Elf64_Phdr *phdr; + int i, ret = 0; + void *ptr; + + dev_dbg(dev, "%s: addr = 0x%lx size = 0x%lx\n", __func__, addr, size); + + if (rproc_elf64_sanity_check(addr, size)) + return -EINVAL; + + ehdr = (Elf64_Ehdr *)addr; + phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff); + + /* go through the available ELF segments */ + for (i = 0; i < ehdr->e_phnum; i++, phdr++) { + da = phdr->p_paddr; + memsz = phdr->p_memsz; + filesz = phdr->p_filesz; + offset = phdr->p_offset; + + if (phdr->p_type != PT_LOAD) + continue; + + dev_dbg(dev, "%s:phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n", + __func__, phdr->p_type, da, memsz, filesz); + + ptr = (void *)(uintptr_t)da; + if (ops->device_to_virt) { + ptr = ops->device_to_virt(dev, da, phdr->p_memsz); + if (!ptr) { + dev_err(dev, "bad da 0x%llx mem 0x%llx\n", da, + memsz); + ret = -EINVAL; + break; + } + } + + if (filesz) + memcpy(ptr, (void *)addr + offset, filesz); + if (filesz != memsz) + memset(ptr + filesz, 0x00, memsz - filesz); + + flush_cache(rounddown((ulong)ptr, ARCH_DMA_MINALIGN), + roundup((ulong)ptr + filesz, ARCH_DMA_MINALIGN) - + rounddown((ulong)ptr, ARCH_DMA_MINALIGN)); + } + + return ret; +} diff --git a/include/remoteproc.h b/include/remoteproc.h index 1ef88be7f7..56a11db6e3 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -214,6 +214,18 @@ int rproc_is_running(int id); */ int rproc_elf32_sanity_check(ulong addr, ulong size); +/** + * rproc_elf64_sanity_check() - Verify if an image is a valid ELF32 one + * + * Check if a valid ELF64 image exists at the given memory location. Verify + * basic ELF64 format requirements like magic number and sections size. + * + * @addr: address of the image to verify + * @size: size of the image + * @return 0 if the image looks good, else appropriate error value. + */ +int rproc_elf64_sanity_check(ulong addr, ulong size); + /** * rproc_elf32_load_image() - load an ELF32 image * @dev: device loading the ELF32 image @@ -222,6 +234,15 @@ int rproc_elf32_sanity_check(ulong addr, ulong size); * @return 0 if the image is successfully loaded, else appropriate error value. */ int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size); + +/** + * rproc_elf64_load_image() - load an ELF64 image + * @dev: device loading the ELF64 image + * @addr: valid ELF64 image address + * @size: size of the image + * @return 0 if the image is successfully loaded, else appropriate error value. + */ +int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size); #else static inline int rproc_init(void) { return -ENOSYS; } static inline int rproc_dev_init(int id) { return -ENOSYS; } @@ -234,9 +255,14 @@ static inline int rproc_ping(int id) { return -ENOSYS; } static inline int rproc_is_running(int id) { return -ENOSYS; } static inline int rproc_elf32_sanity_check(ulong addr, ulong size) { return -ENOSYS; } +static inline int rproc_elf64_sanity_check(ulong addr, + ulong size) { return -ENOSYS; } static inline int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size) { return -ENOSYS; } +static inline int rproc_elf64_load_image(struct udevice *dev, ulong addr, + ulong size) +{ return -ENOSYS; } #endif #endif /* _RPROC_H_ */ From 856c0ad413f52d20963ef6b0fe982a0ca91086f2 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:30 +0530 Subject: [PATCH 12/58] remoteproc: elf_loader: Introduce a common elf loader and checker functions Introduce a common remoteproc elf loader and checker functions that automatically detects the 64 bit elf file or 32 bit elf file and loads/checks the sections accordingly. Signed-off-by: Lokesh Vutla Reviewed-by: Fabien Dessenne --- drivers/remoteproc/rproc-elf-loader.c | 31 +++++++++++++++++++++++++++ include/remoteproc.h | 29 +++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c index 1aece2fc31..42a78f4207 100644 --- a/drivers/remoteproc/rproc-elf-loader.c +++ b/drivers/remoteproc/rproc-elf-loader.c @@ -120,6 +120,22 @@ int rproc_elf64_sanity_check(ulong addr, ulong size) return 0; } +/* Basic function to verify ELF image format */ +int rproc_elf_sanity_check(ulong addr, ulong size) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr; + + if (!addr) { + dev_err(dev, "Invalid firmware address\n"); + return -EFAULT; + } + + if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) + return rproc_elf64_sanity_check(addr, size); + else + return rproc_elf32_sanity_check(addr, size); +} + int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size) { Elf32_Ehdr *ehdr; /* Elf header structure pointer */ @@ -220,3 +236,18 @@ int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size) return ret; } + +int rproc_elf_load_image(struct udevice *dev, ulong addr, ulong size) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr; + + if (!addr) { + dev_err(dev, "Invalid firmware address\n"); + return -EFAULT; + } + + if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) + return rproc_elf64_load_image(dev, addr, size); + else + return rproc_elf32_load_image(dev, addr, size); +} diff --git a/include/remoteproc.h b/include/remoteproc.h index 56a11db6e3..812e0f47c4 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -226,6 +226,19 @@ int rproc_elf32_sanity_check(ulong addr, ulong size); */ int rproc_elf64_sanity_check(ulong addr, ulong size); +/** + * rproc_elf_sanity_check() - Verify if an image is a valid ELF one + * + * Check if a valid ELF image exists at the given memory location. Auto + * detects ELF32/ELF64 and verifies basic ELF64/ELF32 format requirements + * like magic number and sections size. + * + * @addr: address of the image to verify + * @size: size of the image + * @return 0 if the image looks good, else appropriate error value. + */ +int rproc_elf_sanity_check(ulong addr, ulong size); + /** * rproc_elf32_load_image() - load an ELF32 image * @dev: device loading the ELF32 image @@ -243,6 +256,17 @@ int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size); * @return 0 if the image is successfully loaded, else appropriate error value. */ int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size); + +/** + * rproc_elf_load_image() - load an ELF image + * @dev: device loading the ELF image + * @addr: valid ELF image address + * @size: size of the image + * + * Auto detects if the image is ELF32 or ELF64 image and load accordingly. + * @return 0 if the image is successfully loaded, else appropriate error value. + */ +int rproc_elf_load_image(struct udevice *dev, unsigned long addr, ulong size); #else static inline int rproc_init(void) { return -ENOSYS; } static inline int rproc_dev_init(int id) { return -ENOSYS; } @@ -257,12 +281,17 @@ static inline int rproc_elf32_sanity_check(ulong addr, ulong size) { return -ENOSYS; } static inline int rproc_elf64_sanity_check(ulong addr, ulong size) { return -ENOSYS; } +static inline int rproc_elf_sanity_check(ulong addr, + ulong size) { return -ENOSYS; } static inline int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size) { return -ENOSYS; } static inline int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size) { return -ENOSYS; } +static inline int rproc_elf_load_image(struct udevice *dev, ulong addr, + ulong size) +{ return -ENOSYS; } #endif #endif /* _RPROC_H_ */ From 81e39fbd9251bfbef3bc156735e95b67cd7a828f Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:31 +0530 Subject: [PATCH 13/58] remoteproc: elf_loader: Introduce rproc_elf_get_boot_addr() api Introduce rproc_elf_get_boot_addr() that returns the entry point of the elf file. This api auto detects the 64/32 bit elf file and returns the boot addr accordingly. Signed-off-by: Lokesh Vutla --- drivers/remoteproc/rproc-elf-loader.c | 24 ++++++++++++++++++++++++ include/remoteproc.h | 12 ++++++++++++ test/dm/remoteproc.c | 2 ++ 3 files changed, 38 insertions(+) diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c index 42a78f4207..b38a226065 100644 --- a/drivers/remoteproc/rproc-elf-loader.c +++ b/drivers/remoteproc/rproc-elf-loader.c @@ -251,3 +251,27 @@ int rproc_elf_load_image(struct udevice *dev, ulong addr, ulong size) else return rproc_elf32_load_image(dev, addr, size); } + +static ulong rproc_elf32_get_boot_addr(ulong addr) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr; + + return ehdr->e_entry; +} + +static ulong rproc_elf64_get_boot_addr(ulong addr) +{ + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)addr; + + return ehdr->e_entry; +} + +ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr; + + if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) + return rproc_elf64_get_boot_addr(addr); + else + return rproc_elf32_get_boot_addr(addr); +} diff --git a/include/remoteproc.h b/include/remoteproc.h index 812e0f47c4..046cd9e54e 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -267,6 +267,16 @@ int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size); * @return 0 if the image is successfully loaded, else appropriate error value. */ int rproc_elf_load_image(struct udevice *dev, unsigned long addr, ulong size); + +/** + * rproc_elf_get_boot_addr() - Get rproc's boot address. + * @dev: device loading the ELF image + * @addr: valid ELF image address + * + * This function returns the entry point address of the ELF + * image. + */ +ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr); #else static inline int rproc_init(void) { return -ENOSYS; } static inline int rproc_dev_init(int id) { return -ENOSYS; } @@ -292,6 +302,8 @@ static inline int rproc_elf64_load_image(struct udevice *dev, ulong addr, static inline int rproc_elf_load_image(struct udevice *dev, ulong addr, ulong size) { return -ENOSYS; } +static inline ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr) +{ return 0; } #endif #endif /* _RPROC_H_ */ diff --git a/test/dm/remoteproc.c b/test/dm/remoteproc.c index c77361c8f4..1d9a9b32d5 100644 --- a/test/dm/remoteproc.c +++ b/test/dm/remoteproc.c @@ -174,6 +174,8 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) /* Load firmware in loaded_firmware, and verify it */ ut_assertok(rproc_elf32_load_image(dev, (ulong)valid_elf32, size)); ut_assertok(memcmp(loaded_firmware, valid_elf32, loaded_firmware_size)); + ut_asserteq(rproc_elf_get_boot_addr(dev, (unsigned long)valid_elf32), + 0x08000000); unmap_physmem(loaded_firmware, MAP_NOCACHE); /* Invalid ELF Magic */ From f7954828b8d0defeb6a10371f070ecd29ed192dd Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:32 +0530 Subject: [PATCH 14/58] remoteproc: tisci_proc: Add helper api for controlling core power domain Power domain for the remote cores needs to be handled in a right sequence as mandated by the spec. Introduce tisci helper apis that can control power-domains of remote cores. TISCI clients can use this api and control the remote cores power domain instead of hooking it to power-domain layer. Signed-off-by: Lokesh Vutla --- drivers/remoteproc/ti_sci_proc.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/remoteproc/ti_sci_proc.h b/drivers/remoteproc/ti_sci_proc.h index ccfc39ec88..f8299d1aff 100644 --- a/drivers/remoteproc/ti_sci_proc.h +++ b/drivers/remoteproc/ti_sci_proc.h @@ -19,12 +19,14 @@ * @proc_id: processor id for the consumer remoteproc device * @host_id: host id to pass the control over for this consumer remoteproc * device + * @dev_id: Device ID as identified by system controller. */ struct ti_sci_proc { const struct ti_sci_handle *sci; const struct ti_sci_proc_ops *ops; u8 proc_id; u8 host_id; + u16 dev_id; }; static inline int ti_sci_proc_request(struct ti_sci_proc *tsp) @@ -118,4 +120,29 @@ static inline int ti_sci_proc_set_control(struct ti_sci_proc *tsp, return ret; } +static inline int ti_sci_proc_power_domain_on(struct ti_sci_proc *tsp) +{ + int ret; + + debug("%s: dev_id = %d\n", __func__, tsp->dev_id); + + ret = tsp->sci->ops.dev_ops.get_device_exclusive(tsp->sci, tsp->dev_id); + if (ret) + pr_err("Power-domain on failed for dev = %d\n", tsp->dev_id); + + return ret; +} + +static inline int ti_sci_proc_power_domain_off(struct ti_sci_proc *tsp) +{ + int ret; + + debug("%s: dev_id = %d\n", __func__, tsp->dev_id); + + ret = tsp->sci->ops.dev_ops.put_device(tsp->sci, tsp->dev_id); + if (ret) + pr_err("Power-domain off failed for dev = %d\n", tsp->dev_id); + + return ret; +} #endif /* REMOTEPROC_TI_SCI_PROC_H */ From 471c2d5e22398d356ad653cfbc1303f01c0edbed Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 4 Sep 2019 16:01:33 +0530 Subject: [PATCH 15/58] dt-bindings: remoteproc: Add bindings for R5F subsystem on TI K3 SoCs The Texas Instruments K3 family of SoCs have one of more dual-core Arm Cortex R5F processor subsystems/clusters (R5FSS). Add the device tree bindings document for these R5F subsystem devices. These R5F processors do not have an MMU, and so require fixed memory carveout regions matching the firmware image addresses. The nodes require more than one memory region, with the first memory region used for DMA allocations at runtime. The remaining memory regions are reserved and are used for the loading and running of the R5F remote processors. The added example illustrates the DT nodes for the single R5FSS device present on K3 AM65x family of SoCs. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- .../remoteproc/ti,k3-r5f-rproc.txt | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 doc/device-tree-bindings/remoteproc/ti,k3-r5f-rproc.txt diff --git a/doc/device-tree-bindings/remoteproc/ti,k3-r5f-rproc.txt b/doc/device-tree-bindings/remoteproc/ti,k3-r5f-rproc.txt new file mode 100644 index 0000000000..c2fa6e8344 --- /dev/null +++ b/doc/device-tree-bindings/remoteproc/ti,k3-r5f-rproc.txt @@ -0,0 +1,164 @@ +TI K3 R5F processor subsystems +============================== + +The TI K3 family of SoCs usually have one or more dual-core Arm Cortex +R5F processor subsystems/clusters (R5FSS). The dual core cluster can be +used either in a LockStep mode providing safety/fault tolerance features +or in a Split mode providing two individual compute cores for doubling +the compute capacity. These are used together with other processors +present on the SoC to achieve various system level goals. + +R5F Sub-System Device Node: +=========================== +Each Dual-Core R5F sub-system is represented as a single DTS node representing +the cluster, with a pair of child DT nodes representing the individual R5F +cores. Each node has a number of required or optional properties that enable +the OS running on the host processor to perform the device management of the +remote processor and to communicate with the remote processor. + +Required properties: +-------------------- +The following are the mandatory properties: + +- compatible: Should be one of the following, + "ti,am654-r5fss" for R5F clusters/subsystems on + K3 AM65x SoCs + "ti,j721e-r5fss" for R5F clusters/subsystems on + K3 J721E SoCs +- power-domains: Should contain a phandle to a PM domain provider node + and an args specifier containing the R5FSS device id + value. This property is as per the binding, + Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt +- #address-cells: Should be 1 +- #size-cells: Should be 1 +- ranges: Standard ranges definition providing translations for + R5F TCM address spaces + +Optional properties: +-------------------- +- lockstep-mode: Configuration Mode for the Dual R5F cores within the R5F + cluster. Should be either a value of 1 (LockStep mode) or + 0 (Split mode), default is LockStep mode if omitted. + + +R5F Processor Child Nodes: +========================== +The R5F Sub-System device node should define two R5F child nodes, each node +representing a TI instantiation of the Arm Cortex R5F core. There are some +specific integration differences for the IP like the usage of a Region Address +Translator (RAT) for translating the larger SoC bus addresses into a 32-bit +address space for the processor. + +Required properties: +-------------------- +The following are the mandatory properties: + +- compatible: Should be one of the following, + "ti,am654-r5f" for the R5F cores in K3 AM65x SoCs + "ti,j721e-r5f" for the R5F cores in K3 J721E SOCs +- reg: Should contain an entry for each value in 'reg-names'. + Each entry should have the memory region's start address + and the size of the region, the representation matching + the parent node's '#address-cells' and '#size-cells' values. +- reg-names: Should contain strings with the following names, each + representing a specific internal memory region, and + should be defined in this order, + "atcm", "btcm" +- ti,sci: Should be a phandle to the TI-SCI System Controller node +- ti,sci-dev-id: Should contain the TI-SCI device id corresponding to the + R5F Core. Please refer to the corresponding System + Controller documentation for valid values for the R5F + cores. +- ti,sci-proc-ids: Should contain 2 integer values. The first cell should + contain the TI-SCI processor id for the R5F core device + and the second cell should contain the TI-SCI host id to + which the processor control ownership should be + transferred to. +- resets: Should contain the phandle to the reset controller node + managing the resets for this device, and a reset + specifier. Please refer to the following reset bindings + for the reset argument specifier, + Documentation/devicetree/bindings/reset/ti,sci-reset.txt + for AM65x and J721E SoCs + +Optional properties: +-------------------- +The following properties are optional properties for each of the R5F cores: + +- atcm-enable: R5F core configuration mode dictating if ATCM should be + enabled. Should be either a value of 1 (enabled) or + 0 (disabled), default is disabled if omitted. R5F view + of ATCM dictated by loczrama property. +- btcm-enable: R5F core configuration mode dictating if BTCM should be + enabled. Should be either a value of 1 (enabled) or + 0 (disabled), default is enabled if omitted. R5F view + of BTCM dictated by loczrama property. +- loczrama: R5F core configuration mode dictating which TCM should + appear at address 0 (from core's view). Should be either + a value of 1 (ATCM at 0x0) or 0 (BTCM at 0x0), default + value is 1 if omitted. + +Example: +-------- +1. AM654 SoC + /* AM65x remoteproc alias */ + aliases { + remoteproc0 = &mcu_r5fss0_core0; + }; + + cbass_main: interconnect@100000 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x41000000 0x00 0x41000000 0x00 0x00020000>, + <0x00 0x41400000 0x00 0x41400000 0x00 0x00020000>, + <0x00 0x41c00000 0x00 0x41c00000 0x00 0x00080000>; + + cbass_mcu: interconnect@28380000 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x41000000 0x00 0x41000000 0x00 0x00020000>, /* MCU R5F Core0 */ + <0x00 0x41400000 0x00 0x41400000 0x00 0x00020000>, /* MCU R5F Core1 */ + <0x00 0x41c00000 0x00 0x41c00000 0x00 0x00080000>; /* MCU SRAM */ + + /* AM65x MCU R5FSS node */ + mcu_r5fss0: r5fss@41000000 { + compatible = "ti,am654-r5fss"; + power-domains = <&k3_pds 129>; + lockstep-mode = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x41000000 0x00 0x41000000 0x20000>, + <0x41400000 0x00 0x41400000 0x20000>; + + mcu_r5f0: r5f@41000000 { + compatible = "ti,am654-r5f"; + reg = <0x41000000 0x00008000>, + <0x41010000 0x00008000>; + reg-names = "atcm", "btcm"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <159>; + ti,sci-proc-ids = <0x01 0xFF>; + resets = <&k3_reset 159 1>; + atcm-enable = <1>; + btcm-enable = <1>; + loczrama = <1>; + }; + + mcu_r5f1: r5f@41400000 { + compatible = "ti,am654-r5f"; + reg = <0x41400000 0x00008000>, + <0x41410000 0x00008000>; + reg-names = "atcm", "btcm"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <245>; + ti,sci-proc-ids = <0x02 0xFF>; + resets = <&k3_reset 245 1>; + atcm-enable = <1>; + btcm-enable = <1>; + loczrama = <1>; + }; + }; + }; + }; From 4c850356a83f170c69da96dda64fd440f766424e Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:34 +0530 Subject: [PATCH 16/58] remoteproc: Introduce K3 remoteproc driver for R5F subsystem SoCs with K3 architecture have an integrated Arm Cortex-R5F subsystem that is comprised of dual-core Arm Cortex-R5F processor cores. This R5 subsytem can be configured at boot time to be either run in a LockStep mode or in an Asymmetric Multi Processing (AMP) fashion in Split-mode. This subsystem has each Tightly-Coupled Memory (TCM) internal memories for each core split between two banks - TCMA and TCMB. Add a remoteproc driver to support this subsystem to be able to load and boot the R5 cores primarily in LockStep mode or split mode. Signed-off-by: Lokesh Vutla Signed-off-by: Suman Anna --- drivers/remoteproc/Kconfig | 10 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/ti_k3_r5f_rproc.c | 816 +++++++++++++++++++++++++++ 3 files changed, 827 insertions(+) create mode 100644 drivers/remoteproc/ti_k3_r5f_rproc.c diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index f54a245424..c2d59ba000 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -52,6 +52,16 @@ config REMOTEPROC_TI_K3_ARM64 on various TI K3 family of SoCs through the remote processor framework. +config REMOTEPROC_TI_K3_R5F + bool "TI K3 R5F remoteproc support" + select REMOTEPROC + depends on ARCH_K3 + depends on TI_SCI_PROTOCOL + help + Say y here to support TI's R5F remote processor subsystems + on various TI K3 family of SoCs through the remote processor + framework. + config REMOTEPROC_TI_POWER bool "Support for TI Power processor" select REMOTEPROC diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 271ba55b09..9d247ba5e7 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -11,4 +11,5 @@ obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o obj-$(CONFIG_REMOTEPROC_TI_K3_ARM64) += ti_k3_arm64_rproc.o +obj-$(CONFIG_REMOTEPROC_TI_K3_R5F) += ti_k3_r5f_rproc.o obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o diff --git a/drivers/remoteproc/ti_k3_r5f_rproc.c b/drivers/remoteproc/ti_k3_r5f_rproc.c new file mode 100644 index 0000000000..ae1e4b9e04 --- /dev/null +++ b/drivers/remoteproc/ti_k3_r5f_rproc.c @@ -0,0 +1,816 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments' K3 R5 Remoteproc driver + * + * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ti_sci_proc.h" + +/* + * R5F's view of this address can either be for ATCM or BTCM with the other + * at address 0x0 based on loczrama signal. + */ +#define K3_R5_TCM_DEV_ADDR 0x41010000 + +/* R5 TI-SCI Processor Configuration Flags */ +#define PROC_BOOT_CFG_FLAG_R5_DBG_EN 0x00000001 +#define PROC_BOOT_CFG_FLAG_R5_DBG_NIDEN 0x00000002 +#define PROC_BOOT_CFG_FLAG_R5_LOCKSTEP 0x00000100 +#define PROC_BOOT_CFG_FLAG_R5_TEINIT 0x00000200 +#define PROC_BOOT_CFG_FLAG_R5_NMFI_EN 0x00000400 +#define PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE 0x00000800 +#define PROC_BOOT_CFG_FLAG_R5_BTCM_EN 0x00001000 +#define PROC_BOOT_CFG_FLAG_R5_ATCM_EN 0x00002000 +#define PROC_BOOT_CFG_FLAG_GEN_IGN_BOOTVECTOR 0x10000000 + +/* R5 TI-SCI Processor Control Flags */ +#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001 + +/* R5 TI-SCI Processor Status Flags */ +#define PROC_BOOT_STATUS_FLAG_R5_WFE 0x00000001 +#define PROC_BOOT_STATUS_FLAG_R5_WFI 0x00000002 +#define PROC_BOOT_STATUS_FLAG_R5_CLK_GATED 0x00000004 +#define PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED 0x00000100 + +#define NR_CORES 2 + +enum cluster_mode { + CLUSTER_MODE_SPLIT = 0, + CLUSTER_MODE_LOCKSTEP, +}; + +/** + * struct k3_r5_mem - internal memory structure + * @cpu_addr: MPU virtual address of the memory region + * @bus_addr: Bus address used to access the memory region + * @dev_addr: Device address from remoteproc view + * @size: Size of the memory region + */ +struct k3_r5f_mem { + void __iomem *cpu_addr; + phys_addr_t bus_addr; + u32 dev_addr; + size_t size; +}; + +/** + * struct k3_r5f_core - K3 R5 core structure + * @dev: cached device pointer + * @cluster: pointer to the parent cluster. + * @reset: reset control handle + * @tsp: TI-SCI processor control handle + * @mem: Array of available internal memories + * @num_mem: Number of available memories + * @atcm_enable: flag to control ATCM enablement + * @btcm_enable: flag to control BTCM enablement + * @loczrama: flag to dictate which TCM is at device address 0x0 + * @in_use: flag to tell if the core is already in use. + */ +struct k3_r5f_core { + struct udevice *dev; + struct k3_r5f_cluster *cluster; + struct reset_ctl reset; + struct ti_sci_proc tsp; + struct k3_r5f_mem *mem; + int num_mems; + u32 atcm_enable; + u32 btcm_enable; + u32 loczrama; + bool in_use; +}; + +/** + * struct k3_r5f_cluster - K3 R5F Cluster structure + * @mode: Mode to configure the Cluster - Split or LockStep + * @cores: Array of pointers to R5 cores within the cluster + */ +struct k3_r5f_cluster { + enum cluster_mode mode; + struct k3_r5f_core *cores[NR_CORES]; +}; + +static bool is_primary_core(struct k3_r5f_core *core) +{ + return core == core->cluster->cores[0]; +} + +static int k3_r5f_proc_request(struct k3_r5f_core *core) +{ + struct k3_r5f_cluster *cluster = core->cluster; + int i, ret; + + if (cluster->mode == CLUSTER_MODE_LOCKSTEP) { + for (i = 0; i < NR_CORES; i++) { + ret = ti_sci_proc_request(&cluster->cores[i]->tsp); + if (ret) + goto proc_release; + } + } else { + ret = ti_sci_proc_request(&core->tsp); + } + + return 0; + +proc_release: + while (i >= 0) { + ti_sci_proc_release(&cluster->cores[i]->tsp); + i--; + } + return ret; +} + +static void k3_r5f_proc_release(struct k3_r5f_core *core) +{ + struct k3_r5f_cluster *cluster = core->cluster; + int i; + + if (cluster->mode == CLUSTER_MODE_LOCKSTEP) + for (i = 0; i < NR_CORES; i++) + ti_sci_proc_release(&cluster->cores[i]->tsp); + else + ti_sci_proc_release(&core->tsp); +} + +static int k3_r5f_lockstep_release(struct k3_r5f_cluster *cluster) +{ + int ret, c; + + dev_dbg(dev, "%s\n", __func__); + + for (c = NR_CORES - 1; c >= 0; c--) { + ret = ti_sci_proc_power_domain_on(&cluster->cores[c]->tsp); + if (ret) + goto unroll_module_reset; + } + + /* deassert local reset on all applicable cores */ + for (c = NR_CORES - 1; c >= 0; c--) { + ret = reset_deassert(&cluster->cores[c]->reset); + if (ret) + goto unroll_local_reset; + } + + return 0; + +unroll_local_reset: + while (c < NR_CORES) { + reset_assert(&cluster->cores[c]->reset); + c++; + } + c = 0; +unroll_module_reset: + while (c < NR_CORES) { + ti_sci_proc_power_domain_off(&cluster->cores[c]->tsp); + c++; + } + + return ret; +} + +static int k3_r5f_split_release(struct k3_r5f_core *core) +{ + int ret; + + dev_dbg(dev, "%s\n", __func__); + + ret = ti_sci_proc_power_domain_on(&core->tsp); + if (ret) { + dev_err(core->dev, "module-reset deassert failed, ret = %d\n", + ret); + return ret; + } + + ret = reset_deassert(&core->reset); + if (ret) { + dev_err(core->dev, "local-reset deassert failed, ret = %d\n", + ret); + if (ti_sci_proc_power_domain_off(&core->tsp)) + dev_warn(core->dev, "module-reset assert back failed\n"); + } + + return ret; +} + +static int k3_r5f_prepare(struct udevice *dev) +{ + struct k3_r5f_core *core = dev_get_priv(dev); + struct k3_r5f_cluster *cluster = core->cluster; + int ret = 0; + + dev_dbg(dev, "%s\n", __func__); + + if (cluster->mode == CLUSTER_MODE_LOCKSTEP) + ret = k3_r5f_lockstep_release(cluster); + else + ret = k3_r5f_split_release(core); + + if (ret) + dev_err(dev, "Unable to enable cores for TCM loading %d\n", + ret); + + return ret; +} + +static int k3_r5f_core_sanity_check(struct k3_r5f_core *core) +{ + struct k3_r5f_cluster *cluster = core->cluster; + + if (core->in_use) { + dev_err(dev, "Invalid op: Trying to load/start on already running core %d\n", + core->tsp.proc_id); + return -EINVAL; + } + + if (cluster->mode == CLUSTER_MODE_LOCKSTEP && !cluster->cores[1]) { + printf("Secondary core is not probed in this cluster\n"); + return -EAGAIN; + } + + if (cluster->mode == CLUSTER_MODE_LOCKSTEP && !is_primary_core(core)) { + dev_err(dev, "Invalid op: Trying to start secondary core %d in lockstep mode\n", + core->tsp.proc_id); + return -EINVAL; + } + + if (cluster->mode == CLUSTER_MODE_SPLIT && !is_primary_core(core)) { + if (!core->cluster->cores[0]->in_use) { + dev_err(dev, "Invalid seq: Enable primary core before loading secondary core\n"); + return -EINVAL; + } + } + + return 0; +} + +/** + * k3_r5f_load() - Load up the Remote processor image + * @dev: rproc device pointer + * @addr: Address at which image is available + * @size: size of the image + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_r5f_load(struct udevice *dev, ulong addr, ulong size) +{ + struct k3_r5f_core *core = dev_get_priv(dev); + u32 boot_vector; + int ret; + + dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size); + + ret = k3_r5f_core_sanity_check(core); + if (ret) + return ret; + + ret = k3_r5f_proc_request(core); + if (ret) + return ret; + + ret = k3_r5f_prepare(dev); + if (ret) { + dev_err(dev, "R5f prepare failed for core %d\n", + core->tsp.proc_id); + goto proc_release; + } + + /* Zero out TCMs so that ECC can be effective on all TCM addresses */ + if (core->atcm_enable) + memset(core->mem[0].cpu_addr, 0x00, core->mem[0].size); + if (core->btcm_enable) + memset(core->mem[1].cpu_addr, 0x00, core->mem[1].size); + + ret = rproc_elf_load_image(dev, addr, size); + if (ret < 0) { + dev_err(dev, "Loading elf failedi %d\n", ret); + goto proc_release; + } + + boot_vector = rproc_elf_get_boot_addr(dev, addr); + + dev_dbg(dev, "%s: Boot vector = 0x%x\n", __func__, boot_vector); + + ret = ti_sci_proc_set_config(&core->tsp, boot_vector, 0, 0); + +proc_release: + k3_r5f_proc_release(core); + + return ret; +} + +static int k3_r5f_core_halt(struct k3_r5f_core *core) +{ + int ret; + + ret = ti_sci_proc_set_control(&core->tsp, + PROC_BOOT_CTRL_FLAG_R5_CORE_HALT, 0); + if (ret) + dev_err(core->dev, "Core %d failed to stop\n", + core->tsp.proc_id); + + return ret; +} + +static int k3_r5f_core_run(struct k3_r5f_core *core) +{ + int ret; + + ret = ti_sci_proc_set_control(&core->tsp, + 0, PROC_BOOT_CTRL_FLAG_R5_CORE_HALT); + if (ret) { + dev_err(core->dev, "Core %d failed to start\n", + core->tsp.proc_id); + return ret; + } + + return 0; +} + +/** + * k3_r5f_start() - Start the remote processor + * @dev: rproc device pointer + * + * Return: 0 if all went ok, else return appropriate error + */ +static int k3_r5f_start(struct udevice *dev) +{ + struct k3_r5f_core *core = dev_get_priv(dev); + struct k3_r5f_cluster *cluster = core->cluster; + int ret, c; + + dev_dbg(dev, "%s\n", __func__); + + ret = k3_r5f_core_sanity_check(core); + if (ret) + return ret; + + ret = k3_r5f_proc_request(core); + if (ret) + return ret; + + if (cluster->mode == CLUSTER_MODE_LOCKSTEP) { + if (is_primary_core(core)) { + for (c = NR_CORES - 1; c >= 0; c--) { + ret = k3_r5f_core_run(cluster->cores[c]); + if (ret) + goto unroll_core_run; + } + } else { + dev_err(dev, "Invalid op: Trying to start secondary core %d in lockstep mode\n", + core->tsp.proc_id); + ret = -EINVAL; + goto proc_release; + } + } else { + ret = k3_r5f_core_run(core); + if (ret) + goto proc_release; + } + + core->in_use = true; + + k3_r5f_proc_release(core); + return 0; + +unroll_core_run: + while (c < NR_CORES) { + k3_r5f_core_halt(cluster->cores[c]); + c++; + } +proc_release: + k3_r5f_proc_release(core); + + return ret; +} + +static int k3_r5f_split_reset(struct k3_r5f_core *core) +{ + int ret; + + dev_dbg(dev, "%s\n", __func__); + + if (reset_assert(&core->reset)) + ret = -EINVAL; + + if (ti_sci_proc_power_domain_off(&core->tsp)) + ret = -EINVAL; + + return ret; +} + +static int k3_r5f_lockstep_reset(struct k3_r5f_cluster *cluster) +{ + int ret = 0, c; + + dev_dbg(dev, "%s\n", __func__); + + for (c = 0; c < NR_CORES; c++) + if (reset_assert(&cluster->cores[c]->reset)) + ret = -EINVAL; + + /* disable PSC modules on all applicable cores */ + for (c = 0; c < NR_CORES; c++) + if (ti_sci_proc_power_domain_off(&cluster->cores[c]->tsp)) + ret = -EINVAL; + + return ret; +} + +static int k3_r5f_unprepare(struct udevice *dev) +{ + struct k3_r5f_core *core = dev_get_priv(dev); + struct k3_r5f_cluster *cluster = core->cluster; + int ret; + + dev_dbg(dev, "%s\n", __func__); + + if (cluster->mode == CLUSTER_MODE_LOCKSTEP) { + if (is_primary_core(core)) + ret = k3_r5f_lockstep_reset(cluster); + } else { + ret = k3_r5f_split_reset(core); + } + + if (ret) + dev_warn(dev, "Unable to enable cores for TCM loading %d\n", + ret); + + return 0; +} + +static int k3_r5f_stop(struct udevice *dev) +{ + struct k3_r5f_core *core = dev_get_priv(dev); + struct k3_r5f_cluster *cluster = core->cluster; + int c, ret; + + dev_dbg(dev, "%s\n", __func__); + + ret = k3_r5f_proc_request(core); + if (ret) + return ret; + + core->in_use = false; + + if (cluster->mode == CLUSTER_MODE_LOCKSTEP) { + if (is_primary_core(core)) { + for (c = 0; c < NR_CORES; c++) + k3_r5f_core_halt(cluster->cores[c]); + } else { + dev_err(dev, "Invalid op: Trying to stop secondary core in lockstep mode\n"); + ret = -EINVAL; + goto proc_release; + } + } else { + k3_r5f_core_halt(core); + } + + ret = k3_r5f_unprepare(dev); +proc_release: + k3_r5f_proc_release(core); + return ret; +} + +static void *k3_r5f_da_to_va(struct udevice *dev, ulong da, ulong size) +{ + struct k3_r5f_core *core = dev_get_priv(dev); + void __iomem *va = NULL; + phys_addr_t bus_addr; + u32 dev_addr, offset; + ulong mem_size; + int i; + + dev_dbg(dev, "%s\n", __func__); + + if (size <= 0) + return NULL; + + for (i = 0; i < core->num_mems; i++) { + bus_addr = core->mem[i].bus_addr; + dev_addr = core->mem[i].dev_addr; + mem_size = core->mem[i].size; + + if (da >= bus_addr && (da + size) <= (bus_addr + mem_size)) { + offset = da - bus_addr; + va = core->mem[i].cpu_addr + offset; + return (__force void *)va; + } + + if (da >= dev_addr && (da + size) <= (dev_addr + mem_size)) { + offset = da - dev_addr; + va = core->mem[i].cpu_addr + offset; + return (__force void *)va; + } + } + + /* Assume it is DDR region and return da */ + return map_physmem(da, size, MAP_NOCACHE); +} + +static int k3_r5f_init(struct udevice *dev) +{ + return 0; +} + +static int k3_r5f_reset(struct udevice *dev) +{ + return 0; +} + +static const struct dm_rproc_ops k3_r5f_rproc_ops = { + .init = k3_r5f_init, + .reset = k3_r5f_reset, + .start = k3_r5f_start, + .stop = k3_r5f_stop, + .load = k3_r5f_load, + .device_to_virt = k3_r5f_da_to_va, +}; + +static int k3_r5f_rproc_configure(struct k3_r5f_core *core) +{ + struct k3_r5f_cluster *cluster = core->cluster; + u32 set_cfg = 0, clr_cfg = 0, cfg, ctrl, sts; + u64 boot_vec = 0; + int ret; + + dev_dbg(dev, "%s\n", __func__); + + ret = ti_sci_proc_request(&core->tsp); + if (ret < 0) + return ret; + + /* Do not touch boot vector now. Load will take care of it. */ + clr_cfg |= PROC_BOOT_CFG_FLAG_GEN_IGN_BOOTVECTOR; + + ret = ti_sci_proc_get_status(&core->tsp, &boot_vec, &cfg, &ctrl, &sts); + if (ret) + goto out; + + /* Sanity check for Lockstep mode */ + if (cluster->mode && is_primary_core(core) && + !(sts & PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED)) { + dev_err(core->dev, "LockStep mode not permitted on this device\n"); + ret = -EINVAL; + goto out; + } + + /* Primary core only configuration */ + if (is_primary_core(core)) { + /* always enable ARM mode */ + clr_cfg |= PROC_BOOT_CFG_FLAG_R5_TEINIT; + if (cluster->mode == CLUSTER_MODE_LOCKSTEP) + set_cfg |= PROC_BOOT_CFG_FLAG_R5_LOCKSTEP; + else + clr_cfg |= PROC_BOOT_CFG_FLAG_R5_LOCKSTEP; + } + + if (core->atcm_enable) + set_cfg |= PROC_BOOT_CFG_FLAG_R5_ATCM_EN; + else + clr_cfg |= PROC_BOOT_CFG_FLAG_R5_ATCM_EN; + + if (core->btcm_enable) + set_cfg |= PROC_BOOT_CFG_FLAG_R5_BTCM_EN; + else + clr_cfg |= PROC_BOOT_CFG_FLAG_R5_BTCM_EN; + + if (core->loczrama) + set_cfg |= PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE; + else + clr_cfg |= PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE; + + ret = k3_r5f_core_halt(core); + if (ret) + goto out; + + ret = ti_sci_proc_set_config(&core->tsp, boot_vec, set_cfg, clr_cfg); +out: + ti_sci_proc_release(&core->tsp); + return ret; +} + +static int ti_sci_proc_of_to_priv(struct udevice *dev, struct ti_sci_proc *tsp) +{ + u32 ids[2]; + int ret; + + dev_dbg(dev, "%s\n", __func__); + + tsp->sci = ti_sci_get_by_phandle(dev, "ti,sci"); + if (IS_ERR(tsp->sci)) { + dev_err(dev, "ti_sci get failed: %ld\n", PTR_ERR(tsp->sci)); + return PTR_ERR(tsp->sci); + } + + ret = dev_read_u32_array(dev, "ti,sci-proc-ids", ids, 2); + if (ret) { + dev_err(dev, "Proc IDs not populated %d\n", ret); + return ret; + } + + tsp->ops = &tsp->sci->ops.proc_ops; + tsp->proc_id = ids[0]; + tsp->host_id = ids[1]; + tsp->dev_id = dev_read_u32_default(dev, "ti,sci-dev-id", + TI_SCI_RESOURCE_NULL); + if (tsp->dev_id == TI_SCI_RESOURCE_NULL) { + dev_err(dev, "Device ID not populated %d\n", ret); + return -ENODEV; + } + + return 0; +} + +static int k3_r5f_of_to_priv(struct k3_r5f_core *core) +{ + int ret; + + dev_dbg(dev, "%s\n", __func__); + + core->atcm_enable = dev_read_u32_default(core->dev, "atcm-enable", 0); + core->btcm_enable = dev_read_u32_default(core->dev, "btcm-enable", 1); + core->loczrama = dev_read_u32_default(core->dev, "loczrama", 1); + + ret = ti_sci_proc_of_to_priv(core->dev, &core->tsp); + if (ret) + return ret; + + ret = reset_get_by_index(core->dev, 0, &core->reset); + if (ret) { + dev_err(core->dev, "Reset lines not available: %d\n", ret); + return ret; + } + + return 0; +} + +static int k3_r5f_core_of_get_memories(struct k3_r5f_core *core) +{ + static const char * const mem_names[] = {"atcm", "btcm"}; + struct udevice *dev = core->dev; + int i; + + dev_dbg(dev, "%s\n", __func__); + + core->num_mems = ARRAY_SIZE(mem_names); + core->mem = calloc(core->num_mems, sizeof(*core->mem)); + if (!core->mem) + return -ENOMEM; + + for (i = 0; i < core->num_mems; i++) { + core->mem[i].bus_addr = dev_read_addr_size_name(dev, + mem_names[i], + (fdt_addr_t *)&core->mem[i].size); + if (core->mem[i].bus_addr == FDT_ADDR_T_NONE) { + dev_err(dev, "%s bus address not found\n", + mem_names[i]); + return -EINVAL; + } + core->mem[i].cpu_addr = map_physmem(core->mem[i].bus_addr, + core->mem[i].size, + MAP_NOCACHE); + if (!strcmp(mem_names[i], "atcm")) { + core->mem[i].dev_addr = core->loczrama ? + 0 : K3_R5_TCM_DEV_ADDR; + } else { + core->mem[i].dev_addr = core->loczrama ? + K3_R5_TCM_DEV_ADDR : 0; + } + + dev_dbg(dev, "memory %8s: bus addr %pa size 0x%zx va %p da 0x%x\n", + mem_names[i], &core->mem[i].bus_addr, + core->mem[i].size, core->mem[i].cpu_addr, + core->mem[i].dev_addr); + } + + return 0; +} + +/** + * k3_r5f_probe() - Basic probe + * @dev: corresponding k3 remote processor device + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_r5f_probe(struct udevice *dev) +{ + struct k3_r5f_cluster *cluster = dev_get_priv(dev->parent); + struct k3_r5f_core *core = dev_get_priv(dev); + bool r_state; + int ret; + + dev_dbg(dev, "%s\n", __func__); + + core->dev = dev; + ret = k3_r5f_of_to_priv(core); + if (ret) + return ret; + + core->cluster = cluster; + /* Assume Primary core gets probed first */ + if (!cluster->cores[0]) + cluster->cores[0] = core; + else + cluster->cores[1] = core; + + ret = k3_r5f_core_of_get_memories(core); + if (ret) { + dev_err(dev, "Rproc getting internal memories failed\n"); + return ret; + } + + ret = core->tsp.sci->ops.dev_ops.is_on(core->tsp.sci, core->tsp.dev_id, + &r_state, &core->in_use); + if (ret) + return ret; + + if (core->in_use) { + dev_info(dev, "Core %d is already in use. No rproc commands work\n", + core->tsp.proc_id); + return 0; + } + + /* Make sure Local reset is asserted. Redundant? */ + reset_assert(&core->reset); + + ret = k3_r5f_rproc_configure(core); + if (ret) { + dev_err(dev, "rproc configure failed %d\n", ret); + return ret; + } + + dev_dbg(dev, "Remoteproc successfully probed\n"); + + return 0; +} + +static int k3_r5f_remove(struct udevice *dev) +{ + struct k3_r5f_core *core = dev_get_priv(dev); + + free(core->mem); + + ti_sci_proc_release(&core->tsp); + + return 0; +} + +static const struct udevice_id k3_r5f_rproc_ids[] = { + { .compatible = "ti,am654-r5f"}, + { .compatible = "ti,j721e-r5f"}, + {} +}; + +U_BOOT_DRIVER(k3_r5f_rproc) = { + .name = "k3_r5f_rproc", + .of_match = k3_r5f_rproc_ids, + .id = UCLASS_REMOTEPROC, + .ops = &k3_r5f_rproc_ops, + .probe = k3_r5f_probe, + .remove = k3_r5f_remove, + .priv_auto_alloc_size = sizeof(struct k3_r5f_core), +}; + +static int k3_r5f_cluster_probe(struct udevice *dev) +{ + struct k3_r5f_cluster *cluster = dev_get_priv(dev); + + dev_dbg(dev, "%s\n", __func__); + + cluster->mode = dev_read_u32_default(dev, "lockstep-mode", + CLUSTER_MODE_LOCKSTEP); + + if (device_get_child_count(dev) != 2) { + dev_err(dev, "Invalid number of R5 cores"); + return -EINVAL; + } + + dev_dbg(dev, "%s: Cluster successfully probed in %s mode\n", + __func__, cluster->mode ? "lockstep" : "split"); + + return 0; +} + +static const struct udevice_id k3_r5fss_ids[] = { + { .compatible = "ti,am654-r5fss"}, + { .compatible = "ti,j721e-r5fss"}, + {} +}; + +U_BOOT_DRIVER(k3_r5fss) = { + .name = "k3_r5fss", + .of_match = k3_r5fss_ids, + .id = UCLASS_MISC, + .probe = k3_r5f_cluster_probe, + .priv_auto_alloc_size = sizeof(struct k3_r5f_cluster), +}; From e18fb7dd5c00d2830f4c6acca2451032fe1b4870 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 4 Sep 2019 16:01:35 +0530 Subject: [PATCH 17/58] dt-bindings: remoteproc: Add bindings for DSP C66x clusters on TI K3 SoCs Some Texas Instruments K3 family of SoCs have one of more Digital Signal Processor (DSP) subsystems that are comprised of either a TMS320C66x CorePac and/or a next-generation TMS320C71x CorePac processor subsystem. Add the device tree bindings document for the C66x DSP devices on these SoCs. The added example illustrates the DT nodes for the first C66x DSP device present on the K3 J721E family of SoCs. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- .../remoteproc/ti,k3-dsp-rproc.txt | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 doc/device-tree-bindings/remoteproc/ti,k3-dsp-rproc.txt diff --git a/doc/device-tree-bindings/remoteproc/ti,k3-dsp-rproc.txt b/doc/device-tree-bindings/remoteproc/ti,k3-dsp-rproc.txt new file mode 100644 index 0000000000..80ab7a4090 --- /dev/null +++ b/doc/device-tree-bindings/remoteproc/ti,k3-dsp-rproc.txt @@ -0,0 +1,101 @@ +TI K3 DSP devices +================= + +The TI K3 family of SoCs usually have one or more TI DSP Core sub-systems that +are used to offload some of the processor-intensive tasks or algorithms, for +achieving various system level goals. + +These processor sub-systems usually contain additional sub-modules like L1 +and/or L2 caches/SRAMs, an Interrupt Controller, an external memory controller, +a dedicated local power/sleep controller etc. The DSP processor cores in the +K3 SoCs is usually either a TMS320C66x CorePac processor or a TMS320C71x CorePac +processor. + +DSP Device Node: +================ +Each DSP Core sub-system is represented as a single DT node. Each node has a +number of required or optional properties that enable the OS running on the +host processor (Arm CorePac) to perform the device management of the remote +processor and to communicate with the remote processor. + +Required properties: +-------------------- +The following are the mandatory properties: + +- compatible: Should be one of the following, + "ti,j721e-c66-dsp" for C66x DSPs on K3 J721E SoCs + "ti,j721e-c71-dsp" for C71x DSPs on K3 J721E SoCs + +- reg: Should contain an entry for each value in 'reg-names'. + Each entry should have the memory region's start address + and the size of the region, the representation matching + the parent node's '#address-cells' and '#size-cells' values. + +- reg-names: Should contain strings with the following names, each + representing a specific internal memory region (if + present), and should be defined in this order, + "l2sram", "l1pram", "l1dram" + NOTE: C71x DSPs do not have a "l1pram" memory. + +- ti,sci: Should be a phandle to the TI-SCI System Controller node + +- ti,sci-dev-id: Should contain the TI-SCI device id corresponding to the + DSP Core. Please refer to the corresponding System + Controller documentation for valid values for the DSP + cores. + +- ti,sci-proc-ids: Should contain 2 integer values. The first cell should + contain the TI-SCI processor id for the DSP core device + and the second cell should contain the TI-SCI host id to + which the processor control ownership should be + transferred to. + +- resets: Should contain the phandle to the reset controller node + managing the resets for this device, and a reset + specifier. Please refer to the following reset bindings + for the reset argument specifier, + Documentation/devicetree/bindings/reset/ti,sci-reset.txt + +Example: +--------- + +1. J721E SoC + /* J721E remoteproc alias */ + aliases { + rproc6 = &c66_0; + rproc8 = &c71_0; + }; + + cbass_main: interconnect@100000 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x64800000 0x00 0x64800000 0x00 0x00800000>, /* C71_0 */ + <0x4d 0x80800000 0x4d 0x80800000 0x00 0x00800000>, /* C66_0 */ + <0x4d 0x81800000 0x4d 0x81800000 0x00 0x00800000>; /* C66_1 */ + + /* J721E C66_0 DSP node */ + c66_0: dsp@4d80800000 { + compatible = "ti,j721e-c66-dsp"; + reg = <0x4d 0x80800000 0x00 0x00048000>, + <0x4d 0x80e00000 0x00 0x00008000>, + <0x4d 0x80f00000 0x00 0x00008000>; + reg-names = "l2sram", "l1pram", "l1dram"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <142>; + ti,sci-proc-ids = <0x03 0xFF>; + resets = <&k3_reset 142 1>; + }; + + /* J721E C71_0 DSP node */ + c71_0: dsp@64800000 { + compatible = "ti,j721e-c71-dsp"; + reg = <0x00 0x64800000 0x00 0x00080000>, + <0x00 0x64e00000 0x00 0x0000c000>; + reg-names = "l2sram", "l1dram"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <15>; + ti,sci-proc-ids = <0x30 0xFF>; + resets = <&k3_reset 15 1>; + }; + }; From ab827b385718be0aceefb9cd20108265ebb90572 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:36 +0530 Subject: [PATCH 18/58] remoteproc: Introduce K3 C66 and C71 remoteproc driver Certain SoCs with K3 architecture have integrated a C66 Corepac DSP subsystem and an advanced C71 DSPs. Introduce a remoteproc driver that that does take care of loading an elf to any of the specified DSPs and start it. Signed-off-by: Lokesh Vutla Signed-off-by: Suman Anna --- drivers/remoteproc/Kconfig | 10 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/ti_k3_dsp_rproc.c | 354 +++++++++++++++++++++++++++ 3 files changed, 365 insertions(+) create mode 100644 drivers/remoteproc/ti_k3_dsp_rproc.c diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index c2d59ba000..7c2e4804b5 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -52,6 +52,16 @@ config REMOTEPROC_TI_K3_ARM64 on various TI K3 family of SoCs through the remote processor framework. +config REMOTEPROC_TI_K3_DSP + bool "TI K3 C66 and C71 remoteproc support" + select REMOTEPROC + depends on ARCH_K3 + depends on TI_SCI_PROTOCOL + help + Say y here to support TI's C66/C71 remote processor subsystems + on various TI K3 family of SoCs through the remote processor + framework. + config REMOTEPROC_TI_K3_R5F bool "TI K3 R5F remoteproc support" select REMOTEPROC diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 9d247ba5e7..69ae7bd1e8 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -11,5 +11,6 @@ obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o obj-$(CONFIG_REMOTEPROC_TI_K3_ARM64) += ti_k3_arm64_rproc.o +obj-$(CONFIG_REMOTEPROC_TI_K3_DSP) += ti_k3_dsp_rproc.o obj-$(CONFIG_REMOTEPROC_TI_K3_R5F) += ti_k3_r5f_rproc.o obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o diff --git a/drivers/remoteproc/ti_k3_dsp_rproc.c b/drivers/remoteproc/ti_k3_dsp_rproc.c new file mode 100644 index 0000000000..c5dc6b25da --- /dev/null +++ b/drivers/remoteproc/ti_k3_dsp_rproc.c @@ -0,0 +1,354 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments' K3 DSP Remoteproc driver + * + * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ti_sci_proc.h" + +#define KEYSTONE_RPROC_LOCAL_ADDRESS_MASK (SZ_16M - 1) + +/** + * struct k3_dsp_mem - internal memory structure + * @cpu_addr: MPU virtual address of the memory region + * @bus_addr: Bus address used to access the memory region + * @dev_addr: Device address from remoteproc view + * @size: Size of the memory region + */ +struct k3_dsp_mem { + void __iomem *cpu_addr; + phys_addr_t bus_addr; + phys_addr_t dev_addr; + size_t size; +}; + +/** + * struct k3_dsp_privdata - Structure representing Remote processor data. + * @rproc_rst: rproc reset control data + * @tsp: Pointer to TISCI proc contrl handle + * @mem: Array of available memories + * @num_mem: Number of available memories + */ +struct k3_dsp_privdata { + struct reset_ctl dsp_rst; + struct ti_sci_proc tsp; + struct k3_dsp_mem *mem; + int num_mems; +}; + +/** + * k3_dsp_load() - Load up the Remote processor image + * @dev: rproc device pointer + * @addr: Address at which image is available + * @size: size of the image + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_dsp_load(struct udevice *dev, ulong addr, ulong size) +{ + struct k3_dsp_privdata *dsp = dev_get_priv(dev); + u32 boot_vector; + int ret; + + dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size); + ret = ti_sci_proc_request(&dsp->tsp); + if (ret) + return ret; + + ret = rproc_elf_load_image(dev, addr, size); + if (ret < 0) { + dev_err(dev, "Loading elf failed %d\n", ret); + goto proc_release; + } + + boot_vector = rproc_elf_get_boot_addr(dev, addr); + + dev_dbg(dev, "%s: Boot vector = 0x%x\n", __func__, boot_vector); + + ret = ti_sci_proc_set_config(&dsp->tsp, boot_vector, 0, 0); +proc_release: + ti_sci_proc_release(&dsp->tsp); + return ret; +} + +/** + * k3_dsp_start() - Start the remote processor + * @dev: rproc device pointer + * + * Return: 0 if all went ok, else return appropriate error + */ +static int k3_dsp_start(struct udevice *dev) +{ + struct k3_dsp_privdata *dsp = dev_get_priv(dev); + int ret; + + dev_dbg(dev, "%s\n", __func__); + + ret = ti_sci_proc_request(&dsp->tsp); + if (ret) + return ret; + /* + * Setting the right clock frequency would have taken care by + * assigned-clock-rates during the device probe. So no need to + * set the frequency again here. + */ + ret = ti_sci_proc_power_domain_on(&dsp->tsp); + if (ret) + goto proc_release; + + ret = reset_deassert(&dsp->dsp_rst); + +proc_release: + ti_sci_proc_release(&dsp->tsp); + + return ret; +} + +static int k3_dsp_stop(struct udevice *dev) +{ + struct k3_dsp_privdata *dsp = dev_get_priv(dev); + + dev_dbg(dev, "%s\n", __func__); + + ti_sci_proc_request(&dsp->tsp); + reset_assert(&dsp->dsp_rst); + ti_sci_proc_power_domain_off(&dsp->tsp); + ti_sci_proc_release(&dsp->tsp); + + return 0; +} + +/** + * k3_dsp_init() - Initialize the remote processor + * @dev: rproc device pointer + * + * Return: 0 if all went ok, else return appropriate error + */ +static int k3_dsp_init(struct udevice *dev) +{ + dev_dbg(dev, "%s\n", __func__); + + return 0; +} + +static int k3_dsp_reset(struct udevice *dev) +{ + dev_dbg(dev, "%s\n", __func__); + + return 0; +} + +static void *k3_dsp_da_to_va(struct udevice *dev, ulong da, ulong len) +{ + struct k3_dsp_privdata *dsp = dev_get_priv(dev); + phys_addr_t bus_addr, dev_addr; + void __iomem *va = NULL; + size_t size; + u32 offset; + int i; + + dev_dbg(dev, "%s\n", __func__); + + if (len <= 0) + return NULL; + + for (i = 0; i < dsp->num_mems; i++) { + bus_addr = dsp->mem[i].bus_addr; + dev_addr = dsp->mem[i].dev_addr; + size = dsp->mem[i].size; + + if (da >= dev_addr && ((da + len) <= (dev_addr + size))) { + offset = da - dev_addr; + va = dsp->mem[i].cpu_addr + offset; + return (__force void *)va; + } + + if (da >= bus_addr && (da + len) <= (bus_addr + size)) { + offset = da - bus_addr; + va = dsp->mem[i].cpu_addr + offset; + return (__force void *)va; + } + } + + /* Assume it is DDR region and return da */ + return map_physmem(da, len, MAP_NOCACHE); +} + +static const struct dm_rproc_ops k3_dsp_ops = { + .init = k3_dsp_init, + .load = k3_dsp_load, + .start = k3_dsp_start, + .stop = k3_dsp_stop, + .reset = k3_dsp_reset, + .device_to_virt = k3_dsp_da_to_va, +}; + +static int ti_sci_proc_of_to_priv(struct udevice *dev, struct ti_sci_proc *tsp) +{ + u32 ids[2]; + int ret; + + dev_dbg(dev, "%s\n", __func__); + + tsp->sci = ti_sci_get_by_phandle(dev, "ti,sci"); + if (IS_ERR(tsp->sci)) { + dev_err(dev, "ti_sci get failed: %ld\n", PTR_ERR(tsp->sci)); + return PTR_ERR(tsp->sci); + } + + ret = dev_read_u32_array(dev, "ti,sci-proc-ids", ids, 2); + if (ret) { + dev_err(dev, "Proc IDs not populated %d\n", ret); + return ret; + } + + tsp->ops = &tsp->sci->ops.proc_ops; + tsp->proc_id = ids[0]; + tsp->host_id = ids[1]; + tsp->dev_id = dev_read_u32_default(dev, "ti,sci-dev-id", + TI_SCI_RESOURCE_NULL); + if (tsp->dev_id == TI_SCI_RESOURCE_NULL) { + dev_err(dev, "Device ID not populated %d\n", ret); + return -ENODEV; + } + + return 0; +} + +static int k3_dsp_of_get_memories(struct udevice *dev) +{ + static const char * const mem_names[] = {"l2sram", "l1pram", "l1dram"}; + struct k3_dsp_privdata *dsp = dev_get_priv(dev); + int i; + + dev_dbg(dev, "%s\n", __func__); + + dsp->num_mems = ARRAY_SIZE(mem_names); + dsp->mem = calloc(dsp->num_mems, sizeof(*dsp->mem)); + if (!dsp->mem) + return -ENOMEM; + + for (i = 0; i < dsp->num_mems; i++) { + /* C71 cores only have a L1P Cache, there are no L1P SRAMs */ + if (device_is_compatible(dev, "ti,j721e-c71-dsp") && + !strcmp(mem_names[i], "l1pram")) { + dsp->mem[i].bus_addr = FDT_ADDR_T_NONE; + dsp->mem[i].dev_addr = FDT_ADDR_T_NONE; + dsp->mem[i].cpu_addr = NULL; + dsp->mem[i].size = 0; + continue; + } + + dsp->mem[i].bus_addr = dev_read_addr_size_name(dev, mem_names[i], + (fdt_addr_t *)&dsp->mem[i].size); + if (dsp->mem[i].bus_addr == FDT_ADDR_T_NONE) { + dev_err(dev, "%s bus address not found\n", mem_names[i]); + return -EINVAL; + } + dsp->mem[i].cpu_addr = map_physmem(dsp->mem[i].bus_addr, + dsp->mem[i].size, + MAP_NOCACHE); + dsp->mem[i].dev_addr = dsp->mem[i].bus_addr & + KEYSTONE_RPROC_LOCAL_ADDRESS_MASK; + + dev_dbg(dev, "memory %8s: bus addr %pa size 0x%zx va %p da %pa\n", + mem_names[i], &dsp->mem[i].bus_addr, + dsp->mem[i].size, dsp->mem[i].cpu_addr, + &dsp->mem[i].dev_addr); + } + + return 0; +} + +/** + * k3_of_to_priv() - generate private data from device tree + * @dev: corresponding k3 dsp processor device + * @dsp: pointer to driver specific private data + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_dsp_of_to_priv(struct udevice *dev, struct k3_dsp_privdata *dsp) +{ + int ret; + + dev_dbg(dev, "%s\n", __func__); + + ret = reset_get_by_index(dev, 0, &dsp->dsp_rst); + if (ret) { + dev_err(dev, "reset_get() failed: %d\n", ret); + return ret; + } + + ret = ti_sci_proc_of_to_priv(dev, &dsp->tsp); + if (ret) + return ret; + + ret = k3_dsp_of_get_memories(dev); + if (ret) + return ret; + + return 0; +} + +/** + * k3_dsp_probe() - Basic probe + * @dev: corresponding k3 remote processor device + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_dsp_probe(struct udevice *dev) +{ + struct k3_dsp_privdata *dsp; + int ret; + + dev_dbg(dev, "%s\n", __func__); + + dsp = dev_get_priv(dev); + + ret = k3_dsp_of_to_priv(dev, dsp); + if (ret) { + dev_dbg(dev, "%s: Probe failed with error %d\n", __func__, ret); + return ret; + } + + dev_dbg(dev, "Remoteproc successfully probed\n"); + + return 0; +} + +static int k3_dsp_remove(struct udevice *dev) +{ + struct k3_dsp_privdata *dsp = dev_get_priv(dev); + + free(dsp->mem); + + return 0; +} + +static const struct udevice_id k3_dsp_ids[] = { + { .compatible = "ti,j721e-c66-dsp"}, + { .compatible = "ti,j721e-c71-dsp"}, + {} +}; + +U_BOOT_DRIVER(k3_dsp) = { + .name = "k3_dsp", + .of_match = k3_dsp_ids, + .id = UCLASS_REMOTEPROC, + .ops = &k3_dsp_ops, + .probe = k3_dsp_probe, + .remove = k3_dsp_remove, + .priv_auto_alloc_size = sizeof(struct k3_dsp_privdata), +}; From b9f035e9c8c87510a01dd4228ea19b4e9a5a8734 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:37 +0530 Subject: [PATCH 19/58] arm: dts: k3-j721e-mcu: Add MCU domain R5F cluster node The J721E SoCs have 3 dual-core Arm Cortex-R5F processor (R5FSS) subsystems/clusters. One R5F cluster (MCU_R5FSS0) is present within the MCU domain, and the remaining two clusters are present in the MAIN domain (MAIN_R5FSS0 & MAIN_R5FSS1). Each of these can be configured at boot time to be either run in a LockStep mode or in an Asymmetric Multi Processing (AMP) fashion in Split-mode. These subsystems have 64 KB each Tightly-Coupled Memory (TCM) internal memories for each core split between two banks - ATCM and BTCM (further interleaved into two banks). There are some IP integration differences from standard Arm R5 clusters such as the absence of an ACP port, presence of an additional TI-specific Region Address Translater (RAT) module for translating 32-bit CPU addresses into larger system bus addresses etc. Add the DT node for the MCU domain R5F cluster/subsystem, the two R5 cores are added as child nodes to the main cluster/subsystem node. The cluster is configured to run in LockStep mode by default, with the ATCMs enabled to allow the R5 cores to execute code from DDR with boot-strapping code from ATCM. The inter-processor communication between the main A72 cores and these processors is achieved through shared memory and Mailboxes. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- arch/arm/dts/k3-j721e-common-proc-board.dts | 5 +++ arch/arm/dts/k3-j721e-mcu-wakeup.dtsi | 38 +++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/arch/arm/dts/k3-j721e-common-proc-board.dts b/arch/arm/dts/k3-j721e-common-proc-board.dts index b5b8c3c5cc..070d21cd05 100644 --- a/arch/arm/dts/k3-j721e-common-proc-board.dts +++ b/arch/arm/dts/k3-j721e-common-proc-board.dts @@ -12,6 +12,11 @@ stdout-path = "serial2:115200n8"; bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000"; }; + + aliases { + remoteproc0 = &mcu_r5fss0_core0; + remoteproc1 = &mcu_r5fss0_core1; + }; }; &wkup_uart0 { diff --git a/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi b/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi index 1175fa9a50..b958b5b3c1 100644 --- a/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi +++ b/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi @@ -69,4 +69,42 @@ clocks = <&k3_clks 149 0>; clock-names = "fclk"; }; + + mcu_r5fss0: r5fss@41000000 { + compatible = "ti,j721e-r5fss"; + lockstep-mode = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x41000000 0x00 0x41000000 0x20000>, + <0x41400000 0x00 0x41400000 0x20000>; + power-domains = <&k3_pds 249 TI_SCI_PD_EXCLUSIVE>; + + mcu_r5fss0_core0: r5f@41000000 { + compatible = "ti,j721e-r5f"; + reg = <0x41000000 0x00008000>, + <0x41010000 0x00008000>; + reg-names = "atcm", "btcm"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <250>; + ti,sci-proc-ids = <0x01 0xFF>; + resets = <&k3_reset 250 1>; + atcm-enable = <1>; + btcm-enable = <1>; + loczrama = <1>; + }; + + mcu_r5fss0_core1: r5f@41400000 { + compatible = "ti,j721e-r5f"; + reg = <0x41400000 0x00008000>, + <0x41410000 0x00008000>; + reg-names = "atcm", "btcm"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <251>; + ti,sci-proc-ids = <0x02 0xFF>; + resets = <&k3_reset 251 1>; + atcm-enable = <1>; + btcm-enable = <1>; + loczrama = <1>; + }; + }; }; From 55f8eb316979621a229069b60625c5fd580182c4 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:38 +0530 Subject: [PATCH 20/58] arm: dts: k3-j721e-main: Add MAIN domain R5F cluster nodes The J721E SoCs have 3 dual-core Arm Cortex-R5F processor (R5FSS) subsystems/clusters. One R5F cluster (MCU_R5FSS0) is present within the MCU domain, and the remaining two clusters are present in the MAIN domain (MAIN_R5FSS0 & MAIN_R5FSS1). Each of these can be configured at boot time to be either run in a LockStep mode or in an Asymmetric Multi Processing (AMP) fashion in Split-mode. These subsystems have 64 KB each Tightly-Coupled Memory (TCM) internal memories for each core split between two banks - ATCM and BTCM (further interleaved into two banks). There are some IP integration differences from standard Arm R5 clusters such as the absence of an ACP port, presence of an additional TI-specific Region Address Translater (RAT) module for translating 32-bit CPU addresses into larger system bus addresses etc. Add the DT nodes for these two MAIN domain R5F cluster/subsystems, the two R5 cores are each added as child nodes to the corresponding main cluster node. Configure SS0 in split mode an SS1 in lockstep mode, with the ATCMs enabled to allow the R5 cores to execute code from DDR with boot-strapping code from ATCM. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- arch/arm/dts/k3-j721e-common-proc-board.dts | 4 ++ arch/arm/dts/k3-j721e-main.dtsi | 76 +++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/arch/arm/dts/k3-j721e-common-proc-board.dts b/arch/arm/dts/k3-j721e-common-proc-board.dts index 070d21cd05..21afdc8ce0 100644 --- a/arch/arm/dts/k3-j721e-common-proc-board.dts +++ b/arch/arm/dts/k3-j721e-common-proc-board.dts @@ -16,6 +16,10 @@ aliases { remoteproc0 = &mcu_r5fss0_core0; remoteproc1 = &mcu_r5fss0_core1; + remoteproc2 = &main_r5fss0_core0; + remoteproc3 = &main_r5fss0_core1; + remoteproc4 = &main_r5fss1_core0; + remoteproc5 = &main_r5fss1_core1; }; }; diff --git a/arch/arm/dts/k3-j721e-main.dtsi b/arch/arm/dts/k3-j721e-main.dtsi index 3445784293..59ca4e5686 100644 --- a/arch/arm/dts/k3-j721e-main.dtsi +++ b/arch/arm/dts/k3-j721e-main.dtsi @@ -228,4 +228,80 @@ ti,trm-icp = <0x8>; dma-coherent; }; + + main_r5fss0: r5fss@5c00000 { + compatible = "ti,j721e-r5fss"; + lockstep-mode = <0>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x5c00000 0x00 0x5c00000 0x20000>, + <0x5d00000 0x00 0x5d00000 0x20000>; + power-domains = <&k3_pds 243 TI_SCI_PD_EXCLUSIVE>; + + main_r5fss0_core0: r5f@5c00000 { + compatible = "ti,j721e-r5f"; + reg = <0x5c00000 0x00008000>, + <0x5c10000 0x00008000>; + reg-names = "atcm", "btcm"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <245>; + ti,sci-proc-ids = <0x06 0xFF>; + resets = <&k3_reset 245 1>; + atcm-enable = <1>; + btcm-enable = <1>; + loczrama = <1>; + }; + + main_r5fss0_core1: r5f@5d00000 { + compatible = "ti,j721e-r5f"; + reg = <0x5d00000 0x00008000>, + <0x5d10000 0x00008000>; + reg-names = "atcm", "btcm"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <246>; + ti,sci-proc-ids = <0x07 0xFF>; + resets = <&k3_reset 246 1>; + atcm-enable = <1>; + btcm-enable = <1>; + loczrama = <1>; + }; + }; + + main_r5fss1: r5fss@5e00000 { + compatible = "ti,j721e-r5fss"; + lockstep-mode = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x5e00000 0x00 0x5e00000 0x20000>, + <0x5f00000 0x00 0x5f00000 0x20000>; + power-domains = <&k3_pds 244 TI_SCI_PD_EXCLUSIVE>; + + main_r5fss1_core0: r5f@5e00000 { + compatible = "ti,j721e-r5f"; + reg = <0x5e00000 0x00008000>, + <0x5e10000 0x00008000>; + reg-names = "atcm", "btcm"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <247>; + ti,sci-proc-ids = <0x08 0xFF>; + resets = <&k3_reset 247 1>; + atcm-enable = <1>; + btcm-enable = <1>; + loczrama = <1>; + }; + + main_r5fss1_core1: r5f@5f00000 { + compatible = "ti,j721e-r5f"; + reg = <0x5f00000 0x00008000>, + <0x5f10000 0x00008000>; + reg-names = "atcm", "btcm"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <248>; + ti,sci-proc-ids = <0x09 0xFF>; + resets = <&k3_reset 248 1>; + atcm-enable = <1>; + btcm-enable = <1>; + loczrama = <1>; + }; + }; }; From 293e39780d5f03c3ce8a2b032b607a9cf161d9fc Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:39 +0530 Subject: [PATCH 21/58] arm: dts: k3-j721e-main: Add C66x DSP nodes The J721E SoCs have two TMS320C66x DSP Core Subsystems (C66x CorePacs) in the MAIN voltage domain, each with a C66x Fixed/Floating-Point DSP Core, and 32 KB of L1P & L1D configurable SRAMs/Cache and an additional 288 KB of L2 configurable SRAM/Cache. These subsystems do not have an MMU but contain a Region Address Translator (RAT) sub-module for translating 32-bit processor addresses into larger bus addresses. The inter-processor communication between the main A72 cores and these processors is achieved through shared memory and Mailboxes. Add the DT nodes for these DSP processor sub-systems in the common k3-j721e-main.dtsi file. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- arch/arm/dts/k3-j721e-common-proc-board.dts | 2 ++ arch/arm/dts/k3-j721e-main.dtsi | 24 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/arch/arm/dts/k3-j721e-common-proc-board.dts b/arch/arm/dts/k3-j721e-common-proc-board.dts index 21afdc8ce0..a548277718 100644 --- a/arch/arm/dts/k3-j721e-common-proc-board.dts +++ b/arch/arm/dts/k3-j721e-common-proc-board.dts @@ -20,6 +20,8 @@ remoteproc3 = &main_r5fss0_core1; remoteproc4 = &main_r5fss1_core0; remoteproc5 = &main_r5fss1_core1; + remoteproc6 = &c66_0; + remoteproc7 = &c66_1; }; }; diff --git a/arch/arm/dts/k3-j721e-main.dtsi b/arch/arm/dts/k3-j721e-main.dtsi index 59ca4e5686..c3aa0cdcf1 100644 --- a/arch/arm/dts/k3-j721e-main.dtsi +++ b/arch/arm/dts/k3-j721e-main.dtsi @@ -304,4 +304,28 @@ loczrama = <1>; }; }; + + c66_0: dsp@4d80800000 { + compatible = "ti,j721e-c66-dsp"; + reg = <0x4d 0x80800000 0x00 0x00048000>, + <0x4d 0x80e00000 0x00 0x00008000>, + <0x4d 0x80f00000 0x00 0x00008000>; + reg-names = "l2sram", "l1pram", "l1dram"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <142>; + ti,sci-proc-ids = <0x03 0xFF>; + resets = <&k3_reset 142 1>; + }; + + c66_1: dsp@4d81800000 { + compatible = "ti,j721e-c66-dsp"; + reg = <0x4d 0x81800000 0x00 0x00048000>, + <0x4d 0x81e00000 0x00 0x00008000>, + <0x4d 0x81f00000 0x00 0x00008000>; + reg-names = "l2sram", "l1pram", "l1dram"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <143>; + ti,sci-proc-ids = <0x04 0xFF>; + resets = <&k3_reset 143 1>; + }; }; From 1b846fc24d80ceb358312b4aa3e8242d36784fe4 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:40 +0530 Subject: [PATCH 22/58] arm: dts: k3-j721e-main: Add C71x DSP node The J721E SoCs have a single TMS320C71x DSP Subsystem in the MAIN voltage domain containing the next-generation C711 CPU core. The subsystem has 32 KB of L1D configurable SRAM/Cache and 512 KB of L2 configurable SRAM/Cache. This subsystem has a CMMU but is not used currently. The inter-processor communication between the main A72 cores and the C711 processor is achieved through shared memory and a Mailbox. Add the DT node for this DSP processor sub-system in the common k3-j721e-main.dtsi file. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- arch/arm/dts/k3-j721e-common-proc-board.dts | 1 + arch/arm/dts/k3-j721e-main.dtsi | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm/dts/k3-j721e-common-proc-board.dts b/arch/arm/dts/k3-j721e-common-proc-board.dts index a548277718..b21f597a80 100644 --- a/arch/arm/dts/k3-j721e-common-proc-board.dts +++ b/arch/arm/dts/k3-j721e-common-proc-board.dts @@ -22,6 +22,7 @@ remoteproc5 = &main_r5fss1_core1; remoteproc6 = &c66_0; remoteproc7 = &c66_1; + remoteproc8 = &c71_0; }; }; diff --git a/arch/arm/dts/k3-j721e-main.dtsi b/arch/arm/dts/k3-j721e-main.dtsi index c3aa0cdcf1..6bd59bac52 100644 --- a/arch/arm/dts/k3-j721e-main.dtsi +++ b/arch/arm/dts/k3-j721e-main.dtsi @@ -328,4 +328,15 @@ ti,sci-proc-ids = <0x04 0xFF>; resets = <&k3_reset 143 1>; }; + + c71_0: dsp@64800000 { + compatible = "ti,j721e-c71-dsp"; + reg = <0x00 0x64800000 0x00 0x00080000>, + <0x00 0x64e00000 0x00 0x0000c000>; + reg-names = "l2sram", "l1dram"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <15>; + ti,sci-proc-ids = <0x30 0xFF>; + resets = <&k3_reset 15 1>; + }; }; From 35f21c3ac649daad3f322d4d556c8ee7683c6ffd Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 4 Sep 2019 16:01:41 +0530 Subject: [PATCH 23/58] arm: dts: k3-am65-mcu: Add MCU domain R5F DT nodes The AM65x SoCs has a single dual-core Arm Cortex-R5F processor subsystem/cluster (MCU_R5FSS0) within the MCU domain. This cluster can be configured at boot time to be either run in a LockStep mode or in an Asymmetric Multi Processing (AMP) fashion in Split-mode. This subsystem has 64 KB each Tightly-Coupled Memory (TCM) internal memories for each core split between two banks - ATCM and BTCM (further interleaved into two banks). There are some IP integration differences from standard Arm R5 clusters such as the absence of an ACP port, presence of an additional TI-specific Region Address Translater (RAT) module for translating 32-bit CPU addresses into larger system bus addresses etc. Add the DT node for the MCU domain R5F cluster/subsystem, the two R5 cores are added as child nodes to the main cluster/subsystem node. The cluster is configured to run in Split-mode by default, with the ATCMs enabled to allow the R5 cores to execute code from DDR with boot-strapping code from ATCM. The inter-processor communication between the main A72 cores and these processors is achieved through shared memory and Mailboxes. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- arch/arm/dts/k3-am65-mcu.dtsi | 40 +++++++++++++++++++++++++++- arch/arm/dts/k3-am654-base-board.dts | 5 ++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/k3-am65-mcu.dtsi b/arch/arm/dts/k3-am65-mcu.dtsi index c9bfd9b80f..c42e7553c7 100644 --- a/arch/arm/dts/k3-am65-mcu.dtsi +++ b/arch/arm/dts/k3-am65-mcu.dtsi @@ -2,7 +2,7 @@ /* * Device Tree Source for AM6 SoC Family MCU Domain peripherals * - * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2016-2019 Texas Instruments Incorporated - http://www.ti.com/ */ &cbass_mcu { @@ -26,4 +26,42 @@ clocks = <&k3_clks 114 1>; power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>; }; + + mcu_r5fss0: r5fss@41000000 { + compatible = "ti,am654-r5fss"; + lockstep-mode = <0>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x41000000 0x00 0x41000000 0x20000>, + <0x41400000 0x00 0x41400000 0x20000>; + power-domains = <&k3_pds 129 TI_SCI_PD_EXCLUSIVE>; + + mcu_r5fss0_core0: r5f@41000000 { + compatible = "ti,am654-r5f"; + reg = <0x41000000 0x00008000>, + <0x41010000 0x00008000>; + reg-names = "atcm", "btcm"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <159>; + ti,sci-proc-ids = <0x01 0xFF>; + resets = <&k3_reset 159 1>; + atcm-enable = <1>; + btcm-enable = <1>; + loczrama = <1>; + }; + + mcu_r5fss0_core1: r5f@41400000 { + compatible = "ti,am654-r5f"; + reg = <0x41400000 0x00008000>, + <0x41410000 0x00008000>; + reg-names = "atcm", "btcm"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <245>; + ti,sci-proc-ids = <0x02 0xFF>; + resets = <&k3_reset 245 1>; + atcm-enable = <1>; + btcm-enable = <1>; + loczrama = <1>; + }; + }; }; diff --git a/arch/arm/dts/k3-am654-base-board.dts b/arch/arm/dts/k3-am654-base-board.dts index e73b9aa6b1..573ead0b4d 100644 --- a/arch/arm/dts/k3-am654-base-board.dts +++ b/arch/arm/dts/k3-am654-base-board.dts @@ -17,6 +17,11 @@ bootargs = "earlycon=ns16550a,mmio32,0x02800000"; }; + aliases { + remoteproc0 = &mcu_r5fss0_core0; + remoteproc1 = &mcu_r5fss0_core1; + }; + memory@80000000 { device_type = "memory"; /* 4G RAM */ From bb17aaf658b4bb28677e346053a684447e3ddeb2 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 4 Sep 2019 16:01:42 +0530 Subject: [PATCH 24/58] env: ti: k3_rproc: Add common rproc environment variables Add a new file include/environment/ti/k3_rproc.h that defines common environment variables useful for booting various remote processors from U-Boot. This file is expected to be included in the board config files with the EXTRA_ENV_RPROC_SETTINGS added to CONFIG_EXTRA_ENV_SETTINGS and DEFAULT_RPROCS macro overwritten to include the actual list of processors to be booted. The 'boot_rprocs' variable just needs to be added to the board's bootcmd to automatically boot the processors, and runtime control can be achieved through the 'dorprocboot' variable. The variables are currently defined to use MMC as the boot media, and can be expanded in the future to include other boot media. The immediate usage is intended for K3 J721E SoCs. Signed-off-by: Jean-Jacques Hiblot Signed-off-by: Suman Anna --- include/environment/ti/k3_rproc.h | 52 +++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 include/environment/ti/k3_rproc.h diff --git a/include/environment/ti/k3_rproc.h b/include/environment/ti/k3_rproc.h new file mode 100644 index 0000000000..3418cb42be --- /dev/null +++ b/include/environment/ti/k3_rproc.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com + * + * rproc environment variable definitions for various TI K3 SoCs. + */ + +#ifndef __TI_RPROC_H +#define __TI_RPROC_H + +/* + * should contain a list of tuplies, + * override in board config files with the actual list + */ +#define DEFAULT_RPROCS "" + +#ifdef CONFIG_CMD_REMOTEPROC +#define EXTRA_ENV_RPROC_SETTINGS \ + "dorprocboot=0\0" \ + "boot_rprocs=" \ + "if test ${dorprocboot} -eq 1 && test ${boot} = mmc; then "\ + "rproc init;" \ + "run boot_rprocs_mmc;" \ + "fi;\0" \ + "rproc_load_and_boot_one=" \ + "if load mmc ${bootpart} $loadaddr ${rproc_fw}; then " \ + "if rproc load ${rproc_id} ${loadaddr} ${filesize}; then "\ + "rproc start ${rproc_id};" \ + "fi;" \ + "fi\0" \ + "boot_rprocs_mmc=" \ + "env set rproc_id;" \ + "env set rproc_fw;" \ + "for i in ${rproc_fw_binaries} ; do " \ + "if test -z \"${rproc_id}\" ; then " \ + "env set rproc_id $i;" \ + "else " \ + "env set rproc_fw $i;" \ + "run rproc_load_and_boot_one;" \ + "env set rproc_id;" \ + "env set rproc_fw;" \ + "fi;" \ + "done\0" \ + "rproc_fw_binaries=" \ + DEFAULT_RPROCS \ + "\0" +#else +#define EXTRA_ENV_RPROC_SETTINGS \ + "boot_rprocs= \0" +#endif /* CONFIG_CMD_REMOTEPROC */ + +#endif /* __TI_RPROC_H */ From 0b4ab9c9a754fe3787b33807c8f0605ba334ef56 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 4 Sep 2019 16:01:43 +0530 Subject: [PATCH 25/58] env: ti: j721e-evm: Add support to boot rprocs including R5Fs and DSPs Add support to boot some remoteprocs at U-boot prompt on the J721E EVM boards by using the 'boot_rprocs' and other env variables defined in the common environment file k3_rproc.h, and updating the 'DEFAULT_RPROCS' macro. The list of R5F cores to be started before loading and booting the Linux kernel are as follows, and in this order: Main R5FSS0 (Split) Core1 : 3 /lib/firmware/j7-main-r5f0_1-fw Main R5FSS1 (LockStep) : 4 /lib/firmware/j7-main-r5f1_0-fw The MCU R5FSS0 and Main R5FSS1 are currently in LockStep mode, so the equivalent Core1 rprocs (rproc #1 and #5) are not included. The Main R5FSS0 Core0 (rproc #2) is already started by R5 SPL, so is not included in the list either. The DSP cores are started in the following order before loading and booting the Linux kernel: C66_0: 6 /lib/firmware/j7-c66_0-fw C66_1: 7 /lib/firmware/j7-c66_1-fw C71_0: 8 /lib/firmware/j7-c71_0-fw The order of the rprocs to boot can be changed at runtime if desired by overwriting the 'rproc_fw_binaries' environment variable at U-boot prompt. Signed-off-by: Jean-Jacques Hiblot Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- include/configs/j721e_evm.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/include/configs/j721e_evm.h b/include/configs/j721e_evm.h index 5fe77ef16d..dbe226b46d 100644 --- a/include/configs/j721e_evm.h +++ b/include/configs/j721e_evm.h @@ -12,6 +12,7 @@ #include #include #include +#include #define CONFIG_ENV_SIZE (128 << 10) @@ -87,11 +88,22 @@ "get_kern_mmc=load mmc ${bootpart} ${loadaddr} " \ "${bootdir}/${name_kern}\0" +#ifdef DEFAULT_RPROCS +#undef DEFAULT_RPROCS +#endif +#define DEFAULT_RPROCS "" \ + "3 /lib/firmware/j7-main-r5f0_1-fw " \ + "4 /lib/firmware/j7-main-r5f1_0-fw " \ + "6 /lib/firmware/j7-c66_0-fw " \ + "7 /lib/firmware/j7-c66_1-fw " \ + "8 /lib/firmware/j7-c71_0-fw " + /* Incorporate settings into the U-Boot environment */ #define CONFIG_EXTRA_ENV_SETTINGS \ DEFAULT_MMC_TI_ARGS \ EXTRA_ENV_J721E_BOARD_SETTINGS \ - EXTRA_ENV_J721E_BOARD_SETTINGS_MMC + EXTRA_ENV_J721E_BOARD_SETTINGS_MMC \ + EXTRA_ENV_RPROC_SETTINGS /* Now for the remaining common defines */ #include From b9bb1952c9fcfe16b7d1f2ec45eb584591e1c7f5 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 4 Sep 2019 16:01:44 +0530 Subject: [PATCH 26/58] env: ti: am65x_evm: Add env support to boot the MCU R5F rprocs Add support to boot the MCU domain R5F Core0 remoteproc at U-boot prompt on the AM65x EVM boards by using the 'boot_rprocs' and other env variables defined in the common environment file k3_rproc.h, and updating the 'DEFAULT_RPROCS' macro. The default configuration is to use the MCU R5F in Split mode, so both the R5F Core0 and Core1 are started before loading and booting the Linux kernel using the following firmware: MCU R5FSS0 Core0 (Split) : 0 /lib/firmware/am65x-mcu-r5f0_0-fw MCU R5FSS0 Core1 (Split) : 1 /lib/firmware/am65x-mcu-r5f0_1-fw The MCU R5FSS was initially running the R5 SPL in LockStep mode with ATCM disabled, and is actually shutdown to enable it to be reconfigured and booted by either A53 U-Boot or Linux kernel in remoteproc mode and using ATCM. The MCU R5FSS would need to be reconfigured for Lockstep mode through DT if a fault-tolerant/safety application were to be run on the cluster with the DEFAULT_RPROCS macro updated to remove the Core1 firmware. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- include/configs/am65x_evm.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h index 0249a20ba8..1149d55937 100644 --- a/include/configs/am65x_evm.h +++ b/include/configs/am65x_evm.h @@ -12,6 +12,7 @@ #include #include #include +#include #define CONFIG_ENV_SIZE (128 << 10) @@ -98,12 +99,20 @@ "${bootdir}/${name_fit}\0" \ "partitions=" PARTS_DEFAULT +#ifdef DEFAULT_RPROCS +#undef DEFAULT_RPROCS +#endif +#define DEFAULT_RPROCS "" \ + "0 /lib/firmware/am65x-mcu-r5f0_0-fw " \ + "1 /lib/firmware/am65x-mcu-r5f0_1-fw " + /* Incorporate settings into the U-Boot environment */ #define CONFIG_EXTRA_ENV_SETTINGS \ DEFAULT_MMC_TI_ARGS \ DEFAULT_FIT_TI_ARGS \ EXTRA_ENV_AM65X_BOARD_SETTINGS \ - EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC + EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC \ + EXTRA_ENV_RPROC_SETTINGS /* MMC ENV related defines */ #ifdef CONFIG_ENV_IS_IN_MMC From 5b1185c15b76f8924152645cec86756b0416e4e7 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:45 +0530 Subject: [PATCH 27/58] configs: j721e_evm_a72: Enable R5F and DSP remoteproc driver Enable R5F and DSP remoteproc drivers for j721e running on a72. Signed-off-by: Lokesh Vutla --- configs/j721e_evm_a72_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig index 5cb933d878..f0ec650fa5 100644 --- a/configs/j721e_evm_a72_defconfig +++ b/configs/j721e_evm_a72_defconfig @@ -34,6 +34,7 @@ CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_CMD_ASKENV=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_MMC=y +CONFIG_CMD_REMOTEPROC=y CONFIG_CMD_SF=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y @@ -72,6 +73,8 @@ CONFIG_SPL_PINCTRL=y CONFIG_PINCTRL_SINGLE=y CONFIG_POWER_DOMAIN=y CONFIG_TI_SCI_POWER_DOMAIN=y +CONFIG_REMOTEPROC_TI_K3_DSP=y +CONFIG_REMOTEPROC_TI_K3_R5F=y CONFIG_DM_RESET=y CONFIG_RESET_TI_SCI=y CONFIG_DM_SERIAL=y From 750dc1ed518b4ce222efff5358a24f48a6811a71 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 4 Sep 2019 16:01:46 +0530 Subject: [PATCH 28/58] configs: j721e_evm_a72: Enhance bootcmd to start remoteprocs The A72 U-boot can support early booting of any of the R5F or C66x or C71x remote processors from U-boot prompt to achieve various system usecases before booting the Linux kernel. Update the default BOOTCOMMAND to provide an automatic and easier way to start various remote processors through added environment variables. Signed-off-by: Jean-Jacques Hiblot Signed-off-by: Suman Anna --- configs/j721e_evm_a72_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig index f0ec650fa5..d455d17d26 100644 --- a/configs/j721e_evm_a72_defconfig +++ b/configs/j721e_evm_a72_defconfig @@ -18,7 +18,7 @@ CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_DISTRO_DEFAULTS=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_LOAD_FIT=y -CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern" +CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run boot_rprocs; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y From 9af139c17b4588732237d0b76d1ef37e07934c9d Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 4 Sep 2019 16:01:47 +0530 Subject: [PATCH 29/58] configs: am65x_evm_a53: Enable R5F remoteproc driver Enable the R5F remoteproc driver for the AM65x GP EVM so that the MCU domain R5F cores can be booted from A53 U-boot. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- configs/am65x_evm_a53_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index e5b127c75c..d320c00f1e 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -35,6 +35,7 @@ CONFIG_CMD_GPT=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_PCI=y +CONFIG_CMD_REMOTEPROC=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y # CONFIG_ISO_PARTITION is not set @@ -83,6 +84,7 @@ CONFIG_SPL_PINCTRL=y CONFIG_PINCTRL_SINGLE=y CONFIG_POWER_DOMAIN=y CONFIG_TI_SCI_POWER_DOMAIN=y +CONFIG_REMOTEPROC_TI_K3_R5F=y CONFIG_DM_RESET=y CONFIG_RESET_TI_SCI=y CONFIG_DM_SERIAL=y From 65b91b2f8c4aca31abaada3980096ba369609eaa Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 4 Sep 2019 16:01:48 +0530 Subject: [PATCH 30/58] configs: am65x_evm_a53: Enhance bootcmd to start remoteprocs The A53 U-boot can support early booting of the MCU R5F remote processor(s) from U-boot prompt to achieve various system usecases before booting the Linux kernel. Update the default BOOTCOMMAND to provide an automatic and easier way to start the MCU R5F cores through added environment variables. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- configs/am65x_evm_a53_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index d320c00f1e..453177bde1 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -17,7 +17,7 @@ CONFIG_DISTRO_DEFAULTS=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_LOAD_FIT=y CONFIG_OF_BOARD_SETUP=y -CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern" +CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run boot_rprocs; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y From 60bdc6b9f372d3e2d89c2e59b22ea7f3867a090d Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 4 Sep 2019 16:01:49 +0530 Subject: [PATCH 31/58] armv8: K3: am65x: Update DDR address regions in MMU table The A53 U-Boot code can load and boot the MCU domain R5F cores (either a single core in LockStep mode or 2 cores in Split mode) to achieve various early system functionalities. Change the memory attributes for the DDR regions used by the remote processors so that the cores can see and execute the proper code loaded by U-Boot. These regions are currently limited to 0xa0000000 to 0xa2100000 as per the DDR carveouts assigned for these R5F cores in the overall DDR memory map. Signed-off-by: Suman Anna Signed-off-by: Lokesh Vutla --- arch/arm/mach-k3/arm64-mmu.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-k3/arm64-mmu.c b/arch/arm/mach-k3/arm64-mmu.c index 82778d2197..98c5a777e5 100644 --- a/arch/arm/mach-k3/arm64-mmu.c +++ b/arch/arm/mach-k3/arm64-mmu.c @@ -14,7 +14,7 @@ #ifdef CONFIG_SOC_K3_AM6 /* NR_DRAM_BANKS + 32bit IO + 64bit IO + terminator */ -#define NR_MMU_REGIONS (CONFIG_NR_DRAM_BANKS + 3) +#define NR_MMU_REGIONS (CONFIG_NR_DRAM_BANKS + 5) /* ToDo: Add 64bit IO */ struct mm_region am654_mem_map[NR_MMU_REGIONS] = { @@ -28,7 +28,19 @@ struct mm_region am654_mem_map[NR_MMU_REGIONS] = { }, { .virt = 0x80000000UL, .phys = 0x80000000UL, - .size = 0x80000000UL, + .size = 0x20000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + .virt = 0xa0000000UL, + .phys = 0xa0000000UL, + .size = 0x02100000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | + PTE_BLOCK_INNER_SHARE + }, { + .virt = 0xa2100000UL, + .phys = 0xa2100000UL, + .size = 0x5df00000UL, .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE }, { From 8bdd83ee507529ce98d844cdfbe2ec4233aa5a1c Mon Sep 17 00:00:00 2001 From: Kedar Chitnis Date: Wed, 4 Sep 2019 16:01:50 +0530 Subject: [PATCH 32/58] armv8: K3: j721e: Updated ddr address regions in MMU table The A72 U-Boot code loads and boots a number of remote processors including the C71x DSP, both the C66_0 and C66_1 DSPs, and the various Main R5FSS Cores. In order to view the code loaded by the U-Boot by remote cores, U-Boot should configure the memory region with right memory attributes. Right now U-Boot carves out a memory region which is not sufficient for all the images to be loaded. So, increase this carve out region by 256MB. Signed-off-by: Kedar Chitnis Signed-off-by: Lokesh Vutla --- arch/arm/mach-k3/arm64-mmu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-k3/arm64-mmu.c b/arch/arm/mach-k3/arm64-mmu.c index 98c5a777e5..7f908eee80 100644 --- a/arch/arm/mach-k3/arm64-mmu.c +++ b/arch/arm/mach-k3/arm64-mmu.c @@ -80,13 +80,13 @@ struct mm_region j721e_mem_map[NR_MMU_REGIONS] = { }, { .virt = 0xa0000000UL, .phys = 0xa0000000UL, - .size = 0x0bc00000UL, + .size = 0x1bc00000UL, .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | PTE_BLOCK_NON_SHARE }, { - .virt = 0xabc00000UL, - .phys = 0xabc00000UL, - .size = 0x54400000UL, + .virt = 0xbbc00000UL, + .phys = 0xbbc00000UL, + .size = 0x44400000UL, .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE }, { From 3d95fc523e818f786cf505403052399a3236623f Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 4 Sep 2019 16:01:51 +0530 Subject: [PATCH 33/58] board: j721e: Add README Add README file explaining the build and boot procedure for J721E evm. Signed-off-by: Lokesh Vutla --- board/ti/j721e/README | 227 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 board/ti/j721e/README diff --git a/board/ti/j721e/README b/board/ti/j721e/README new file mode 100644 index 0000000000..5be7d099db --- /dev/null +++ b/board/ti/j721e/README @@ -0,0 +1,227 @@ +Introduction: +------------- +The J721e family of SoCs are part of K3 Multicore SoC architecture platform +targeting automotive applications. They are designed as a low power, high +performance and highly integrated device architecture, adding significant +enhancement on processing power, graphics capability, video and imaging +processing, virtualization and coherent memory support. + +The device is partitioned into three functional domains, each containing +specific processing cores and peripherals: +1. Wake-up (WKUP) domain: + - Device Management and Security Controller (DMSC) +2. Microcontroller (MCU) domain: + - Dual Core ARM Cortex-R5F processor +3. MAIN domain: + - Dual core 64-bit ARM Cortex-A72 + - 2 x Dual cortex ARM Cortex-R5 subsystem + - 2 x C66x Digital signal processor sub system + - C71x Digital signal processor sub-system with MMA. + +More info can be found in TRM: http://www.ti.com/lit/pdf/spruil1 + +Boot Flow: +---------- +Boot flow is similar to that of AM65x SoC and extending it with remoteproc +support. Below is the pictorial representation of boot flow: + ++------------------------------------------------------------------------+-----------------------+ +| DMSC | MCU R5 | A72 | MAIN R5/C66x/C7x | ++------------------------------------------------------------------------+-----------------------+ +| +--------+ | | | | +| | Reset | | | | | +| +--------+ | | | | +| : | | | | +| +--------+ | +-----------+ | | | +| | *ROM* |----------|-->| Reset rls | | | | +| +--------+ | +-----------+ | | | +| | | | : | | | +| | ROM | | : | | | +| |services| | : | | | +| | | | +-------------+ | | | +| | | | | *R5 ROM* | | | | +| | | | +-------------+ | | | +| | |<---------|---|Load and auth| | | | +| | | | | tiboot3.bin | | | | +| | | | +-------------+ | | | +| | | | : | | | +| | | | : | | | +| | | | : | | | +| | | | +-------------+ | | | +| | | | | *R5 SPL* | | | | +| | | | +-------------+ | | | +| | | | | Load | | | | +| | | | | sysfw.itb | | | | +| | Start | | +-------------+ | | | +| | System |<---------|---| Start | | | | +| |Firmware| | | SYSFW | | | | +| +--------+ | +-------------+ | | | +| : | | | | | | +| +---------+ | | Load | | | | +| | *SYSFW* | | | system | | | | +| +---------+ | | Config data | | | | +| | |<--------|---| | | | | +| | | | +-------------+ | | | +| | | | | DDR | | | | +| | | | | config | | | | +| | | | +-------------+ | | | +| | | | | Load | | | | +| | | | | tispl.bin | | | | +| | | | +-------------+ | | | +| | | | | Load R5 | | | | +| | | | | firmware | | | | +| | | | +-------------+ | | | +| | |<--------|---| Start A72 | | | | +| | | | | and jump to | | | | +| | | | | next image | | | | +| | | | +-------------+ | | | +| | | | | +-----------+ | | +| | |---------|-----------------------|---->| Reset rls | | | +| | | | | +-----------+ | | +| | DMSC | | | : | | +| |Services | | | +-----------+ | | +| | |<--------|-----------------------|---->|*ATF/OPTEE*| | | +| | | | | +-----------+ | | +| | | | | : | | +| | | | | +-----------+ | | +| | |<--------|-----------------------|---->| *A72 SPL* | | | +| | | | | +-----------+ | | +| | | | | | Load | | | +| | | | | | u-boot.img| | | +| | | | | +-----------+ | | +| | | | | : | | +| | | | | +-----------+ | | +| | |<--------|-----------------------|---->| *U-Boot* | | | +| | | | | +-----------+ | | +| | | | | | prompt | | | +| | | | | +-----------+ | | +| | | | | | Load R5 | | | +| | | | | | Firmware | | | +| | | | | +-----------+ | | +| | |<--------|-----------------------|-----| Start R5 | | +-----------+ | +| | |---------|-----------------------|-----+-----------+-----|----->| R5 starts | | +| | | | | | Load C6 | | +-----------+ | +| | | | | | Firmware | | | +| | | | | +-----------+ | | +| | |<--------|-----------------------|-----| Start C6 | | +-----------+ | +| | |---------|-----------------------|-----+-----------+-----|----->| C6 starts | | +| | | | | | Load C7 | | +-----------+ | +| | | | | | Firmware | | | +| | | | | +-----------+ | | +| | |<--------|-----------------------|-----| Start C7 | | +-----------+ | +| | |---------|-----------------------|-----+-----------+-----|----->| C7 starts | | +| +---------+ | | | +-----------+ | +| | | | | ++------------------------------------------------------------------------+-----------------------+ + +- Here DMSC acts as master and provides all the critical services. R5/A72 +requests DMSC to get these services done as shown in the above diagram. + +Sources: +-------- +1. SYSFW: + Tree: git://git.ti.com/processor-firmware/system-firmware-image-gen.git + Branch: master + +2. ATF: + Tree: https://github.com/ARM-software/arm-trusted-firmware.git + Branch: master + +3. OPTEE: + Tree: https://github.com/OP-TEE/optee_os.git + Branch: master + +4. U-Boot: + Tree: https://gitlab.denx.de/u-boot/u-boot + Branch: master + +Build procedure: +---------------- +1. SYSFW: +$ make CROSS_COMPILE=arm-linux-gnueabihf- + +2. ATF: +$ make CROSS_COMPILE=aarch64-linux-gnu- ARCH=aarch64 PLAT=k3 TARGET_BOARD=generic SPD=opteed + +3. OPTEE: +$ make PLATFORM=k3-j721e CFG_ARM64_core=y + +4. U-Boot: + +4.1. R5: +$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- j721e_evm_r5_defconfig O=/tmp/r5 +$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=/tmp/r5 + +4.2. A72: +$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- j721e_evm_a72_defconfig O=/tmp/a72 +$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- ATF=/build/k3/generic/release/bl31.bin TEE=/out/arm-plat-k3/core/tee-pager.bin O=/tmp/a72 + +Target Images +-------------- +Copy the below images to an SD card and boot: +- sysfw.itb from step 1 +- tiboot3.bin from step 4.1 +- tispl.bin, u-boot.img from 4.2 + +Image formats: +-------------- + +- tiboot3.bin: + +-----------------------+ + | X.509 | + | Certificate | + | +-------------------+ | + | | | | + | | R5 | | + | | u-boot-spl.bin | | + | | | | + | +-------------------+ | + | | | | + | | FIT header | | + | | +---------------+ | | + | | | | | | + | | | DTB 1...N | | | + | | +---------------+ | | + | +-------------------+ | + +-----------------------+ + +- tispl.bin + +-----------------------+ + | | + | FIT HEADER | + | +-------------------+ | + | | | | + | | A72 ATF | | + | +-------------------+ | + | | | | + | | A72 OPTEE | | + | +-------------------+ | + | | | | + | | A72 SPL | | + | +-------------------+ | + | | | | + | | SPL DTB 1...N | | + | +-------------------+ | + +-----------------------+ + +- sysfw.itb + +-----------------------+ + | | + | FIT HEADER | + | +-------------------+ | + | | | | + | | sysfw.bin | | + | +-------------------+ | + | | | | + | | board config | | + | +-------------------+ | + | | | | + | | PM config | | + | +-------------------+ | + | | | | + | | RM config | | + | +-------------------+ | + | | | | + | | Secure config | | + | +-------------------+ | + +-----------------------+ From ed474ae00c7b2b51fc97b0580d2e52483a657acb Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Mon, 16 Sep 2019 13:47:15 +0530 Subject: [PATCH 34/58] arm: omap: emif-common: Fix ecc address calculation ecc_address_range registers contains the start address and end address of the DDR address space. But the ddr driver is assuming the register contains the start address and size of the DDR address space. Because of this the ecc enabling is failing for the 2nd range of ecc addresses. Fix this calculation. Signed-off-by: Lokesh Vutla --- arch/arm/mach-omap2/emif-common.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-omap2/emif-common.c b/arch/arm/mach-omap2/emif-common.c index b384343a3f..04bbfd84a2 100644 --- a/arch/arm/mach-omap2/emif-common.c +++ b/arch/arm/mach-omap2/emif-common.c @@ -348,7 +348,7 @@ static void dra7_reset_ddr_data(u32 base, u32 size) static void dra7_enable_ecc(u32 base, const struct emif_regs *regs) { struct emif_reg_struct *emif = (struct emif_reg_struct *)base; - u32 rgn, size; + u32 rgn, rgn_start, size; /* ECC available only on dra76x EMIF1 */ if ((base != EMIF1_BASE) || !is_dra76x()) @@ -362,22 +362,22 @@ static void dra7_enable_ecc(u32 base, const struct emif_regs *regs) writel(regs->emif_ecc_ctrl_reg, &emif->emif_ecc_ctrl_reg); /* Set region1 memory with 0 */ - rgn = ((regs->emif_ecc_address_range_1 & - EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16) + - CONFIG_SYS_SDRAM_BASE; + rgn_start = (regs->emif_ecc_address_range_1 & + EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16; + rgn = rgn_start + CONFIG_SYS_SDRAM_BASE; size = (regs->emif_ecc_address_range_1 & - EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0x10000; + EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0x10000 - rgn_start; if (regs->emif_ecc_ctrl_reg & EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK) dra7_reset_ddr_data(rgn, size); /* Set region2 memory with 0 */ - rgn = ((regs->emif_ecc_address_range_2 & - EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16) + - CONFIG_SYS_SDRAM_BASE; + rgn_start = (regs->emif_ecc_address_range_2 & + EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16; + rgn = rgn_start + CONFIG_SYS_SDRAM_BASE; size = (regs->emif_ecc_address_range_2 & - EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0x10000; + EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0x10000 - rgn_start; if (regs->emif_ecc_ctrl_reg & EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK) From 5ebe6c0cb74a93ae75a1dd37e92e3765511f788c Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Mon, 16 Sep 2019 13:47:16 +0530 Subject: [PATCH 35/58] cmd: ti: ddr3: Fix ecc address calculation ecc_address_range registers contains the start address and end address of the DDR address space. But the ddr cmd driver is assuming the register contains the start address and size of the DDR address space. Because of this some valid ecc addresses are errored out as invalid address. Fix this calculation. Signed-off-by: Lokesh Vutla --- cmd/ti/ddr3.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/ti/ddr3.c b/cmd/ti/ddr3.c index b82cbe152d..34f870ab43 100644 --- a/cmd/ti/ddr3.c +++ b/cmd/ti/ddr3.c @@ -242,8 +242,8 @@ static int is_addr_valid(u32 addr) if (ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK) { start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16) + CONFIG_SYS_SDRAM_BASE; - end_addr = start_addr + (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) - + 0xFFFF; + end_addr = (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0xFFFF + + CONFIG_SYS_SDRAM_BASE; if ((addr >= start_addr) && (addr <= end_addr)) /* addr within ecc address range 1 */ return 1; @@ -254,8 +254,8 @@ static int is_addr_valid(u32 addr) range = readl(&emif->emif_ecc_address_range_2); start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16) + CONFIG_SYS_SDRAM_BASE; - end_addr = start_addr + (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) - + 0xFFFF; + end_addr = (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0xFFFF + + CONFIG_SYS_SDRAM_BASE; if ((addr >= start_addr) && (addr <= end_addr)) /* addr within ecc address range 2 */ return 1; From d0a37a5e510a6772bb86d3cda8d1a2c14c01a0e2 Mon Sep 17 00:00:00 2001 From: Krunal Bhargav Date: Mon, 16 Sep 2019 13:47:17 +0530 Subject: [PATCH 36/58] arm: omap: emif-common: Disable interleaving If ECC is enabled, we need to ensure interleaving is disabled for higher address space. Signed-off-by: Krunal Bhargav Signed-off-by: Lokesh Vutla --- arch/arm/mach-omap2/emif-common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-omap2/emif-common.c b/arch/arm/mach-omap2/emif-common.c index 04bbfd84a2..9bdaa388c9 100644 --- a/arch/arm/mach-omap2/emif-common.c +++ b/arch/arm/mach-omap2/emif-common.c @@ -355,6 +355,9 @@ static void dra7_enable_ecc(u32 base, const struct emif_regs *regs) return; if (regs->emif_ecc_ctrl_reg & EMIF_ECC_CTRL_REG_ECC_EN_MASK) { + /* Disable high-order interleaving */ + clrbits_le32(MA_PRIORITY, MA_HIMEM_INTERLEAVE_UN_MASK); + writel(regs->emif_ecc_address_range_1, &emif->emif_ecc_address_range_1); writel(regs->emif_ecc_address_range_2, From 2b2e1573cffbe5d47712d138690f45e01353c3f5 Mon Sep 17 00:00:00 2001 From: Krunal Bhargav Date: Mon, 16 Sep 2019 13:47:18 +0530 Subject: [PATCH 37/58] arm: omap: emif-common: Fix memory priming for ECC Before the priming begins, we need to disable RMW (Read Modify Write) and disable ECC verification for read accesses. By default, the EMIF tool enables RMW and read accesses in the EMIF_ECC_CTRL_REG. Signed-off-by: Krunal Bhargav Signed-off-by: Lokesh Vutla --- arch/arm/mach-omap2/emif-common.c | 34 +++++++++++++++++++------------ 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-omap2/emif-common.c b/arch/arm/mach-omap2/emif-common.c index 9bdaa388c9..290f9dcdb0 100644 --- a/arch/arm/mach-omap2/emif-common.c +++ b/arch/arm/mach-omap2/emif-common.c @@ -348,7 +348,7 @@ static void dra7_reset_ddr_data(u32 base, u32 size) static void dra7_enable_ecc(u32 base, const struct emif_regs *regs) { struct emif_reg_struct *emif = (struct emif_reg_struct *)base; - u32 rgn, rgn_start, size; + u32 rgn, rgn_start, size, ctrl_reg; /* ECC available only on dra76x EMIF1 */ if ((base != EMIF1_BASE) || !is_dra76x()) @@ -358,11 +358,28 @@ static void dra7_enable_ecc(u32 base, const struct emif_regs *regs) /* Disable high-order interleaving */ clrbits_le32(MA_PRIORITY, MA_HIMEM_INTERLEAVE_UN_MASK); +#ifdef CONFIG_DRA7XX + /* Clear the status flags and other history */ + writel(readl(&emif->emif_1b_ecc_err_cnt), + &emif->emif_1b_ecc_err_cnt); + writel(0xffffffff, &emif->emif_1b_ecc_err_dist_1); + writel(0x2, &emif->emif_1b_ecc_err_addr_log); + writel(0x1, &emif->emif_2b_ecc_err_addr_log); + writel(EMIF_INT_WR_ECC_ERR_SYS_MASK | + EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK | + EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK, + &emif->emif_irqstatus_sys); +#endif writel(regs->emif_ecc_address_range_1, &emif->emif_ecc_address_range_1); writel(regs->emif_ecc_address_range_2, &emif->emif_ecc_address_range_2); - writel(regs->emif_ecc_ctrl_reg, &emif->emif_ecc_ctrl_reg); + + /* Disable RMW and ECC verification for read accesses */ + ctrl_reg = (regs->emif_ecc_ctrl_reg & + ~EMIF_ECC_REG_RMW_EN_MASK) | + EMIF_ECC_CTRL_REG_ECC_VERIFY_DIS_MASK; + writel(ctrl_reg, &emif->emif_ecc_ctrl_reg); /* Set region1 memory with 0 */ rgn_start = (regs->emif_ecc_address_range_1 & @@ -386,17 +403,8 @@ static void dra7_enable_ecc(u32 base, const struct emif_regs *regs) EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK) dra7_reset_ddr_data(rgn, size); -#ifdef CONFIG_DRA7XX - /* Clear the status flags and other history */ - writel(readl(&emif->emif_1b_ecc_err_cnt), - &emif->emif_1b_ecc_err_cnt); - writel(0xffffffff, &emif->emif_1b_ecc_err_dist_1); - writel(0x1, &emif->emif_2b_ecc_err_addr_log); - writel(EMIF_INT_WR_ECC_ERR_SYS_MASK | - EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK | - EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK, - &emif->emif_irqstatus_sys); -#endif + /* Default value enables RMW and ECC verification */ + writel(regs->emif_ecc_ctrl_reg, &emif->emif_ecc_ctrl_reg); } } From 92ffd0d9ed9a8389a7fb28addcd46547d6fb8539 Mon Sep 17 00:00:00 2001 From: Krunal Bhargav Date: Mon, 16 Sep 2019 13:47:19 +0530 Subject: [PATCH 38/58] cmd: ti: ddr3: Move the print statement after test If the ECC is enabled over the entire memory region, we need to ensure the printf/put calls do not modify the stack after ECC is disabled. Moved the printf/put statements after ECC is enabled. Signed-off-by: Krunal Bhargav Signed-off-by: Lokesh Vutla --- cmd/ti/ddr3.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmd/ti/ddr3.c b/cmd/ti/ddr3.c index 34f870ab43..448a7f54a9 100644 --- a/cmd/ti/ddr3.c +++ b/cmd/ti/ddr3.c @@ -202,10 +202,6 @@ static int ddr_memory_ecc_err(u32 addr, u32 ecc_err) writel(val2, addr); val3 = readl(addr); - printf("\tECC test: addr 0x%x, read data 0x%x, written data 0x%x, err pattern: 0x%x, read after write data 0x%x\n", - addr, val1, val2, ecc_err, val3); - - puts("\tECC test: Enabling DDR ECC ...\n"); #ifdef CONFIG_ARCH_KEYSTONE ecc_ctrl = ECC_START_ADDR1 | (ECC_END_ADDR1 << 16); writel(ecc_ctrl, EMIF1_BASE + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET); @@ -214,6 +210,11 @@ static int ddr_memory_ecc_err(u32 addr, u32 ecc_err) writel(ecc_ctrl, &emif->emif_ecc_ctrl_reg); #endif + printf("\tECC test: addr 0x%x, read data 0x%x, written data 0x%x, err pattern: 0x%x, read after write data 0x%x\n", + addr, val1, val2, ecc_err, val3); + + puts("\tECC test: Enabled DDR ECC ...\n"); + val1 = readl(addr); printf("\tECC test: addr 0x%x, read data 0x%x\n", addr, val1); From b1476b52b3bbac8f1e5b49e930d431259a6a7a0a Mon Sep 17 00:00:00 2001 From: Moses Christopher Date: Tue, 17 Sep 2019 14:25:37 +0000 Subject: [PATCH 39/58] am335x, guardian: update guardian board - add BOARD_LATE_INIT function calls in board.c - add swi_status detection in board.c - mux: add guardian interfaces to single pinmux structure - am33xx, kconfig: add BOARD_LATE_INIT for GUARDIAN board Signed-off-by: Moses Christopher Reviewed-by: Tom Rini --- arch/arm/mach-omap2/am33xx/Kconfig | 1 + board/bosch/guardian/board.c | 53 ++++++++++++++++++++++++++++++ board/bosch/guardian/mux.c | 32 +++++++----------- 3 files changed, 65 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig index 7f6b344c82..39d9c2873b 100644 --- a/arch/arm/mach-omap2/am33xx/Kconfig +++ b/arch/arm/mach-omap2/am33xx/Kconfig @@ -89,6 +89,7 @@ config TARGET_AM335X_SHC config TARGET_AM335X_GUARDIAN bool "Support am335x based guardian board from bosch" + select BOARD_LATE_INIT select DM select DM_SERIAL select DM_GPIO diff --git a/board/bosch/guardian/board.c b/board/bosch/guardian/board.c index ec0c4a17f6..072aa4ebb8 100644 --- a/board/bosch/guardian/board.c +++ b/board/bosch/guardian/board.c @@ -172,6 +172,8 @@ void sdram_init(void) int board_init(void) { + save_omap_boot_params(); + #if defined(CONFIG_HW_WATCHDOG) hw_watchdog_init(); #endif @@ -183,3 +185,54 @@ int board_init(void) #endif return 0; } + +#ifdef CONFIG_BOARD_LATE_INIT +static void set_bootmode_env(void) +{ + char *boot_device_name = NULL; + char *boot_mode_gpio = "gpio@44e07000_14"; + int ret; + int value; + + struct gpio_desc boot_mode_desc; + + switch (gd->arch.omap_boot_device) { + case BOOT_DEVICE_NAND: + boot_device_name = "nand"; + break; + case BOOT_DEVICE_USBETH: + boot_device_name = "usbeth"; + break; + default: + break; + } + + if (boot_device_name) + env_set("boot_device", boot_device_name); + + ret = dm_gpio_lookup_name(boot_mode_gpio, &boot_mode_desc); + if (ret) { + printf("%s is not found\n", boot_mode_gpio); + goto err; + } + + ret = dm_gpio_request(&boot_mode_desc, "setup_bootmode_env"); + if (ret && ret != -EBUSY) { + printf("requesting gpio: %s failed\n", boot_mode_gpio); + goto err; + } + + value = dm_gpio_get_value(&boot_mode_desc); + value ? env_set("swi_status", "0") : env_set("swi_status", "1"); + return; + +err: + env_set("swi_status", "err"); +} + +int board_late_init(void) +{ + set_bootmode_env(); + return 0; +} +#endif /* CONFIG_BOARD_LATE_INIT */ diff --git a/board/bosch/guardian/mux.c b/board/bosch/guardian/mux.c index 708c3e7fdd..20a1f2522f 100644 --- a/board/bosch/guardian/mux.c +++ b/board/bosch/guardian/mux.c @@ -26,24 +26,16 @@ static struct module_pin_mux i2c0_pin_mux[] = { {-1}, }; -static struct module_pin_mux adc_voltages_en[] = { - {OFFSET(mcasp0_ahclkx), (MODE(7) | PULLUP_EN)}, - {-1}, -}; - -static struct module_pin_mux asp_power_en[] = { - {OFFSET(mcasp0_aclkx), (MODE(7) | PULLUP_EN)}, - {-1}, -}; - -static struct module_pin_mux switch_off_3v6_pin_mux[] = { - {OFFSET(mii1_txd0), (MODE(7) | PULLUP_EN)}, - /* - * The uart1 lines are made floating inputs, based on the Guardian - * A2 Sample Power Supply Schematics - */ - {OFFSET(uart1_rxd), (MODE(7) | PULLUDDIS)}, - {OFFSET(uart1_txd), (MODE(7) | PULLUDDIS)}, +static struct module_pin_mux guardian_interfaces_pin_mux[] = { + {OFFSET(mcasp0_ahclkx), (MODE(7) | PULLDOWN_EN)}, + {OFFSET(mcasp0_aclkx), (MODE(7) | PULLUP_EN)}, + {OFFSET(mii1_txd0), (MODE(7) | PULLUP_EN)}, + {OFFSET(uart1_rxd), (MODE(7) | RXACTIVE | PULLUDDIS)}, + {OFFSET(uart1_txd), (MODE(7) | PULLUDDIS)}, + {OFFSET(mii1_crs), (MODE(7) | PULLDOWN_EN)}, + {OFFSET(rmii1_refclk), (MODE(7) | PULLDOWN_EN)}, + {OFFSET(mii1_txd3), (MODE(7) | PULLUDDIS)}, + {OFFSET(mii1_rxdv), (MODE(7) | PULLDOWN_EN)}, {-1}, }; @@ -93,7 +85,5 @@ void enable_board_pin_mux(void) #ifdef CONFIG_NAND configure_module_pin_mux(nand_pin_mux); #endif - configure_module_pin_mux(adc_voltages_en); - configure_module_pin_mux(asp_power_en); - configure_module_pin_mux(switch_off_3v6_pin_mux); + configure_module_pin_mux(guardian_interfaces_pin_mux); } From 51d4e47afa9cbd6b83cfc4143bbd7a1fd9981321 Mon Sep 17 00:00:00 2001 From: Moses Christopher Date: Tue, 17 Sep 2019 14:25:38 +0000 Subject: [PATCH 40/58] am335x, guardian: adapt guardian board to DM - update partition table - remove env partitions - dts: add new interfaces (uart2, extra gpio-key) remove unneeded entries update nand timings for performance improvement - defconfig: adapt configurations to suit DM remove unneeded configs - am335x_guardian.h: remove mmc boot Signed-off-by: Moses Christopher Reviewed-by: Tom Rini --- arch/arm/dts/am335x-guardian.dts | 102 +++++++++++++++++------------- configs/am335x_guardian_defconfig | 25 +++++--- include/configs/am335x_guardian.h | 11 ++-- 3 files changed, 80 insertions(+), 58 deletions(-) diff --git a/arch/arm/dts/am335x-guardian.dts b/arch/arm/dts/am335x-guardian.dts index f3f022c375..5ed2133e78 100644 --- a/arch/arm/dts/am335x-guardian.dts +++ b/arch/arm/dts/am335x-guardian.dts @@ -32,12 +32,19 @@ gpio_keys { compatible = "gpio-keys"; pinctrl-names = "default"; - pinctrl-0 = <&gpio_keys_pins>; + pinctrl-0 = <&guardian_button_pins>; - button21 { + select-button { + label = "guardian-select-button"; + linux,code = ; + gpios = <&gpio1 31 GPIO_ACTIVE_LOW>; + wakeup-source; + }; + + power-button { label = "guardian-power-button"; linux,code = ; - gpios = <&gpio2 21 0>; + gpios = <&gpio2 21 GPIO_ACTIVE_LOW>; wakeup-source; }; }; @@ -45,19 +52,12 @@ leds { compatible = "gpio-leds"; pinctrl-names = "default"; - pinctrl-0 = <&leds_pins>; + pinctrl-0 = <&guardian_led_pins>; - led1 { - label = "green:heartbeat"; - gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "heartbeat"; - default-state = "off"; - }; - - led2 { - label = "green:mmc0"; + life-led { + label = "guardian:life-led"; gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "mmc0"; + linux,default-trigger = "heartbeat"; default-state = "off"; }; }; @@ -140,22 +140,25 @@ gpmc,device-width = <1>; gpmc,sync-clk-ps = <0>; gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <44>; - gpmc,cs-wr-off-ns = <44>; - gpmc,adv-on-ns = <6>; - gpmc,adv-rd-off-ns = <34>; - gpmc,adv-wr-off-ns = <44>; + gpmc,cs-rd-off-ns = <30>; + gpmc,cs-wr-off-ns = <30>; + gpmc,adv-on-ns = <0>; + gpmc,adv-rd-off-ns = <30>; + gpmc,adv-wr-off-ns = <30>; gpmc,we-on-ns = <0>; - gpmc,we-off-ns = <40>; - gpmc,oe-on-ns = <0>; - gpmc,oe-off-ns = <54>; - gpmc,access-ns = <64>; - gpmc,rd-cycle-ns = <82>; - gpmc,wr-cycle-ns = <82>; + gpmc,we-off-ns = <15>; + gpmc,oe-on-ns = <1>; + gpmc,oe-off-ns = <15>; + gpmc,access-ns = <30>; + gpmc,rd-cycle-ns = <30>; + gpmc,wr-cycle-ns = <30>; + gpmc,wait-on-read = "true"; + gpmc,wait-on-write = "true"; gpmc,bus-turnaround-ns = <0>; gpmc,cycle2cycle-delay-ns = <0>; gpmc,clk-activation-ns = <0>; - gpmc,wr-access-ns = <40>; + gpmc,wait-monitoring-ns = <0>; + gpmc,wr-access-ns = <0>; gpmc,wr-data-mux-bus-ns = <0>; /* @@ -199,18 +202,8 @@ }; partition@6 { - label = "u-boot-env"; - reg = <0x300000 0x40000>; - }; - - partition@7 { - label = "u-boot-env.backup1"; - reg = <0x340000 0x40000>; - }; - - partition@8 { label = "UBI"; - reg = <0x380000 0x1fc80000>; + reg = <0x300000 0x1fd00000>; }; }; }; @@ -326,6 +319,12 @@ status = "okay"; }; +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "okay"; +}; + &usb { status = "okay"; }; @@ -354,7 +353,7 @@ &am33xx_pinmux { pinctrl-names = "default"; - pinctrl-0 = <&clkout2_pin &gpio_pins>; + pinctrl-0 = <&clkout2_pin &guardian_interface_pins>; clkout2_pin: pinmux_clkout2_pin { pinctrl-single,pins = < @@ -368,16 +367,25 @@ >; }; - gpio_keys_pins: pinmux_gpio_keys_pins { + guardian_button_pins: pinmux_gpio_keys_pins { pinctrl-single,pins = < AM33XX_IOPAD(0x940, PIN_INPUT | MUX_MODE7) + AM33XX_IOPAD(0x884, PIN_INPUT | MUX_MODE7) >; }; - gpio_pins: pinmux_gpio_pins { + guardian_interface_pins: pinmux_guardian_interface_pins { pinctrl-single,pins = < - AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE7) - AM33XX_IOPAD(0x990, PIN_OUTPUT | MUX_MODE7) + AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE7) + AM33XX_IOPAD(0x990, PIN_OUTPUT | MUX_MODE7) + AM33XX_IOPAD(0x9ac, PIN_OUTPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE7) + AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE7) + AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLUP | MUX_MODE7) + AM33XX_IOPAD(0x90c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x944, PIN_OUTPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x91c, PIN_INPUT | MUX_MODE7) + AM33XX_IOPAD(0x918, PIN_OUTPUT_PULLDOWN | MUX_MODE7) >; }; @@ -452,10 +460,9 @@ >; }; - leds_pins: pinmux_leds_pins { + guardian_led_pins: pinmux_leds_pins { pinctrl-single,pins = < AM33XX_IOPAD(0x868, PIN_OUTPUT | MUX_MODE7) - AM33XX_IOPAD(0x86c, PIN_OUTPUT | MUX_MODE7) >; }; @@ -487,6 +494,13 @@ >; }; + uart2_pins: pinmux_uart2_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE1) + AM33XX_IOPAD(0x930, PIN_OUTPUT_PULLDOWN | MUX_MODE1) + >; + }; + nandflash_pins: pinmux_nandflash_pins { pinctrl-single,pins = < AM33XX_IOPAD(0x800, PIN_INPUT | MUX_MODE0) diff --git a/configs/am335x_guardian_defconfig b/configs/am335x_guardian_defconfig index 3cada51d35..3ce324193f 100644 --- a/configs/am335x_guardian_defconfig +++ b/configs/am335x_guardian_defconfig @@ -6,11 +6,10 @@ CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_AM33XX=y CONFIG_TARGET_AM335X_GUARDIAN=y -CONFIG_SPL_MMC_SUPPORT=y +# CONFIG_SPL_MMC_SUPPORT is not set CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_DRIVERS_MISC_SUPPORT=y CONFIG_ENV_SIZE=0x040000 -CONFIG_ENV_OFFSET=0x300000 CONFIG_SPL=y CONFIG_BOOTSTAGE_STASH_ADDR=0x0 CONFIG_SPL_LIBDISK_SUPPORT=y @@ -21,6 +20,7 @@ CONFIG_VERSION_VARIABLE=y CONFIG_ARCH_MISC_INIT=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_SPL_SEPARATE_BSS=y +# CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR is not set CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_ETH_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y @@ -30,8 +30,8 @@ CONFIG_SPL_NET_VCI_STRING="Guardian U-Boot SPL" CONFIG_SPL_POWER_SUPPORT=y CONFIG_SPL_USB_GADGET=y CONFIG_SPL_USB_ETHER=y -CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_YMODEM_SUPPORT=y +# CONFIG_SPL_WATCHDOG_SUPPORT is not set +# CONFIG_SPL_YMODEM_SUPPORT is not set CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n" CONFIG_AUTOBOOT_DELAY_STR="d" @@ -43,14 +43,14 @@ CONFIG_CMD_ASKENV=y CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y CONFIG_CMD_I2C=y -CONFIG_CMD_MMC=y +# CONFIG_CMD_MMC is not set CONFIG_CMD_MTD=y CONFIG_CMD_NAND=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_MTDPARTS=y -CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:256k(SPL),256k(SPL.backup1),256k(SPL.backup2),256k(SPL.backup3),1m(u-boot),1m(u-boot.backup1),256k(u-boot-env),256k(u-boot-env.backup1),-(UBI)" +CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:256k(SPL),256k(SPL.backup1),256k(SPL.backup2),256k(SPL.backup3),1m(u-boot),1m(u-boot.backup1),-(UBI)" CONFIG_CMD_UBI=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_ISO_PARTITION is not set @@ -58,14 +58,17 @@ CONFIG_CMD_UBI=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="am335x-guardian" -CONFIG_ENV_IS_IN_NAND=y +CONFIG_OF_SEPARATE=y +CONFIG_ENV_IS_NOWHERE=y CONFIG_SPL_ENV_IS_NOWHERE=y CONFIG_SPL_DM=y +CONFIG_SPL_DM_USB=y CONFIG_BOOTCOUNT_LIMIT=y CONFIG_BOOTCOUNT_ENV=y CONFIG_MISC=y -CONFIG_DM_MMC=y -CONFIG_MMC_OMAP_HS=y +# CONFIG_DM_MMC is not set +# CONFIG_MMC is not set +# CONFIG_MMC_OMAP_HS is not set CONFIG_MTD=y CONFIG_NAND=y CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y @@ -78,15 +81,19 @@ CONFIG_PHY=y CONFIG_NOP_PHY=y CONFIG_PINCTRL=y CONFIG_PINCTRL_SINGLE=y +# CONFIG_WATCHDOG is not set +CONFIG_SPL_WDT=y CONFIG_USB=y CONFIG_DM_USB_GADGET=y CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_MUSB_HOST=y CONFIG_USB_MUSB_GADGET=y CONFIG_USB_MUSB_TI=y +CONFIG_USB_MUSB_DSPS=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" CONFIG_USB_GADGET_VENDOR_NUM=0x0451 CONFIG_USB_GADGET_PRODUCT_NUM=0xd022 CONFIG_USB_ETHER=y +# CONFIG_USB_STORAGE is not set CONFIG_FAT_WRITE=y diff --git a/include/configs/am335x_guardian.h b/include/configs/am335x_guardian.h index 8bde198313..b45b8d2eec 100644 --- a/include/configs/am335x_guardian.h +++ b/include/configs/am335x_guardian.h @@ -16,10 +16,14 @@ #define CONFIG_TIMESTAMP #endif +#define CONFIG_SYS_BOOTM_LEN (16 << 20) + /* Clock Defines */ #define V_OSCK 24000000 /* Clock output from T2 */ #define V_SCLK (V_OSCK) +#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG + #ifndef CONFIG_SPL_BUILD #define MEM_LAYOUT_ENV_SETTINGS \ @@ -30,7 +34,6 @@ "ramdisk_addr_r=0x88080000\0" \ #define BOOT_TARGET_DEVICES(func) \ - func(MMC, mmc, 0) \ func(UBIFS, ubifs, 0) \ func(PXE, pxe, na) \ func(DHCP, dhcp, na) @@ -44,11 +47,12 @@ MEM_LAYOUT_ENV_SETTINGS \ BOOTENV \ "bootlimit=3\0" \ + "bootubivol=rootfs\0" \ "altbootcmd=" \ "setenv boot_config \"extlinux-rollback.conf\"; " \ "run distro_bootcmd\0" -#endif /* CONFIG_SPL_BUILD */ +#endif /* ! CONFIG_SPL_BUILD */ /* NS16550 Configuration */ #define CONFIG_SYS_NS16550_COM1 0x44e09000 /* UART0 */ @@ -65,9 +69,6 @@ #define CONFIG_SYS_BOOTCOUNT_LE #ifdef CONFIG_NAND -#define CONFIG_ENV_OFFSET 0x300000 -#define CONFIG_ENV_OFFSET_REDUND 0x340000 -#define CONFIG_ENV_SIZE 0x040000 #define CONFIG_SYS_NAND_5_ADDR_CYCLE #define CONFIG_SYS_NAND_PAGE_COUNT (CONFIG_SYS_NAND_BLOCK_SIZE / \ From 87875f252859c45f2e5d8cfd76f8409dce2b17cc Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 17 Sep 2019 15:40:25 -0400 Subject: [PATCH 41/58] configs: ti: Use addr_fit for run_fit environment variable When running 'run_fit' the FIT file should have been loaded at 'addr_fit', although at this point they should be the same use this variable instead of 'loadaddr'. Signed-off-by: Andrew F. Davis --- include/configs/ti_armv7_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h index 2de6bc2390..6d15304a65 100644 --- a/include/configs/ti_armv7_common.h +++ b/include/configs/ti_armv7_common.h @@ -60,7 +60,7 @@ "do;" \ "setenv overlaystring ${overlaystring}'#'${overlay};" \ "done;\0" \ - "run_fit=bootm ${loadaddr}#${fdtfile}${overlaystring}\0" \ + "run_fit=bootm ${addr_fit}#${fdtfile}${overlaystring}\0" \ "loadfit=run args_mmc; run run_fit;\0" \ /* From e704cd64666eda5f9e18df5eabd2f1e94d7e0dc7 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Tue, 24 Sep 2019 13:17:16 +0530 Subject: [PATCH 42/58] mmc: am654_sdhci: Drop a redundant power_domain_on in probe Power-domain is enabled by default in device_probe. am654 mmc driver is enabling power-domain again in probe. As the second call is redundant, drop power_domain_on from probe. Tested-by: Suman Anna Signed-off-by: Lokesh Vutla Reviewed-by: Peng Fan --- drivers/mmc/am654_sdhci.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c index 1793a3f99a..7cd5516197 100644 --- a/drivers/mmc/am654_sdhci.c +++ b/drivers/mmc/am654_sdhci.c @@ -219,23 +219,10 @@ static int am654_sdhci_probe(struct udevice *dev) struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sdhci_host *host = dev_get_priv(dev); struct mmc_config *cfg = &plat->cfg; - struct power_domain sdhci_pwrdmn; struct clk clk; unsigned long clock; int ret; - ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0); - if (!ret) { - ret = power_domain_on(&sdhci_pwrdmn); - if (ret) { - dev_err(dev, "Power domain on failed (%d)\n", ret); - return ret; - } - } else if (ret != -ENOENT && ret != -ENODEV && ret != -ENOSYS) { - dev_err(dev, "failed to get power domain (%d)\n", ret); - return ret; - } - ret = clk_get_by_index(dev, 0, &clk); if (ret) { dev_err(dev, "failed to get clock\n"); From 523555fc1711ba9f4ccfca649223d445fd956751 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 25 Sep 2019 14:38:05 +0530 Subject: [PATCH 43/58] configs: am65x_evm_a53: Disable PSCI_RESET AM65x uses TISCI protocol to reset the device and does not support PSCI reset. So disable PSCI reset. Signed-off-by: Lokesh Vutla --- configs/am65x_evm_a53_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index 453177bde1..4022801260 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -12,6 +12,7 @@ CONFIG_NR_DRAM_BANKS=2 CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FS_FAT=y CONFIG_SPL_LIBDISK_SUPPORT=y +# CONFIG_PSCI_RESET is not set CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_DISTRO_DEFAULTS=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set From d53a1772718f58950f6ee5968ca08fd6926ca3c2 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 25 Sep 2019 14:38:13 +0530 Subject: [PATCH 44/58] configs: j721e_evm_a72: Disable PSCI_RESET J721E uses TISCI protocol to reset the device and does not support PSCI reset. So disable PSCI reset. Signed-off-by: Lokesh Vutla --- configs/j721e_evm_a72_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig index d455d17d26..c66365767f 100644 --- a/configs/j721e_evm_a72_defconfig +++ b/configs/j721e_evm_a72_defconfig @@ -14,6 +14,7 @@ CONFIG_SPL_FS_FAT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y +# CONFIG_PSCI_RESET is not set CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_DISTRO_DEFAULTS=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set From f8ca9121896bcff1476943a96d7392eb05f55364 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Fri, 27 Sep 2019 13:32:11 +0530 Subject: [PATCH 45/58] arm: k3: Add support for printing CPUINFO Add support for printing CPU info for all K3 devices. Signed-off-by: Lokesh Vutla --- arch/arm/mach-k3/common.c | 42 ++++++++++++++++++++++++ arch/arm/mach-k3/common.h | 6 ++++ arch/arm/mach-k3/include/mach/hardware.h | 18 ++++++++++ 3 files changed, 66 insertions(+) diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index 6c453b9af4..97aa15d6a6 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include struct ti_sci_handle *get_ti_sci_handle(void) { @@ -190,3 +192,43 @@ void reset_cpu(ulong ignored) { } #endif + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + u32 soc, rev; + char *name; + + soc = (readl(CTRLMMR_WKUP_JTAG_DEVICE_ID) & + DEVICE_ID_FAMILY_MASK) >> DEVICE_ID_FAMILY_SHIFT; + rev = (readl(CTRLMMR_WKUP_JTAG_ID) & + JTAG_ID_VARIANT_MASK) >> JTAG_ID_VARIANT_SHIFT; + + printf("SoC: "); + switch (soc) { + case AM654: + name = "AM654"; + break; + case J721E: + name = "J721E"; + break; + default: + name = "Unknown Silicon"; + }; + + printf("%s PG ", name); + switch (rev) { + case REV_PG1_0: + name = "1.0"; + break; + case REV_PG2_0: + name = "2.0"; + break; + default: + name = "Unknown Revision"; + }; + printf("%s\n", name); + + return 0; +} +#endif diff --git a/arch/arm/mach-k3/common.h b/arch/arm/mach-k3/common.h index ab68e14de8..8f9a023921 100644 --- a/arch/arm/mach-k3/common.h +++ b/arch/arm/mach-k3/common.h @@ -8,5 +8,11 @@ #include +#define AM654 2 +#define J721E 4 + +#define REV_PG1_0 0 +#define REV_PG2_0 1 + void setup_k3_mpu_regions(void); int early_console_init(void); diff --git a/arch/arm/mach-k3/include/mach/hardware.h b/arch/arm/mach-k3/include/mach/hardware.h index 4e629822aa..d670d5a56e 100644 --- a/arch/arm/mach-k3/include/mach/hardware.h +++ b/arch/arm/mach-k3/include/mach/hardware.h @@ -13,4 +13,22 @@ #ifdef CONFIG_SOC_K3_J721E #include "j721e_hardware.h" #endif + +/* Assuming these addresses and definitions stay common across K3 devices */ +#define CTRLMMR_WKUP_JTAG_DEVICE_ID 0x43000018 +#define DEVICE_ID_FAMILY_SHIFT 26 +#define DEVICE_ID_FAMILY_MASK (0x3f << 26) +#define DEVICE_ID_BASE_SHIFT 11 +#define DEVICE_ID_BASE_MASK (0x1fff << 11) +#define DEVICE_ID_SPEED_SHIFT 6 +#define DEVICE_ID_SPEED_MASK (0x1f << 6) +#define DEVICE_ID_TEMP_SHIFT 3 +#define DEVICE_ID_TEMP_MASK (0x7 << 3) + +#define CTRLMMR_WKUP_JTAG_ID 0x43000014 +#define JTAG_ID_VARIANT_SHIFT 28 +#define JTAG_ID_VARIANT_MASK (0xf << 28) +#define JTAG_ID_PARTNO_SHIFT 12 +#define JTAG_ID_PARTNO_MASK (0x7ff << 1) + #endif /* _ASM_ARCH_HARDWARE_H_ */ From bd8f138f5a1ed9bcd1339b0fb1daa2d024b472d1 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Fri, 27 Sep 2019 13:32:12 +0530 Subject: [PATCH 46/58] board: am65x: Print board name and version during boot Print the board name and ver along with the DT Model. While at it print the ver for all the detected daughter cards. Signed-off-by: Lokesh Vutla --- board/ti/am65x/evm.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c index ad333ad883..544f872459 100644 --- a/board/ti/am65x/evm.c +++ b/board/ti/am65x/evm.c @@ -127,6 +127,19 @@ int do_board_detect(void) return ret; } +int checkboard(void) +{ + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + + if (do_board_detect()) + /* EEPROM not populated */ + printf("Board: %s rev %s\n", "AM6-COMPROCEVM", "E3"); + else + printf("Board: %s rev %s\n", ep->name, ep->version); + + return 0; +} + static void setup_board_eeprom_env(void) { char *name = "am65x"; @@ -272,7 +285,7 @@ static int probe_daughtercards(void) if (strncmp(ep.name, cards[i].card_name, sizeof(ep.name))) continue; - printf("detected %s\n", cards[i].card_name); + printf("Detected: %s rev %s\n", ep.name, ep.version); /* * Populate any MAC addresses from daughtercard into the U-Boot From 4fce88611d114a07cd13cee31427c5eb62ab7ac5 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Fri, 27 Sep 2019 13:32:13 +0530 Subject: [PATCH 47/58] configs: j721e_evm_a72: Enable DISPLAY_CPUINFO Enable CONFIG_DISPLAY_CPUINFO so that cpuinfo is printed during boot. Signed-off-by: Lokesh Vutla --- configs/j721e_evm_a72_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig index c66365767f..6729e03620 100644 --- a/configs/j721e_evm_a72_defconfig +++ b/configs/j721e_evm_a72_defconfig @@ -20,7 +20,6 @@ CONFIG_DISTRO_DEFAULTS=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_LOAD_FIT=y CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run boot_rprocs; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern" -# CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y From ac2251181884dba6aefec3b82cd9ba19ee3d3b03 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Fri, 27 Sep 2019 13:32:14 +0530 Subject: [PATCH 48/58] configs: am65x_evm_a53: Enable DISPLAY_CPUINFO Enable CONFIG_DISPLAY_CPUINFO so that cpuinfo is printed during boot. Signed-off-by: Lokesh Vutla --- configs/am65x_evm_a53_defconfig | 1 - configs/am65x_hs_evm_a53_defconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index 4022801260..c60978c9be 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -19,7 +19,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_SPL_LOAD_FIT=y CONFIG_OF_BOARD_SETUP=y CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run boot_rprocs; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern" -# CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig index e9fceea58c..caee953426 100644 --- a/configs/am65x_hs_evm_a53_defconfig +++ b/configs/am65x_hs_evm_a53_defconfig @@ -21,7 +21,6 @@ CONFIG_SPL_LOAD_FIT=y CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y CONFIG_OF_BOARD_SETUP=y CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_fit_${boot}; run get_overlaystring; run run_fit" -# CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y From e69ffdb763dec192102f2705cac14f38c56d9b62 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Fri, 27 Sep 2019 13:32:15 +0530 Subject: [PATCH 49/58] arm: k3: Use driver_name to get ti_sci handle Use the driver name to get ti_sci handle rather than relying on just the FIRMWARE uclass. Signed-off-by: Lokesh Vutla --- arch/arm/mach-k3/common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index 97aa15d6a6..f8274b39d6 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -22,7 +22,8 @@ struct ti_sci_handle *get_ti_sci_handle(void) struct udevice *dev; int ret; - ret = uclass_get_device(UCLASS_FIRMWARE, 0, &dev); + ret = uclass_get_device_by_driver(UCLASS_FIRMWARE, + DM_GET_DRIVER(ti_sci), &dev); if (ret) panic("Failed to get SYSFW (%d)\n", ret); From 260777fc2333183728d24fb0ffaa22a888c09655 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 27 Sep 2019 19:14:26 +0300 Subject: [PATCH 50/58] clk: cdce9xx: add support for cdce9xx clock synthesizer Add support for CDCE913/925/937/949 family of devices. These are modular PLL-based low cost, high performance, programmable clock synthesizers, multipliers and dividers. They generate up to 9 output clocks from a single input frequency. The initial version of the driver does not support programming of the PLLs, and thus they run in the bypass mode only. The code is loosely based on the linux kernel cdce9xx driver. Signed-off-by: Tero Kristo --- doc/device-tree-bindings/clock/ti,cdce9xx.txt | 49 ++++ drivers/clk/Kconfig | 7 + drivers/clk/Makefile | 1 + drivers/clk/clk-cdce9xx.c | 254 ++++++++++++++++++ 4 files changed, 311 insertions(+) create mode 100644 doc/device-tree-bindings/clock/ti,cdce9xx.txt create mode 100644 drivers/clk/clk-cdce9xx.c diff --git a/doc/device-tree-bindings/clock/ti,cdce9xx.txt b/doc/device-tree-bindings/clock/ti,cdce9xx.txt new file mode 100644 index 0000000000..0d01f2d5cc --- /dev/null +++ b/doc/device-tree-bindings/clock/ti,cdce9xx.txt @@ -0,0 +1,49 @@ +Binding for TI CDCE913/925/937/949 programmable I2C clock synthesizers. + +Reference +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] http://www.ti.com/product/cdce913 +[3] http://www.ti.com/product/cdce925 +[4] http://www.ti.com/product/cdce937 +[5] http://www.ti.com/product/cdce949 + +The driver provides clock sources for each output Y1 through Y5. + +Required properties: + - compatible: Shall be one of the following: + - "ti,cdce913": 1-PLL, 3 Outputs + - "ti,cdce925": 2-PLL, 5 Outputs + - "ti,cdce937": 3-PLL, 7 Outputs + - "ti,cdce949": 4-PLL, 9 Outputs + - reg: I2C device address. + - clocks: Points to a fixed parent clock that provides the input frequency. + - #clock-cells: From common clock bindings: Shall be 1. + +Optional properties: + - xtal-load-pf: Crystal load-capacitor value to fine-tune performance on a + board, or to compensate for external influences. + +For all PLL1, PLL2, ... an optional child node can be used to specify spread +spectrum clocking parameters for a board. + - spread-spectrum: SSC mode as defined in the data sheet. + - spread-spectrum-center: Use "centered" mode instead of "max" mode. When + present, the clock runs at the requested frequency on average. Otherwise + the requested frequency is the maximum value of the SCC range. + + +Example: + + clockgen: cdce925pw@64 { + compatible = "cdce925"; + reg = <0x64>; + clocks = <&xtal_27Mhz>; + #clock-cells = <1>; + xtal-load-pf = <5>; + /* PLL options to get SSC 1% centered */ + PLL2 { + spread-spectrum = <4>; + spread-spectrum-center; + }; + }; diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 0035f0a9c6..16d4237f89 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -134,6 +134,13 @@ config CLK_STM32MP1 Enable the STM32 clock (RCC) driver. Enable support for manipulating STM32MP1's on-SoC clocks. +config CLK_CDCE9XX + bool "Enable CDCD9XX clock driver" + depends on CLK + help + Enable the clock synthesizer driver for CDCE913/925/937/949 + series of chips. + source "drivers/clk/analogbits/Kconfig" source "drivers/clk/at91/Kconfig" source "drivers/clk/exynos/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index d7cea3b8bf..8de6777468 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -44,3 +44,4 @@ obj-$(CONFIG_SANDBOX_CLK_CCF) += clk_sandbox_ccf.o obj-$(CONFIG_STM32H7) += clk_stm32h7.o obj-$(CONFIG_CLK_TI_SCI) += clk-ti-sci.o obj-$(CONFIG_CLK_VERSAL) += clk_versal.o +obj-$(CONFIG_CLK_CDCE9XX) += clk-cdce9xx.o diff --git a/drivers/clk/clk-cdce9xx.c b/drivers/clk/clk-cdce9xx.c new file mode 100644 index 0000000000..5d1489ab0e --- /dev/null +++ b/drivers/clk/clk-cdce9xx.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments CDCE913/925/937/949 clock synthesizer driver + * + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Tero Kristo + * + * Based on Linux kernel clk-cdce925.c. + */ + +#include +#include +#include +#include +#include + +#define MAX_NUMBER_OF_PLLS 4 +#define MAX_NUMER_OF_OUTPUTS 9 + +#define CDCE9XX_REG_GLOBAL1 0x01 +#define CDCE9XX_REG_Y1SPIPDIVH 0x02 +#define CDCE9XX_REG_PDIV1L 0x03 +#define CDCE9XX_REG_XCSEL 0x05 + +#define CDCE9XX_PDIV1_H_MASK 0x3 + +#define CDCE9XX_REG_PDIV(clk) (0x16 + (((clk) - 1) & 1) + \ + ((clk) - 1) / 2 * 0x10) + +#define CDCE9XX_PDIV_MASK 0x7f + +#define CDCE9XX_BYTE_TRANSFER BIT(7) + +struct cdce9xx_chip_info { + int num_plls; + int num_outputs; +}; + +struct cdce9xx_clk_data { + struct udevice *i2c; + struct cdce9xx_chip_info *chip; + u32 xtal_rate; +}; + +static const struct cdce9xx_chip_info cdce913_chip_info = { + .num_plls = 1, .num_outputs = 3, +}; + +static const struct cdce9xx_chip_info cdce925_chip_info = { + .num_plls = 2, .num_outputs = 5, +}; + +static const struct cdce9xx_chip_info cdce937_chip_info = { + .num_plls = 3, .num_outputs = 7, +}; + +static const struct cdce9xx_chip_info cdce949_chip_info = { + .num_plls = 4, .num_outputs = 9, +}; + +static int cdce9xx_reg_read(struct udevice *dev, u8 addr, u8 *buf) +{ + struct cdce9xx_clk_data *data = dev_get_priv(dev); + int ret; + + ret = dm_i2c_read(data->i2c, addr | CDCE9XX_BYTE_TRANSFER, buf, 1); + if (ret) + dev_err(dev, "%s: failed for addr:%x, ret:%d\n", __func__, + addr, ret); + + return ret; +} + +static int cdce9xx_reg_write(struct udevice *dev, u8 addr, u8 val) +{ + struct cdce9xx_clk_data *data = dev_get_priv(dev); + int ret; + + ret = dm_i2c_write(data->i2c, addr | CDCE9XX_BYTE_TRANSFER, &val, 1); + if (ret) + dev_err(dev, "%s: failed for addr:%x, ret:%d\n", __func__, + addr, ret); + + return ret; +} + +static int cdce9xx_clk_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args) +{ + struct cdce9xx_clk_data *data = dev_get_priv(clk->dev); + + if (args->args_count != 1) + return -EINVAL; + + if (args->args[0] > data->chip->num_outputs) + return -EINVAL; + + clk->id = args->args[0]; + + return 0; +} + +static int cdce9xx_clk_probe(struct udevice *dev) +{ + struct cdce9xx_clk_data *data = dev_get_priv(dev); + struct cdce9xx_chip_info *chip = (void *)dev_get_driver_data(dev); + int ret; + u32 val; + struct clk clk; + + val = (u32)dev_read_addr_ptr(dev); + + ret = i2c_get_chip(dev->parent, val, 1, &data->i2c); + if (ret) { + dev_err(dev, "I2C probe failed.\n"); + return ret; + } + + data->chip = chip; + + ret = clk_get_by_index(dev, 0, &clk); + data->xtal_rate = clk_get_rate(&clk); + + val = dev_read_u32_default(dev, "xtal-load-pf", -1); + if (val >= 0) + cdce9xx_reg_write(dev, CDCE9XX_REG_XCSEL, val << 3); + + return 0; +} + +static u16 cdce9xx_clk_get_pdiv(struct clk *clk) +{ + u8 val; + u16 pdiv; + int ret; + + if (clk->id == 0) { + ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, &val); + if (ret) + return 0; + + pdiv = (val & CDCE9XX_PDIV1_H_MASK) << 8; + + ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV1L, &val); + if (ret) + return 0; + + pdiv |= val; + } else { + ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV(clk->id), + &val); + if (ret) + return 0; + + pdiv = val & CDCE9XX_PDIV_MASK; + } + + return pdiv; +} + +static u32 cdce9xx_clk_get_parent_rate(struct clk *clk) +{ + struct cdce9xx_clk_data *data = dev_get_priv(clk->dev); + + return data->xtal_rate; +} + +static ulong cdce9xx_clk_get_rate(struct clk *clk) +{ + u32 parent_rate; + u16 pdiv; + + parent_rate = cdce9xx_clk_get_parent_rate(clk); + + pdiv = cdce9xx_clk_get_pdiv(clk); + + return parent_rate / pdiv; +} + +static ulong cdce9xx_clk_set_rate(struct clk *clk, ulong rate) +{ + u32 parent_rate; + int pdiv; + u32 diff; + u8 val; + int ret; + + parent_rate = cdce9xx_clk_get_parent_rate(clk); + + pdiv = parent_rate / rate; + + diff = rate - parent_rate / pdiv; + + if (rate - parent_rate / (pdiv + 1) < diff) + pdiv++; + + if (clk->id == 0) { + ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, &val); + if (ret) + return ret; + + val &= ~CDCE9XX_PDIV1_H_MASK; + + val |= (pdiv >> 8); + + ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, val); + if (ret) + return ret; + + ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_PDIV1L, + (pdiv & 0xff)); + if (ret) + return ret; + } else { + ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV(clk->id), + &val); + if (ret) + return ret; + + val &= ~CDCE9XX_PDIV_MASK; + + val |= pdiv; + + ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_PDIV(clk->id), + val); + if (ret) + return ret; + } + + return 0; +} + +static const struct udevice_id cdce9xx_clk_of_match[] = { + { .compatible = "ti,cdce913", .data = (u32)&cdce913_chip_info }, + { .compatible = "ti,cdce925", .data = (u32)&cdce925_chip_info }, + { .compatible = "ti,cdce937", .data = (u32)&cdce937_chip_info }, + { .compatible = "ti,cdce949", .data = (u32)&cdce949_chip_info }, + { /* sentinel */ }, +}; + +static const struct clk_ops cdce9xx_clk_ops = { + .of_xlate = cdce9xx_clk_of_xlate, + .get_rate = cdce9xx_clk_get_rate, + .set_rate = cdce9xx_clk_set_rate, +}; + +U_BOOT_DRIVER(cdce9xx_clk) = { + .name = "cdce9xx-clk", + .id = UCLASS_CLK, + .of_match = cdce9xx_clk_of_match, + .probe = cdce9xx_clk_probe, + .priv_auto_alloc_size = sizeof(struct cdce9xx_clk_data), + .ops = &cdce9xx_clk_ops, +}; From e8e683d33b0ccd43e03809bf4ea88a899a867473 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 27 Sep 2019 19:14:27 +0300 Subject: [PATCH 51/58] board: ti: am57xx-idk: Configure the CDCE913 clock synthesizer AM57xx-IDK boards contain the CDCE913 clock synthesizer, and their reset crystal capacitance load value of 10pF is wrong leading into lost packets in certain networking tests. Add DT data for this device, and probe it from the board file to program the crystal capacitance load value to 0pF to avoid any problems. Signed-off-by: Tero Kristo --- arch/arm/dts/am571x-idk-u-boot.dtsi | 5 +++++ arch/arm/dts/am572x-idk-u-boot.dtsi | 5 +++++ arch/arm/dts/am574x-idk-u-boot.dtsi | 5 +++++ arch/arm/dts/am57xx-idk-common-u-boot.dtsi | 23 ++++++++++++++++++++++ board/ti/am57xx/board.c | 5 +++++ configs/am57xx_evm_defconfig | 2 ++ 6 files changed, 45 insertions(+) create mode 100644 arch/arm/dts/am571x-idk-u-boot.dtsi create mode 100644 arch/arm/dts/am572x-idk-u-boot.dtsi create mode 100644 arch/arm/dts/am574x-idk-u-boot.dtsi create mode 100644 arch/arm/dts/am57xx-idk-common-u-boot.dtsi diff --git a/arch/arm/dts/am571x-idk-u-boot.dtsi b/arch/arm/dts/am571x-idk-u-boot.dtsi new file mode 100644 index 0000000000..65199200ed --- /dev/null +++ b/arch/arm/dts/am571x-idk-u-boot.dtsi @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ +#include "am57xx-idk-common-u-boot.dtsi" diff --git a/arch/arm/dts/am572x-idk-u-boot.dtsi b/arch/arm/dts/am572x-idk-u-boot.dtsi new file mode 100644 index 0000000000..65199200ed --- /dev/null +++ b/arch/arm/dts/am572x-idk-u-boot.dtsi @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ +#include "am57xx-idk-common-u-boot.dtsi" diff --git a/arch/arm/dts/am574x-idk-u-boot.dtsi b/arch/arm/dts/am574x-idk-u-boot.dtsi new file mode 100644 index 0000000000..65199200ed --- /dev/null +++ b/arch/arm/dts/am574x-idk-u-boot.dtsi @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ +#include "am57xx-idk-common-u-boot.dtsi" diff --git a/arch/arm/dts/am57xx-idk-common-u-boot.dtsi b/arch/arm/dts/am57xx-idk-common-u-boot.dtsi new file mode 100644 index 0000000000..b07aea0048 --- /dev/null +++ b/arch/arm/dts/am57xx-idk-common-u-boot.dtsi @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ +#include "omap5-u-boot.dtsi" + +/ { + xtal25mhz: xtal25mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; +}; + +&i2c1 { + cdce913: cdce913@65 { + compatible = "ti,cdce913"; + reg = <0x65>; + clocks = <&xtal25mhz>; + #clock-cells = <1>; + xtal-load-pf = <0>; + }; +}; diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c index f78e6c2e1f..237a834c53 100644 --- a/board/ti/am57xx/board.c +++ b/board/ti/am57xx/board.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "../common/board_detect.h" #include "mux_data.h" @@ -689,6 +690,7 @@ int board_late_init(void) { setup_board_eeprom_env(); u8 val; + struct udevice *dev; /* * DEV_CTRL.DEV_ON = 1 please - else palmas switches off in 8 seconds @@ -720,6 +722,9 @@ int board_late_init(void) am57x_idk_lcd_detect(); + /* Just probe the potentially supported cdce913 device */ + uclass_get_device(UCLASS_CLK, 0, &dev); + #if !defined(CONFIG_SPL_BUILD) board_ti_set_ethaddr(2); #endif diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig index 3b613e135c..e2f558cde7 100644 --- a/configs/am57xx_evm_defconfig +++ b/configs/am57xx_evm_defconfig @@ -98,3 +98,5 @@ CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" CONFIG_USB_GADGET_VENDOR_NUM=0x0451 CONFIG_USB_GADGET_PRODUCT_NUM=0xd022 +CONFIG_CLK=y +CONFIG_CLK_CDCE9XX=y From 9850d4e52f7f8da1bab7fae32f90e8eba7b4f6af Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 27 Sep 2019 19:14:28 +0300 Subject: [PATCH 52/58] board: ti: am43xx-idk: Configure the CDCE913 clock synthesizer AM43xx-IDK boards contain the CDCE913 clock synthesizer, and their reset crystal capacitance load value of 10pF is wrong leading into lost packets in certain networking tests. Add DT data for this device, and probe it from the board file to program the crystal capacitance load value to 0pF to avoid any problems. Signed-off-by: Tero Kristo --- arch/arm/dts/am437x-idk-evm-u-boot.dtsi | 14 ++++++++++++++ board/ti/am43xx/board.c | 5 +++++ configs/am43xx_evm_defconfig | 2 ++ 3 files changed, 21 insertions(+) diff --git a/arch/arm/dts/am437x-idk-evm-u-boot.dtsi b/arch/arm/dts/am437x-idk-evm-u-boot.dtsi index 3aa9195e44..50fe09cfc3 100644 --- a/arch/arm/dts/am437x-idk-evm-u-boot.dtsi +++ b/arch/arm/dts/am437x-idk-evm-u-boot.dtsi @@ -9,6 +9,12 @@ ocp { u-boot,dm-spl; }; + + xtal25mhz: xtal25mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; }; &uart0 { @@ -17,6 +23,14 @@ &i2c0 { u-boot,dm-spl; + + cdce913: cdce913@65 { + compatible = "ti,cdce913"; + reg = <0x65>; + clocks = <&xtal25mhz>; + #clock-cells = <1>; + xtal-load-pf = <0>; + }; }; &mmc1 { diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index 2e09cc20e8..f5ecf871bc 100644 --- a/board/ti/am43xx/board.c +++ b/board/ti/am43xx/board.c @@ -720,6 +720,7 @@ static int device_okay(const char *path) int board_late_init(void) { + struct udevice *dev; #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG set_board_info_env(NULL); @@ -737,6 +738,10 @@ int board_late_init(void) if (device_okay("/ocp/omap_dwc3@483c0000")) enable_usb_clocks(1); #endif + + /* Just probe the potentially supported cdce913 device */ + uclass_get_device(UCLASS_CLK, 0, &dev); + return 0; } #endif diff --git a/configs/am43xx_evm_defconfig b/configs/am43xx_evm_defconfig index 7c74047f3a..7367c6952b 100644 --- a/configs/am43xx_evm_defconfig +++ b/configs/am43xx_evm_defconfig @@ -78,3 +78,5 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0403 CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00 CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_ETHER=y +CONFIG_CLK=y +CONFIG_CLK_CDCE9XX=y From 752a45a153c778bb8b2cdcd0933180b311858b86 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 27 Sep 2019 19:14:29 +0300 Subject: [PATCH 53/58] board: ti: am335x-ice: Configure the CDCE913 clock synthesizer AM335x-ICE boards contain the CDCE913 clock synthesizer, and their reset crystal capacitance load value of 10pF is wrong leading into lost packets in certain networking tests. Add DT data for this device, and probe it from the board file to program the crystal capacitance load value to 0pF to avoid any problems. Signed-off-by: Tero Kristo --- arch/arm/dts/am335x-icev2-u-boot.dtsi | 21 +++++++++++++++++++++ board/ti/am335x/board.c | 4 ++++ configs/am335x_evm_defconfig | 2 ++ 3 files changed, 27 insertions(+) create mode 100644 arch/arm/dts/am335x-icev2-u-boot.dtsi diff --git a/arch/arm/dts/am335x-icev2-u-boot.dtsi b/arch/arm/dts/am335x-icev2-u-boot.dtsi new file mode 100644 index 0000000000..cc9569af03 --- /dev/null +++ b/arch/arm/dts/am335x-icev2-u-boot.dtsi @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ +/ { + xtal25mhz: xtal25mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; +}; + +&i2c0 { + cdce913: cdce913@65 { + compatible = "ti,cdce913"; + reg = <0x65>; + clocks = <&xtal25mhz>; + #clock-cells = <1>; + xtal-load-pf = <0>; + }; +}; diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index 7eaa6cd96d..499c872227 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -791,6 +791,7 @@ int board_init(void) #ifdef CONFIG_BOARD_LATE_INIT int board_late_init(void) { + struct udevice *dev; #if !defined(CONFIG_SPL_BUILD) uint8_t mac_addr[6]; uint32_t mac_hi, mac_lo; @@ -871,6 +872,9 @@ int board_late_init(void) env_set("serial#", board_serial); } + /* Just probe the potentially supported cdce913 device */ + uclass_get_device(UCLASS_CLK, 0, &dev); + return 0; } #endif diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig index 2aa9b65caf..93a28b290b 100644 --- a/configs/am335x_evm_defconfig +++ b/configs/am335x_evm_defconfig @@ -77,3 +77,5 @@ CONFIG_DYNAMIC_CRC_TABLE=y CONFIG_RSA=y CONFIG_LZO=y # CONFIG_OF_LIBFDT_OVERLAY is not set +CONFIG_CLK=y +CONFIG_CLK_CDCE9XX=y From fbbcb1e0207f3cde5561f438920151886b4358b4 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Sun, 29 Sep 2019 17:37:58 +0530 Subject: [PATCH 54/58] arm: dts: k3-j721e-common-proc-board: Mark main_uart0 as shared device Main uart0 is used as debug console by both R5SPL and A72 bootloader and Linux. So mark it as shared device so that power-domain request is successful by both cores. Signed-off-by: Lokesh Vutla --- arch/arm/dts/k3-j721e-common-proc-board.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/dts/k3-j721e-common-proc-board.dts b/arch/arm/dts/k3-j721e-common-proc-board.dts index b21f597a80..c978cabd13 100644 --- a/arch/arm/dts/k3-j721e-common-proc-board.dts +++ b/arch/arm/dts/k3-j721e-common-proc-board.dts @@ -31,6 +31,10 @@ status = "disabled"; }; +&main_uart0 { + power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>; +}; + &main_uart3 { /* UART not brought out */ status = "disabled"; From 6685d2e26e971e6ffb0d4d2a323b66c5eb3758a9 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Mon, 30 Sep 2019 18:24:06 +0530 Subject: [PATCH 55/58] configs: am43xx_evm: Enable USB support spl_dm_init is failing as usb to be probed with the following error: "omap_dwc3@483c0000: ret=-2" Enable usb to make spl boot on am43xx devices Reported-by: Tero Kristo Signed-off-by: Lokesh Vutla --- configs/am43xx_evm_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/am43xx_evm_defconfig b/configs/am43xx_evm_defconfig index 7367c6952b..5e3e01c915 100644 --- a/configs/am43xx_evm_defconfig +++ b/configs/am43xx_evm_defconfig @@ -18,6 +18,7 @@ CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_NET_SUPPORT=y CONFIG_SPL_NET_VCI_STRING="AM43xx U-Boot SPL" CONFIG_SPL_OS_BOOT=y +CONFIG_SPL_USB_HOST_SUPPORT=y CONFIG_SPL_USB_GADGET=y CONFIG_SPL_USB_ETHER=y CONFIG_CMD_SPL=y From 2fff0e96a6ed4bb464f3ef7c2e3628ddf2d988d0 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 30 Sep 2019 20:42:21 +0300 Subject: [PATCH 56/58] tao3530: Fix usage of mmc rescan Currently "bootcmd" does not work as intended but instead prints MMC usage information and goes directly to "nandboot". Follow what the commit 669681104daa ("configs: Fix usage of mmc rescan") does for other boards prior to support for TechNexion TAO3530 SoM was added. Signed-off-by: Jarkko Nikula --- include/configs/tao3530.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/configs/tao3530.h b/include/configs/tao3530.h index c34e785d9e..7a54fe3e1e 100644 --- a/include/configs/tao3530.h +++ b/include/configs/tao3530.h @@ -114,7 +114,7 @@ "bootm ${loadaddr}\0" \ #define CONFIG_BOOTCOMMAND \ - "if mmc rescan ${mmcdev}; then " \ + "mmc dev ${mmcdev}; if mmc rescan; then " \ "if run loadbootscript; then " \ "run bootscript; " \ "else " \ From 60e3d43a26d0334dd09521220e0312d50679b1c7 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Tue, 1 Oct 2019 10:41:00 +0530 Subject: [PATCH 57/58] arm: dra7xx: Fix error path in iodelay recalibration When an error is reported in __recalibrate_iodelay_start(), de-isolation of IO doesn't happen. Because of this, undefined behaviour is observed on many peripherals without any error. So make sure io is out of isolation at the end of iodelay recalibration. Reported-by: Richard Woodruff Signed-off-by: Lokesh Vutla --- arch/arm/mach-omap2/omap5/dra7xx_iodelay.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c b/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c index e2abb7d058..9bd7051786 100644 --- a/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c +++ b/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c @@ -202,8 +202,9 @@ void __recalibrate_iodelay_end(int ret) return; } - if (!ret) - ret = isolate_io(DEISOLATE_IO); + /* Deisolate IO if it is already isolated */ + if (readl((*ctrl)->ctrl_core_sma_sw_0) & CTRL_ISOLATE_MASK) + isolate_io(DEISOLATE_IO); /* lock IODELAY CONFIG registers */ writel(CFG_IODELAY_LOCK_KEY, (*ctrl)->iodelay_config_base + From 5c6e497eaaf2c76344f82e823c2a0aad3cc26167 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Tue, 1 Oct 2019 10:41:01 +0530 Subject: [PATCH 58/58] arm: dra7xx: Hang on any failure during IOdelay recalibration If there is any failure during IOdelay recalibration sequence, IOs are not guaranteed to behave as expected. So hang on any failure during the sequence. Signed-off-by: Lokesh Vutla --- arch/arm/mach-omap2/omap5/dra7xx_iodelay.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c b/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c index 9bd7051786..9eda57c450 100644 --- a/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c +++ b/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c @@ -241,6 +241,12 @@ void __recalibrate_iodelay_end(int ret) debug("IODELAY: IO delay recalibration successfully completed\n"); } + /* If there is an error during iodelay recalibration, SoC is in a bad + * state. Do not progress any further. + */ + if (ret) + hang(); + return; }