ls2080: Exit dpaa only right before exiting U-Boot

On ls2080 we have a separate network fabric component which we need to
shut down before we enter Linux (or any other OS). Along with that also
comes configuration of the fabric using a description file.

Today we always stop and configure the fabric in the boot script and
(again) exit it on device tree generation. This works ok for the normal
booti case, but with bootefi the payload we're running may still want to
access the network.

So let's add a new fsl_mc command that defers configuration and stopping
the hardware to when we actually exit U-Boot, so that we can still use
the fabric from an EFI payload.

For existing boot scripts, nothing should change with this patch.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: York Sun <york.sun@nxp.com>
[agraf: Fix x86 build]
diff --git a/arch/arm/include/asm/u-boot-arm.h b/arch/arm/include/asm/u-boot-arm.h
index 414042d..305a302 100644
--- a/arch/arm/include/asm/u-boot-arm.h
+++ b/arch/arm/include/asm/u-boot-arm.h
@@ -37,6 +37,7 @@
 /* board/.../... */
 int	board_init(void);
 void	dram_init_banksize (void);
+void	board_quiesce_devices(void);
 
 /* cpu/.../interrupt.c */
 int	arch_interrupt_init	(void);
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 53c3141..dedcd1e 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -64,6 +64,10 @@
 		    gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp);
 }
 
+__weak void board_quiesce_devices(void)
+{
+}
+
 /**
  * announce_and_cleanup() - Print message and prepare for kernel boot
  *
@@ -84,6 +88,9 @@
 #ifdef CONFIG_USB_DEVICE
 	udc_disconnect();
 #endif
+
+	board_quiesce_devices();
+
 	cleanup_before_linux();
 }
 
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 031740b..4f901f9 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -74,6 +74,7 @@
 /* board/... */
 void timer_set_tsc_base(uint64_t new_base);
 uint64_t timer_get_tsc(void);
+void board_quiesce_devices(void);
 
 void quick_ram_check(void);
 
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
index 7cf9de4..80fadef 100644
--- a/arch/x86/lib/bootm.c
+++ b/arch/x86/lib/bootm.c
@@ -26,6 +26,10 @@
 
 #define COMMAND_LINE_OFFSET 0x9000
 
+__weak void board_quiesce_devices(void)
+{
+}
+
 void bootm_announce_and_cleanup(void)
 {
 	printf("\nStarting kernel ...\n\n");
diff --git a/board/freescale/ls2080a/ls2080a.c b/board/freescale/ls2080a/ls2080a.c
index d0a88d4..4f9b9c8 100644
--- a/board/freescale/ls2080a/ls2080a.c
+++ b/board/freescale/ls2080a/ls2080a.c
@@ -102,6 +102,11 @@
 	else
 		fdt_status_fail(fdt, offset);
 }
+
+void board_quiesce_devices(void)
+{
+	fsl_mc_ldpaa_exit(gd->bd);
+}
 #endif
 
 #ifdef CONFIG_OF_BOARD_SETUP
@@ -122,7 +127,6 @@
 
 #ifdef CONFIG_FSL_MC_ENET
 	fdt_fixup_board_enet(blob);
-	fsl_mc_ldpaa_exit(bd);
 #endif
 
 	return 0;
diff --git a/board/freescale/ls2080aqds/ls2080aqds.c b/board/freescale/ls2080aqds/ls2080aqds.c
index d07ca18..73a61fd 100644
--- a/board/freescale/ls2080aqds/ls2080aqds.c
+++ b/board/freescale/ls2080aqds/ls2080aqds.c
@@ -292,14 +292,16 @@
 	else
 		fdt_status_fail(fdt, offset);
 }
+
+void board_quiesce_devices(void)
+{
+	fsl_mc_ldpaa_exit(gd->bd);
+}
 #endif
 
 #ifdef CONFIG_OF_BOARD_SETUP
 int ft_board_setup(void *blob, bd_t *bd)
 {
-#ifdef CONFIG_FSL_MC_ENET
-	int err;
-#endif
 	u64 base[CONFIG_NR_DRAM_BANKS];
 	u64 size[CONFIG_NR_DRAM_BANKS];
 
@@ -317,9 +319,6 @@
 
 #ifdef CONFIG_FSL_MC_ENET
 	fdt_fixup_board_enet(blob);
-	err = fsl_mc_ldpaa_exit(bd);
-	if (err)
-		return err;
 #endif
 
 	return 0;
diff --git a/board/freescale/ls2080ardb/ls2080ardb.c b/board/freescale/ls2080ardb/ls2080ardb.c
index 83d9e7e..fab44b9 100644
--- a/board/freescale/ls2080ardb/ls2080ardb.c
+++ b/board/freescale/ls2080ardb/ls2080ardb.c
@@ -256,14 +256,16 @@
 	else
 		fdt_status_fail(fdt, offset);
 }
+
+void board_quiesce_devices(void)
+{
+	fsl_mc_ldpaa_exit(gd->bd);
+}
 #endif
 
 #ifdef CONFIG_OF_BOARD_SETUP
 int ft_board_setup(void *blob, bd_t *bd)
 {
-#ifdef CONFIG_FSL_MC_ENET
-	int err;
-#endif
 	u64 base[CONFIG_NR_DRAM_BANKS];
 	u64 size[CONFIG_NR_DRAM_BANKS];
 
@@ -281,9 +283,6 @@
 
 #ifdef CONFIG_FSL_MC_ENET
 	fdt_fixup_board_enet(blob);
-	err = fsl_mc_ldpaa_exit(bd);
-	if (err)
-		return err;
 #endif
 
 	return 0;
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c
index 1811b0f..46b8a6b 100644
--- a/drivers/net/fsl-mc/mc.c
+++ b/drivers/net/fsl-mc/mc.c
@@ -40,6 +40,7 @@
 struct fsl_dpbp_obj *dflt_dpbp = NULL;
 struct fsl_dpio_obj *dflt_dpio = NULL;
 struct fsl_dpni_obj *dflt_dpni = NULL;
+static u64 mc_lazy_dpl_addr;
 
 #ifdef DEBUG
 void dump_ram_words(const char *title, void *addr)
@@ -572,6 +573,9 @@
 	u64 mc_ram_addr = mc_get_dram_addr();
 	size_t mc_ram_size = mc_get_dram_block_size();
 
+	if (!mc_dpl_addr)
+		return -1;
+
 	error = load_mc_dpl(mc_ram_addr, mc_ram_size, mc_dpl_addr);
 	if (error != 0)
 		return error;
@@ -1156,6 +1160,11 @@
 {
 	int err = 0;
 
+	if (bd && mc_lazy_dpl_addr && !fsl_mc_ldpaa_exit(NULL)) {
+		mc_apply_dpl(mc_lazy_dpl_addr);
+		mc_lazy_dpl_addr = 0;
+	}
+
 	/* MC is not loaded intentionally, So return success. */
 	if (bd && get_mc_boot_status() != 0)
 		return 0;
@@ -1259,6 +1268,7 @@
 		}
 		break;
 
+	case 'l':
 	case 'a': {
 			u64 mc_dpl_addr;
 
@@ -1279,8 +1289,17 @@
 				return -ENODEV;
 			}
 
-			if (!fsl_mc_ldpaa_exit(NULL))
-				err = mc_apply_dpl(mc_dpl_addr);
+			if (argv[1][0] == 'l') {
+				/*
+				 * We will do the actual dpaa exit and dpl apply
+				 * later from announce_and_cleanup().
+				 */
+				mc_lazy_dpl_addr = mc_dpl_addr;
+			} else {
+				/* The user wants it applied now */
+				if (!fsl_mc_ldpaa_exit(NULL))
+					err = mc_apply_dpl(mc_dpl_addr);
+			}
 			break;
 		}
 	default:
@@ -1298,5 +1317,6 @@
 	"DPAA2 command to manage Management Complex (MC)",
 	"start mc [FW_addr] [DPC_addr] - Start Management Complex\n"
 	"fsl_mc apply DPL [DPL_addr] - Apply DPL file\n"
+	"fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n"
 	"fsl_mc start aiop [FW_addr] - Start AIOP\n"
 );
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 1fdddf4..51080cb 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -538,6 +538,8 @@
 {
 	EFI_ENTRY("%p, %ld", image_handle, map_key);
 
+	board_quiesce_devices();
+
 	/* Fix up caches for EFI payloads if necessary */
 	efi_exit_caches();