Re: [PATCH 4/4] powerpc: pm: support deep sleep feature on T104x

2015-07-31 Thread Scott Wood
On Fri, 2015-07-31 at 20:53 +0800, Chenhui Zhao wrote:
> diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S 
> b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
> index f22e7e4..32ec426f 100644
> --- a/arch/powerpc/kernel/fsl_booke_entry_mapping.S
> +++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
> @@ -170,6 +170,10 @@ skpinv:  addir6,r6,1 /* 
> Increment */
>   lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
>   ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
>   mtspr   SPRN_MAS2,r6
> +#ifdef ENTRY_DEEPSLEEP_SETUP
> + LOAD_REG_IMMEDIATE(r8, MEMORY_START)
> + ori r8,r8,(MAS3_SX|MAS3_SW|MAS3_SR)
> +#endif
>   mtspr   SPRN_MAS3,r8
>   tlbwe
>  
> @@ -212,12 +216,18 @@ next_tlb_setup:
>   #error You need to specify the mapping or not use this at all.
>  #endif
>  
> +#ifdef ENTRY_DEEPSLEEP_SETUP
> + LOAD_REG_ADDR(r6, 2f)
> + mfmsr   r7
> + rlwinm  r7,r7,0,~(MSR_IS|MSR_DS)
> +#else
>   lis r7,MSR_KERNEL@h
>   ori r7,r7,MSR_KERNEL@l
>   bl  1f  /* Find our address */
>  1:   mflrr9
>   rlwimi  r6,r9,0,20,31
>   addir6,r6,(2f - 1b)
> +#endif

Could you explain what's going on here?  What does the TLB look like before 
and after?

> +int fsl_dp_iomap(void)

I don't think this needs to be global (see the comment where it gets called), 
but if it must be, this name is too terse.

> +{
> + struct device_node *np;
> + int ret = 0;
> + phys_addr_t ccsr_phy_addr, dcsr_phy_addr;
> +
> + saved_law = NULL;
> + ccsr_base = NULL;
> + dcsr_base = NULL;
> + pld_base = NULL;
> +
> + ccsr_phy_addr = get_immrbase();
> + if (ccsr_phy_addr == -1) {
> + pr_err("%s: Can't get the address of CCSR\n", __func__);
> + ret = -EINVAL;
> + goto ccsr_err;
> + }
> + ccsr_base = ioremap(ccsr_phy_addr, SIZE_2MB);
> + if (!ccsr_base) {
> + ret = -ENOMEM;
> + goto ccsr_err;
> + }
> +
> + dcsr_phy_addr = get_dcsrbase();
> + if (dcsr_phy_addr == -1) {
> + pr_err("%s: Can't get the address of DCSR\n", __func__);
> + ret = -EINVAL;
> + goto dcsr_err;
> + }
> + dcsr_base = ioremap(dcsr_phy_addr, SIZE_1MB);
> + if (!dcsr_base) {
> + ret = -ENOMEM;
> + goto dcsr_err;
> + }

Please just map the device tree nodes you need.

> +
> + np = of_find_compatible_node(NULL, NULL, "fsl,tetra-fpga");
> + if (np) {
> + pld_flag = T1040QDS_TETRA_FLAG;
> + } else {
> + np = of_find_compatible_node(NULL, NULL, "fsl,deepsleep-cpld");

I've already rejected fsl,deepsleep-cpld multiple times when others tried to 
add it to a device tree.

> +{
> + u32 ddr_buff_addr;
> +
> + /*
> +  * DDR training initialization will break 128 bytes at the beginning
> +  * of DDR, therefore, save them so that the bootloader will restore
> +  * them. Assume that DDR is mapped to the address space started with
> +  * CONFIG_PAGE_OFFSET.
> +  */
> + memcpy(ddr_buff, (void *)CONFIG_PAGE_OFFSET, DDR_BUF_SIZE);

That assumption may not be true in all relocatable scenarios.

It'd be a lot simpler to just mark that first page as reserved.

> + /* assume ddr_buff is in the physical address space of 4GB */
> + ddr_buff_addr = (u32)(__pa(ddr_buff) & 0x);
> +
> + /*
> +  * the bootloader will restore the first 128 bytes of DDR from
> +  * the location indicated by the register SPARECR3
> +  */
> + out_be32(ccsr_base + CCSR_SCFG_SPARECR3, ddr_buff_addr);

...yeah, please just mark it reserved.

> +}
> +
> +static void fsl_dp_mp_save(void *ccsr)
> +{
> +  struct fsl_bstr *dst = _bstr;
> +
> +  dst->bstrh = in_be32(ccsr + LCC_BSTRH);
> +  dst->bstrl = in_be32(ccsr + LCC_BSTRL);
> +  dst->bstar = in_be32(ccsr + LCC_BSTAR);
> +  dst->cpu_mask = in_be32(ccsr + DCFG_BASE + DCFG_BRR);
> +}

What is "mp"?

> +static void fsl_dp_law_save(void *ccsr)
> +{
> + int i;
> + struct fsl_law *dst = saved_law;
> + struct fsl_law *src = (void *)(ccsr + CCSR_LAW_BASE);
> +
> + for (i = 0; i < num_laws; i++) {
> + dst->lawbarh = in_be32(>lawbarh);
> + dst->lawbarl = in_be32(>lawbarl);
> + dst->lawar = in_be32(>lawar);
> + dst++;
> + src++;
> + }
> +}

Why wouldn't U-Boot restore these the same way on resume as they are now?

> +int fsl_enter_epu_deepsleep(void)
> +{
> + fsl_dp_ddr_save(ccsr_base);
> +
> + fsl_dp_set_resume_pointer(ccsr_base);
> +
> + fsl_dp_mp_save(ccsr_base);
> + fsl_dp_law_save(ccsr_base);
> + /*  enable Warm Device Reset request. */
> + setbits32(ccsr_base + CCSR_SCFG_DPSLPCR, CCSR_SCFG_DPSLPCR_WDRR_EN);
> +
> + /* set GPIO1_29 as an output pin (not open-drain), and output 0 */
> + 

[PATCH 4/4] powerpc: pm: support deep sleep feature on T104x

2015-07-31 Thread Chenhui Zhao
T104x has deep sleep feature, which can switch off most parts of
the SoC when it is in deep sleep mode. This way, it becomes more
energy-efficient.

The DDR controller will also be powered off in deep sleep. Therefore,
the last stage (the latter part of fsl_dp_enter_low) will run without DDR
access. This piece of code and related TLBs are prefetched in advance.

Due to the different initialization code between 32-bit and 64-bit, they
have separate resume entry and precedure.

The feature supports 32-bit and 64-bit kernel mode.

Signed-off-by: Chenhui Zhao 
---
 arch/powerpc/include/asm/fsl_pm.h |  14 +
 arch/powerpc/kernel/fsl_booke_entry_mapping.S |  10 +
 arch/powerpc/kernel/head_64.S |   2 +-
 arch/powerpc/platforms/85xx/Makefile  |   1 +
 arch/powerpc/platforms/85xx/deepsleep.c   | 322 +++
 arch/powerpc/platforms/85xx/qoriq_pm.c|  81 +++-
 arch/powerpc/platforms/85xx/t104x_deepsleep.S | 570 ++
 7 files changed, 997 insertions(+), 3 deletions(-)
 create mode 100644 arch/powerpc/platforms/85xx/deepsleep.c
 create mode 100644 arch/powerpc/platforms/85xx/t104x_deepsleep.S

diff --git a/arch/powerpc/include/asm/fsl_pm.h 
b/arch/powerpc/include/asm/fsl_pm.h
index 4b09f09..b44f484 100644
--- a/arch/powerpc/include/asm/fsl_pm.h
+++ b/arch/powerpc/include/asm/fsl_pm.h
@@ -12,6 +12,7 @@
 #define __PPC_FSL_PM_H
 #ifdef __KERNEL__
 
+#ifndef __ASSEMBLY__
 #define E500_PM_PH10   1
 #define E500_PM_PH15   2
 #define E500_PM_PH20   3
@@ -44,5 +45,18 @@ struct fsl_pm_ops {
 };
 
 extern const struct fsl_pm_ops *qoriq_pm_ops;
+
+extern int fsl_dp_iomap(void);
+extern void fsl_dp_iounmap(void);
+
+extern int fsl_enter_epu_deepsleep(void);
+extern void fsl_dp_enter_low(void __iomem *ccsr_base, void __iomem *dcsr_base,
+void __iomem *pld_base, int pld_flag);
+extern void fsl_booke_deep_sleep_resume(void);
+#endif /* __ASSEMBLY__ */
+
+#define T1040QDS_TETRA_FLAG1
+#define T104xRDB_CPLD_FLAG 2
+
 #endif /* __KERNEL__ */
 #endif /* __PPC_FSL_PM_H */
diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S 
b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
index f22e7e4..32ec426f 100644
--- a/arch/powerpc/kernel/fsl_booke_entry_mapping.S
+++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
@@ -170,6 +170,10 @@ skpinv:addir6,r6,1 /* 
Increment */
lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
mtspr   SPRN_MAS2,r6
+#ifdef ENTRY_DEEPSLEEP_SETUP
+   LOAD_REG_IMMEDIATE(r8, MEMORY_START)
+   ori r8,r8,(MAS3_SX|MAS3_SW|MAS3_SR)
+#endif
mtspr   SPRN_MAS3,r8
tlbwe
 
@@ -212,12 +216,18 @@ next_tlb_setup:
#error You need to specify the mapping or not use this at all.
 #endif
 
+#ifdef ENTRY_DEEPSLEEP_SETUP
+   LOAD_REG_ADDR(r6, 2f)
+   mfmsr   r7
+   rlwinm  r7,r7,0,~(MSR_IS|MSR_DS)
+#else
lis r7,MSR_KERNEL@h
ori r7,r7,MSR_KERNEL@l
bl  1f  /* Find our address */
 1: mflrr9
rlwimi  r6,r9,0,20,31
addir6,r6,(2f - 1b)
+#endif
mtspr   SPRN_SRR0,r6
mtspr   SPRN_SRR1,r7
rfi /* start execution out of TLB1[0] entry 
*/
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index d48125d..b9eb02a 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -696,7 +696,7 @@ _GLOBAL(start_secondary_resume)
 /*
  * This subroutine clobbers r11 and r12
  */
-enable_64b_mode:
+_GLOBAL(enable_64b_mode)
mfmsr   r11 /* grab the current MSR */
 #ifdef CONFIG_PPC_BOOK3E
orisr11,r11,0x8000  /* CM bit set, we'll set ICM later */
diff --git a/arch/powerpc/platforms/85xx/Makefile 
b/arch/powerpc/platforms/85xx/Makefile
index 87fb847..a73d563 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -4,6 +4,7 @@
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_FSL_PMC)+= mpc85xx_pm_ops.o
 obj-$(CONFIG_FSL_QORIQ_PM)   += qoriq_pm.o sleep_fsm.o
+obj-$(CONFIG_FSL_QORIQ_PM)   += deepsleep.o t104x_deepsleep.o
 
 obj-y += common.o
 
diff --git a/arch/powerpc/platforms/85xx/deepsleep.c 
b/arch/powerpc/platforms/85xx/deepsleep.c
new file mode 100644
index 000..5de904d
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/deepsleep.c
@@ -0,0 +1,322 @@
+/*
+ * Support deep sleep feature for T104x
+ *
+ * Copyright 2015 Freescale Semiconductor Inc.
+ *
+ * Author: Chenhui Zhao 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 

[PATCH 4/4] powerpc: pm: support deep sleep feature on T104x

2015-07-31 Thread Chenhui Zhao
T104x has deep sleep feature, which can switch off most parts of
the SoC when it is in deep sleep mode. This way, it becomes more
energy-efficient.

The DDR controller will also be powered off in deep sleep. Therefore,
the last stage (the latter part of fsl_dp_enter_low) will run without DDR
access. This piece of code and related TLBs are prefetched in advance.

Due to the different initialization code between 32-bit and 64-bit, they
have separate resume entry and precedure.

The feature supports 32-bit and 64-bit kernel mode.

Signed-off-by: Chenhui Zhao chenhui.z...@freescale.com
---
 arch/powerpc/include/asm/fsl_pm.h |  14 +
 arch/powerpc/kernel/fsl_booke_entry_mapping.S |  10 +
 arch/powerpc/kernel/head_64.S |   2 +-
 arch/powerpc/platforms/85xx/Makefile  |   1 +
 arch/powerpc/platforms/85xx/deepsleep.c   | 322 +++
 arch/powerpc/platforms/85xx/qoriq_pm.c|  81 +++-
 arch/powerpc/platforms/85xx/t104x_deepsleep.S | 570 ++
 7 files changed, 997 insertions(+), 3 deletions(-)
 create mode 100644 arch/powerpc/platforms/85xx/deepsleep.c
 create mode 100644 arch/powerpc/platforms/85xx/t104x_deepsleep.S

diff --git a/arch/powerpc/include/asm/fsl_pm.h 
b/arch/powerpc/include/asm/fsl_pm.h
index 4b09f09..b44f484 100644
--- a/arch/powerpc/include/asm/fsl_pm.h
+++ b/arch/powerpc/include/asm/fsl_pm.h
@@ -12,6 +12,7 @@
 #define __PPC_FSL_PM_H
 #ifdef __KERNEL__
 
+#ifndef __ASSEMBLY__
 #define E500_PM_PH10   1
 #define E500_PM_PH15   2
 #define E500_PM_PH20   3
@@ -44,5 +45,18 @@ struct fsl_pm_ops {
 };
 
 extern const struct fsl_pm_ops *qoriq_pm_ops;
+
+extern int fsl_dp_iomap(void);
+extern void fsl_dp_iounmap(void);
+
+extern int fsl_enter_epu_deepsleep(void);
+extern void fsl_dp_enter_low(void __iomem *ccsr_base, void __iomem *dcsr_base,
+void __iomem *pld_base, int pld_flag);
+extern void fsl_booke_deep_sleep_resume(void);
+#endif /* __ASSEMBLY__ */
+
+#define T1040QDS_TETRA_FLAG1
+#define T104xRDB_CPLD_FLAG 2
+
 #endif /* __KERNEL__ */
 #endif /* __PPC_FSL_PM_H */
diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S 
b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
index f22e7e4..32ec426f 100644
--- a/arch/powerpc/kernel/fsl_booke_entry_mapping.S
+++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
@@ -170,6 +170,10 @@ skpinv:addir6,r6,1 /* 
Increment */
lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
mtspr   SPRN_MAS2,r6
+#ifdef ENTRY_DEEPSLEEP_SETUP
+   LOAD_REG_IMMEDIATE(r8, MEMORY_START)
+   ori r8,r8,(MAS3_SX|MAS3_SW|MAS3_SR)
+#endif
mtspr   SPRN_MAS3,r8
tlbwe
 
@@ -212,12 +216,18 @@ next_tlb_setup:
#error You need to specify the mapping or not use this at all.
 #endif
 
+#ifdef ENTRY_DEEPSLEEP_SETUP
+   LOAD_REG_ADDR(r6, 2f)
+   mfmsr   r7
+   rlwinm  r7,r7,0,~(MSR_IS|MSR_DS)
+#else
lis r7,MSR_KERNEL@h
ori r7,r7,MSR_KERNEL@l
bl  1f  /* Find our address */
 1: mflrr9
rlwimi  r6,r9,0,20,31
addir6,r6,(2f - 1b)
+#endif
mtspr   SPRN_SRR0,r6
mtspr   SPRN_SRR1,r7
rfi /* start execution out of TLB1[0] entry 
*/
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index d48125d..b9eb02a 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -696,7 +696,7 @@ _GLOBAL(start_secondary_resume)
 /*
  * This subroutine clobbers r11 and r12
  */
-enable_64b_mode:
+_GLOBAL(enable_64b_mode)
mfmsr   r11 /* grab the current MSR */
 #ifdef CONFIG_PPC_BOOK3E
orisr11,r11,0x8000  /* CM bit set, we'll set ICM later */
diff --git a/arch/powerpc/platforms/85xx/Makefile 
b/arch/powerpc/platforms/85xx/Makefile
index 87fb847..a73d563 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -4,6 +4,7 @@
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_FSL_PMC)+= mpc85xx_pm_ops.o
 obj-$(CONFIG_FSL_QORIQ_PM)   += qoriq_pm.o sleep_fsm.o
+obj-$(CONFIG_FSL_QORIQ_PM)   += deepsleep.o t104x_deepsleep.o
 
 obj-y += common.o
 
diff --git a/arch/powerpc/platforms/85xx/deepsleep.c 
b/arch/powerpc/platforms/85xx/deepsleep.c
new file mode 100644
index 000..5de904d
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/deepsleep.c
@@ -0,0 +1,322 @@
+/*
+ * Support deep sleep feature for T104x
+ *
+ * Copyright 2015 Freescale Semiconductor Inc.
+ *
+ * Author: Chenhui Zhao chenhui.z...@freescale.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+

Re: [PATCH 4/4] powerpc: pm: support deep sleep feature on T104x

2015-07-31 Thread Scott Wood
On Fri, 2015-07-31 at 20:53 +0800, Chenhui Zhao wrote:
 diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S 
 b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
 index f22e7e4..32ec426f 100644
 --- a/arch/powerpc/kernel/fsl_booke_entry_mapping.S
 +++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
 @@ -170,6 +170,10 @@ skpinv:  addir6,r6,1 /* 
 Increment */
   lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
   ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
   mtspr   SPRN_MAS2,r6
 +#ifdef ENTRY_DEEPSLEEP_SETUP
 + LOAD_REG_IMMEDIATE(r8, MEMORY_START)
 + ori r8,r8,(MAS3_SX|MAS3_SW|MAS3_SR)
 +#endif
   mtspr   SPRN_MAS3,r8
   tlbwe
  
 @@ -212,12 +216,18 @@ next_tlb_setup:
   #error You need to specify the mapping or not use this at all.
  #endif
  
 +#ifdef ENTRY_DEEPSLEEP_SETUP
 + LOAD_REG_ADDR(r6, 2f)
 + mfmsr   r7
 + rlwinm  r7,r7,0,~(MSR_IS|MSR_DS)
 +#else
   lis r7,MSR_KERNEL@h
   ori r7,r7,MSR_KERNEL@l
   bl  1f  /* Find our address */
  1:   mflrr9
   rlwimi  r6,r9,0,20,31
   addir6,r6,(2f - 1b)
 +#endif

Could you explain what's going on here?  What does the TLB look like before 
and after?

 +int fsl_dp_iomap(void)

I don't think this needs to be global (see the comment where it gets called), 
but if it must be, this name is too terse.

 +{
 + struct device_node *np;
 + int ret = 0;
 + phys_addr_t ccsr_phy_addr, dcsr_phy_addr;
 +
 + saved_law = NULL;
 + ccsr_base = NULL;
 + dcsr_base = NULL;
 + pld_base = NULL;
 +
 + ccsr_phy_addr = get_immrbase();
 + if (ccsr_phy_addr == -1) {
 + pr_err(%s: Can't get the address of CCSR\n, __func__);
 + ret = -EINVAL;
 + goto ccsr_err;
 + }
 + ccsr_base = ioremap(ccsr_phy_addr, SIZE_2MB);
 + if (!ccsr_base) {
 + ret = -ENOMEM;
 + goto ccsr_err;
 + }
 +
 + dcsr_phy_addr = get_dcsrbase();
 + if (dcsr_phy_addr == -1) {
 + pr_err(%s: Can't get the address of DCSR\n, __func__);
 + ret = -EINVAL;
 + goto dcsr_err;
 + }
 + dcsr_base = ioremap(dcsr_phy_addr, SIZE_1MB);
 + if (!dcsr_base) {
 + ret = -ENOMEM;
 + goto dcsr_err;
 + }

Please just map the device tree nodes you need.

 +
 + np = of_find_compatible_node(NULL, NULL, fsl,tetra-fpga);
 + if (np) {
 + pld_flag = T1040QDS_TETRA_FLAG;
 + } else {
 + np = of_find_compatible_node(NULL, NULL, fsl,deepsleep-cpld);

I've already rejected fsl,deepsleep-cpld multiple times when others tried to 
add it to a device tree.

 +{
 + u32 ddr_buff_addr;
 +
 + /*
 +  * DDR training initialization will break 128 bytes at the beginning
 +  * of DDR, therefore, save them so that the bootloader will restore
 +  * them. Assume that DDR is mapped to the address space started with
 +  * CONFIG_PAGE_OFFSET.
 +  */
 + memcpy(ddr_buff, (void *)CONFIG_PAGE_OFFSET, DDR_BUF_SIZE);

That assumption may not be true in all relocatable scenarios.

It'd be a lot simpler to just mark that first page as reserved.

 + /* assume ddr_buff is in the physical address space of 4GB */
 + ddr_buff_addr = (u32)(__pa(ddr_buff)  0x);
 +
 + /*
 +  * the bootloader will restore the first 128 bytes of DDR from
 +  * the location indicated by the register SPARECR3
 +  */
 + out_be32(ccsr_base + CCSR_SCFG_SPARECR3, ddr_buff_addr);

...yeah, please just mark it reserved.

 +}
 +
 +static void fsl_dp_mp_save(void *ccsr)
 +{
 +  struct fsl_bstr *dst = saved_bstr;
 +
 +  dst-bstrh = in_be32(ccsr + LCC_BSTRH);
 +  dst-bstrl = in_be32(ccsr + LCC_BSTRL);
 +  dst-bstar = in_be32(ccsr + LCC_BSTAR);
 +  dst-cpu_mask = in_be32(ccsr + DCFG_BASE + DCFG_BRR);
 +}

What is mp?

 +static void fsl_dp_law_save(void *ccsr)
 +{
 + int i;
 + struct fsl_law *dst = saved_law;
 + struct fsl_law *src = (void *)(ccsr + CCSR_LAW_BASE);
 +
 + for (i = 0; i  num_laws; i++) {
 + dst-lawbarh = in_be32(src-lawbarh);
 + dst-lawbarl = in_be32(src-lawbarl);
 + dst-lawar = in_be32(src-lawar);
 + dst++;
 + src++;
 + }
 +}

Why wouldn't U-Boot restore these the same way on resume as they are now?

 +int fsl_enter_epu_deepsleep(void)
 +{
 + fsl_dp_ddr_save(ccsr_base);
 +
 + fsl_dp_set_resume_pointer(ccsr_base);
 +
 + fsl_dp_mp_save(ccsr_base);
 + fsl_dp_law_save(ccsr_base);
 + /*  enable Warm Device Reset request. */
 + setbits32(ccsr_base + CCSR_SCFG_DPSLPCR, CCSR_SCFG_DPSLPCR_WDRR_EN);
 +
 + /* set GPIO1_29 as an output pin (not open-drain), and output 0 */
 + clrbits32(ccsr_base + CCSR_GPIO1_GPDAT, CCSR_GPIO1_GPDIR_29);
 + clrbits32(ccsr_base + CCSR_GPIO1_GPODR, CCSR_GPIO1_GPDIR_29);
 +