
Make sure that all devices that are powered up by SPL are powered down before entering into the u-boot. Otherwise the subsystem/device will never be powered down by SCFW, due to SPL and u-boot are in different partitions.
Benefiting from power domain driver, this patch implements the function "power_off_pd_devices" to power off all active devices.
Signed-off-by: Ye Li ye.li@nxp.com --- Changes in v2: - New patch in v2 to fix clock set parent failure in u-boot, due to SPL does not power off the resource.
arch/arm/include/asm/arch-imx8/sys_proto.h | 1 + arch/arm/mach-imx/imx8/cpu.c | 34 ++++++++++++++++++++++++++++++ board/freescale/imx8qm_mek/spl.c | 6 ++++++ board/freescale/imx8qxp_mek/spl.c | 6 ++++++ 4 files changed, 47 insertions(+)
diff --git a/arch/arm/include/asm/arch-imx8/sys_proto.h b/arch/arm/include/asm/arch-imx8/sys_proto.h index 73ffaba..fd00e8f 100644 --- a/arch/arm/include/asm/arch-imx8/sys_proto.h +++ b/arch/arm/include/asm/arch-imx8/sys_proto.h @@ -17,3 +17,4 @@ struct pass_over_info_t {
enum boot_device get_boot_device(void); int print_bootinfo(void); +void power_off_pd_devices(const char* permanent_on_devices[], int size); diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c index f2fa262..f03729b 100644 --- a/arch/arm/mach-imx/imx8/cpu.c +++ b/arch/arm/mach-imx/imx8/cpu.c @@ -11,6 +11,9 @@ #include <dm/lists.h> #include <dm/uclass.h> #include <errno.h> +#include <power-domain.h> +#include <dm/device.h> +#include <dm/uclass-internal.h> #include <thermal.h> #include <asm/arch/sci/sci.h> #include <asm/arch/sys_proto.h> @@ -696,3 +699,34 @@ U_BOOT_DRIVER(cpu_imx8_drv) = { .flags = DM_FLAG_PRE_RELOC, }; #endif + +static bool check_device_power_off(struct udevice *dev, + const char* permanent_on_devices[], int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (!strcmp(dev->name, permanent_on_devices[i])) + return false; + } + + return true; +} + +void power_off_pd_devices(const char* permanent_on_devices[], int size) +{ + struct udevice *dev; + struct power_domain pd; + + for (uclass_find_first_device(UCLASS_POWER_DOMAIN, &dev); dev; + uclass_find_next_device(&dev)) { + + if (device_active(dev)) { + /* Power off active pd devices except the permanent power on devices */ + if (check_device_power_off(dev, permanent_on_devices, size)) { + pd.dev = dev; + power_domain_off(&pd); + } + } + } +} diff --git a/board/freescale/imx8qm_mek/spl.c b/board/freescale/imx8qm_mek/spl.c index 95ce9f3..a3f2faa 100644 --- a/board/freescale/imx8qm_mek/spl.c +++ b/board/freescale/imx8qm_mek/spl.c @@ -12,6 +12,7 @@ #include <dm/uclass-internal.h> #include <dm/device-internal.h> #include <dm/lists.h> +#include <asm/arch/sys_proto.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -53,6 +54,11 @@ void spl_board_init(void) puts("Normal Boot\n"); }
+void spl_board_prepare_for_boot(void) +{ + power_off_pd_devices(NULL, 0); +} + #ifdef CONFIG_SPL_LOAD_FIT int board_fit_config_name_match(const char *name) { diff --git a/board/freescale/imx8qxp_mek/spl.c b/board/freescale/imx8qxp_mek/spl.c index cb4006e..f947838 100644 --- a/board/freescale/imx8qxp_mek/spl.c +++ b/board/freescale/imx8qxp_mek/spl.c @@ -12,6 +12,7 @@ #include <dm/uclass-internal.h> #include <dm/device-internal.h> #include <dm/lists.h> +#include <asm/arch/sys_proto.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -37,6 +38,11 @@ void spl_board_init(void) puts("Normal Boot\n"); }
+void spl_board_prepare_for_boot(void) +{ + power_off_pd_devices(NULL, 0); +} + #ifdef CONFIG_SPL_LOAD_FIT int board_fit_config_name_match(const char *name) {