diff mbox series

[04/10] imx: imx8qm/imx8qxp: Power down the resources before SPL jump to u-boot

Message ID 20200505122846.15992-5-peng.fan@nxp.com
State Accepted
Commit 231401de2eab8b8e503eb21afb6579ec24f872c6
Headers show
Series imx: imx8qm/qxp update | expand

Commit Message

Peng Fan May 5, 2020, 12:28 p.m. UTC
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
"imx8_power_off_pd_devices" to power off all active devices.

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 arch/arm/include/asm/arch-imx8/sys_proto.h      |  1 +
 board/freescale/imx8qm_mek/spl.c                |  6 +++++
 board/freescale/imx8qxp_mek/spl.c               |  6 +++++
 drivers/power/domain/imx8-power-domain-legacy.c | 35 +++++++++++++++++++++++++
 4 files changed, 48 insertions(+)

Comments

Stefano Babic May 11, 2020, 10:16 a.m. UTC | #1
> 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
> "imx8_power_off_pd_devices" to power off all active devices.
> Signed-off-by: Peng Fan <peng.fan at nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic
diff mbox series

Patch

diff --git a/arch/arm/include/asm/arch-imx8/sys_proto.h b/arch/arm/include/asm/arch-imx8/sys_proto.h
index fc33e6ed18..2a08ef939d 100644
--- a/arch/arm/include/asm/arch-imx8/sys_proto.h
+++ b/arch/arm/include/asm/arch-imx8/sys_proto.h
@@ -28,3 +28,4 @@  int print_bootinfo(void);
 int sc_pm_setup_uart(sc_rsrc_t uart_rsrc, sc_pm_clock_rate_t clk_rate);
 int imx8_power_domain_lookup_name(const char *name,
 				  struct power_domain *power_domain);
+void imx8_power_off_pd_devices(const char *permanent_on_devices[], int size);
diff --git a/board/freescale/imx8qm_mek/spl.c b/board/freescale/imx8qm_mek/spl.c
index cb4006eb2a..ba99002cf2 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;
 
@@ -37,6 +38,11 @@  void spl_board_init(void)
 	puts("Normal Boot\n");
 }
 
+void spl_board_prepare_for_boot(void)
+{
+	imx8_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 e4e4cbe716..32b61095b0 100644
--- a/board/freescale/imx8qxp_mek/spl.c
+++ b/board/freescale/imx8qxp_mek/spl.c
@@ -17,6 +17,7 @@ 
 #include <asm/arch/sci/sci.h>
 #include <asm/arch/imx8-pins.h>
 #include <asm/arch/iomux.h>
+#include <asm/arch/sys_proto.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -55,6 +56,11 @@  void spl_board_init(void)
 	puts("Normal Boot\n");
 }
 
+void spl_board_prepare_for_boot(void)
+{
+	imx_power_off_pd_devices(NULL, 0);
+}
+
 #ifdef CONFIG_SPL_LOAD_FIT
 int board_fit_config_name_match(const char *name)
 {
diff --git a/drivers/power/domain/imx8-power-domain-legacy.c b/drivers/power/domain/imx8-power-domain-legacy.c
index f679df9e5d..7ba4056e2d 100644
--- a/drivers/power/domain/imx8-power-domain-legacy.c
+++ b/drivers/power/domain/imx8-power-domain-legacy.c
@@ -11,6 +11,7 @@ 
 #include <asm/arch/power-domain.h>
 #include <dm/device-internal.h>
 #include <dm/device.h>
+#include <dm/uclass-internal.h>
 #include <asm/arch/sci/sci.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -19,6 +20,40 @@  struct imx8_power_domain_priv {
 	bool state_on;
 };
 
+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 imx8_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))
+			continue;
+		/*
+		 * 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);
+		}
+	}
+}
+
 int imx8_power_domain_lookup_name(const char *name,
 				  struct power_domain *power_domain)
 {