From: Gary McGee <gary.mc...@lsi.com>

Signed-off-by: Gary McGee <gary.mc...@lsi.com>
---
 arch/arm/mach-axxia/Makefile        |    2 +-
 arch/arm/mach-axxia/ddr_retention.c |   96 ++++------
 arch/arm/mach-axxia/ddr_shutdown.c  |  331 +++++++++++++++++++++++++++++++++++
 3 files changed, 365 insertions(+), 64 deletions(-)
 create mode 100644 arch/arm/mach-axxia/ddr_shutdown.c

diff --git a/arch/arm/mach-axxia/Makefile b/arch/arm/mach-axxia/Makefile
index 4d41b15..b4b8dd2 100644
--- a/arch/arm/mach-axxia/Makefile
+++ b/arch/arm/mach-axxia/Makefile
@@ -7,7 +7,7 @@ obj-y                                   += io.o
 obj-y                                  += ncr.o
 obj-y                                  += timers.o
 obj-y                                  += pci.o
-obj-y                                  += ddr_retention.o
+obj-y                                  += ddr_retention.o ddr_shutdown.o
 obj-$(CONFIG_I2C)                      += i2c.o
 obj-$(CONFIG_SMP)                      += platsmp.o headsmp.o
 obj-$(CONFIG_ARCH_AXXIA_GIC)           += axxia-gic.o
diff --git a/arch/arm/mach-axxia/ddr_retention.c 
b/arch/arm/mach-axxia/ddr_retention.c
index bcedf33..35dbfcb 100644
--- a/arch/arm/mach-axxia/ddr_retention.c
+++ b/arch/arm/mach-axxia/ddr_retention.c
@@ -36,7 +36,6 @@
 static void __iomem *nca;
 static void __iomem *apb;
 static void __iomem *dickens;
-static void __iomem *femac;
 static int ddr_retention_enabled;
 
 enum {
@@ -229,60 +228,33 @@ static inline void cpu_disable_l2_prefetch(void)
 }
 
 static inline void
-ncp_ddr_shutdown(unsigned long ctl_244)
+reset_elm_trace(void)
 {
-       unsigned long value;
-
-       cpu_disable_l2_prefetch();
-
-       /*
-        * put SDRAM in self-refresh mode
-        */
-       ncr_write(NCP_REGION_ID(34, 0), 0x3d0, 4, &ctl_244);
-       ncr_write(NCP_REGION_ID(15, 0), 0x3d0, 4, &ctl_244);
-
-       /* check interrupt status for completion */
-       /* CDR1 - word offset 0x104 (byte offset 0x410) */
-       do {
-               ncr_read(NCP_REGION_ID(34, 0), 0x410, 4, &value);
-       } while ((value & 0x0200) == 0);
+       /* reset and disable ELM trace */
+       ncr_register_write(htonl(0x000fff04), (unsigned *) (apb + 0x68000));
+       ncr_register_write(htonl(0x000fff04), (unsigned *) (apb + 0x78000));
 
-       do {
-               ncr_read(NCP_REGION_ID(15, 0), 0x410, 4, &value);
-       } while ((value & 0x0200) == 0);
-
-       /*
-        Indicate DDR Retention Reset
-        */
-
-       /* set bit 0 of persist_scratch */
-       writel_relaxed(0x00000001, apb + 0x300dc);
+       /* reset ELM statistics */
+       ncr_register_write(htonl(0x00001), (unsigned *) (apb + 0x60230));
+       ncr_register_write(htonl(0x00001), (unsigned *) (apb + 0x70230));
 
-       /*
-        * Issue Chip Reset
-        */
+       /* enable ELM trace */
+       ncr_register_write(htonl(0x000fff01), (unsigned *) (apb + 0x68000));
+       ncr_register_write(htonl(0x000fff01), (unsigned *) (apb + 0x78000));
+}
 
-       /* Intrnl Boot, 0xffff0000 Target */
-       writel_relaxed(0x00000040, apb + 0x31004);
-       /* Set ResetReadDone */
-       writel_relaxed(0x80000000, apb + 0x3180c);
-       /* Chip Reset */
-       writel_relaxed(0x00080802, apb + 0x31008);
 
-       wfi();
-       while (1)
-               ;
-       __asm__ __volatile__("nop\n\t");
+extern void ncp_ddr_shutdown(void *, void *,  unsigned long );
 
-       return;
-}
 
 void
 initiate_retention_reset(void)
 {
        unsigned long ctl_244 = 0;
        unsigned long value;
-       unsigned cpu_id;
+       unsigned cpu_id ;
+       volatile long tmp;
+       volatile long *ptmp;
 
        if (0 == ddr_retention_enabled) {
                pr_info("DDR Retention Reset is Not Enabled\n");
@@ -292,19 +264,17 @@ initiate_retention_reset(void)
        if (NULL == nca || NULL == apb || NULL == dickens)
                BUG();
 
-       /* kill the femac */
-       writel(0x80000000, (femac+0x2000));
-       value = readl(femac + 0x2000);
-
        preempt_disable();
        cpu_id = smp_processor_id();
-       udelay(1000);
+
        /* send stop message to other CPUs */
        local_irq_disable();
+       local_fiq_disable();
        asm volatile ("dsb" : : : "memory");
        asm volatile ("dmb" : : : "memory");
        system_state = SYSTEM_RESTART;
        smp_send_stop();
+       udelay(1000);
 
        flush_cache_all();
        flush_l3();
@@ -314,11 +284,6 @@ initiate_retention_reset(void)
        quiesce_vp_engine(AXXIA_ENGINE_CNAL);
 
 
-       /* disable sysmem interrupts */
-       value = 0;
-       ncr_write(NCP_REGION_ID(34, 0), 0x414, 4, &value);
-       ncr_write(NCP_REGION_ID(15, 0), 0x414, 4, &value);
-
        /* unlock reset register for later */
        writel(0x000000ab, apb + 0x31000); /* Access Key */
 
@@ -327,21 +292,27 @@ initiate_retention_reset(void)
        ncr_read(NCP_REGION_ID(34, 0), 0x3d0, 4, &ctl_244);
        ctl_244 |= 0x000a0000;
 
-
-       /* put secondary CPUs into reset */
+       /* belts & braces: put secondary CPUs into reset */
        value = ~(1 << cpu_id);
        value &= 0xffff;
        ncr_register_write(htonl(value), (unsigned *) (apb + 0x31030));
 
-       /*
-        * issue instruction barrier
-        * this should cause the next few instructions to be fetched
-        * into cache
-        */
-       asm volatile ("dsb" : : : "memory");
+       /* load entire ddr_shutdown function into L2 cache */
+       ptmp = (long *) ncp_ddr_shutdown;
+       do {
+               tmp += *ptmp++;
+       } while (ptmp < (long*) (ncp_ddr_shutdown + 0x1000));
+
        asm volatile ("isb" : : : "memory");
 
-       ncp_ddr_shutdown(ctl_244);
+       /* disable L2 prefetching */
+       cpu_disable_l2_prefetch();
+
+       /* reset ELM DDR access trace buffer */
+       reset_elm_trace();
+
+       /* call cache resident ddr shutdown function */
+       ncp_ddr_shutdown(nca, apb, ctl_244);
 
        return;
 }
@@ -376,7 +347,6 @@ axxia_ddr_retention_init(void)
                        apb = ioremap(0x2010000000, 0x80000);
                        nca = ioremap(0x002020100000ULL, 0x20000);
                        dickens = ioremap(0x2000000000, 0x1000000);
-                       femac = ioremap(0x2010120000, 0x10000);
                        ddr_retention_enabled = 1;
                        pr_info("DDR Retention Reset Initialized\n");
                }
diff --git a/arch/arm/mach-axxia/ddr_shutdown.c 
b/arch/arm/mach-axxia/ddr_shutdown.c
new file mode 100644
index 0000000..6c6c3bb
--- /dev/null
+++ b/arch/arm/mach-axxia/ddr_shutdown.c
@@ -0,0 +1,331 @@
+
+#include <asm/io.h>
+
+/*
+ * private copies of the ioread/write macros
+ * These are defined with a different barrier
+ * to avoid the outer_sync() call that's part
+ * of the normal barrier.
+ */
+#define pvt_ioread32be(p)   ({ unsigned int __v = be32_to_cpu((__force 
__be32)__raw_readl(p)); dsb(); __v; })
+#define pvt_iowrite32be(v,p) ({ dsb(); __raw_writel((__force 
__u32)cpu_to_be32(v), p); })
+
+#define pvt_ioread32(p)   ({ unsigned int __v = (__raw_readl(p)); dsb(); __v; 
})
+#define pvt_iowrite32(v,p) ({ dsb(); __raw_writel((__force __u32)(v), p); })
+
+/* #define DDR_SHUTDOWN_DEBUG  */
+#ifdef DDR_SHUTDOWN_DEBUG
+#define dbg_write(v, p) pvt_iowrite32be(v,p)
+#else
+#define dbg_write(v, p)
+#endif
+
+/*
+ * Wait For Completion timeout
+ * how many loops to wait for the config ring access to complete
+ */
+#define WFC_TIMEOUT (400000)
+
+/*
+ * DDR status timeout
+ * how many times we read the DDR status waiting for self refresh complete
+ */
+#define DDR_TIMEOUT (1000)
+
+void ncp_ddr_shutdown(void *nca, void *apb, unsigned long ctl_244)
+{
+       unsigned long value;
+       int two_elms = 0;
+       int wfc_loop = 0;
+       int ddr_loop = 0;
+
+       /* determine if we are in one or two ELM/SMEM mode */
+       value = pvt_ioread32(apb + 0x60004);
+       two_elms = (value & 0x00000200);
+
+       /*
+        * Issue command to put SMEM0 into self-refresh mode
+        *
+        * ncpWrite 0x22.0.0x3d0
+        */
+       dbg_write(0xaaaa0001, (unsigned *)(nca + 0x1200));
+
+       /* write register value into CDAR[0] */
+       pvt_iowrite32be(ctl_244, (unsigned *)(nca + 0x1000));
+       /* CDR2 - Node.target */
+       pvt_iowrite32be(0x00002200, (unsigned *)(nca + 0xf8));
+       /* CDR1 - word offset 0xf4 (byte offset 0x3d0) */
+       pvt_iowrite32be(0x000000f4, (unsigned *)(nca + 0xf4));
+       /* CDR0 - write command */
+       pvt_iowrite32be(0x80050003, (unsigned *)(nca + 0xf0));
+       wfc_loop = 0;
+       do {
+               if (wfc_loop++ > WFC_TIMEOUT) {
+                       dbg_write(value, (unsigned *)(nca + 0x11fc));
+                       dbg_write(0xffff0001, (unsigned *)(nca + 0x1200));
+                       goto do_reset;
+               }
+               dbg_write(wfc_loop, (unsigned *)(nca + 0x11f8));
+               value = pvt_ioread32be((unsigned *)
+                                      (nca + 0xf0));
+       } while ((0x80000000UL & value));
+       dbg_write(0xaaaa0002, (unsigned *)(nca + 0x1200));
+
+       if (two_elms) {
+               /*
+                * Issue command to put SMEM1 into self-refresh mode
+                *
+                * ncpWrite 0x0f.0.0x3d0
+                */
+               /* CDR2 - Node.target */
+               pvt_iowrite32be(0x00000f00, (unsigned *)(nca + 0xf8));
+               /* CDR0 - write command */
+               pvt_iowrite32be(0x80050003, (unsigned *)(nca + 0xf0));
+               wfc_loop = 0;
+               do {
+                       if (wfc_loop++ > WFC_TIMEOUT) {
+                               dbg_write(value, (unsigned *)(nca + 0x11fc));
+                               dbg_write(0xffff0002,
+                                         (unsigned *)(nca + 0x1200));
+                               goto do_reset;
+                       }
+                       value = pvt_ioread32be((unsigned *)
+                                              (nca + 0xf0));
+               } while ((0x80000000UL & value));
+       }
+
+       dbg_write(0xaaaa0003, (unsigned *)(nca + 0x1200));
+
+       /*
+        * Poll for SMEM0 refresh-mode command completion
+        */
+       /* CDR1 - word offset 0x104 (byte offset 0x410) */
+       pvt_iowrite32be(0x00000104, (unsigned *)(nca + 0xf4));
+       /* CDR2 - Node.target */
+       pvt_iowrite32be(0x00002200, (unsigned *)(nca + 0xf8));
+       ddr_loop = 0;
+       do {
+               if (ddr_loop++ > DDR_TIMEOUT) {
+                       dbg_write(value, (unsigned *)(nca + 0x11fc));
+                       dbg_write(0xffff0003, (unsigned *)(nca + 0x1200));
+                       goto do_reset;
+               }
+               pvt_iowrite32be(wfc_loop, (unsigned *)
+                               (nca + 0x11f0));
+
+               /* issue config ring read */
+               pvt_iowrite32be(0x80040003, (unsigned *)
+                               (nca + 0xf0));
+               wfc_loop = 0;
+               do {
+                       if (wfc_loop++ > WFC_TIMEOUT) {
+                               dbg_write(value, (unsigned *)(nca + 0x11fc));
+                               dbg_write(0xffff0004,
+                                         (unsigned *)(nca + 0x1200));
+                               goto do_reset;
+                       }
+                       value = pvt_ioread32be((unsigned *)
+                                              (nca + 0xf0));
+               } while ((0x80000000UL & value));
+
+               value = pvt_ioread32be((unsigned *)
+                                      (nca + 0x1000));
+
+       } while ((value & 0x0200) == 0);
+       dbg_write(0xaaaa0004, (unsigned *)(nca + 0x1200));
+
+       if (two_elms) {
+               /*
+                * Poll for SMEM1 refresh-mode command completion
+                */
+               /* CDR2 - Node.target */
+               pvt_iowrite32be(0x00000f00, (unsigned *)(nca + 0xf8));
+               ddr_loop = 0;
+               do {
+                       if (ddr_loop++ > DDR_TIMEOUT) {
+                               dbg_write(value, (unsigned *)(nca + 0x11fc));
+                               dbg_write(0xffff0005,
+                                         (unsigned *)(nca + 0x1200));
+                               goto do_reset;
+                       }
+
+                       /* issue config ring read */
+                       pvt_iowrite32be(0x80040003, (unsigned *)(nca + 0xf0));
+                       wfc_loop = 0;
+                       do {
+                               if (wfc_loop++ > WFC_TIMEOUT) {
+                                       dbg_write(value,
+                                                 (unsigned *)(nca + 0x11fc));
+                                       dbg_write(0xffff0006,
+                                                 (unsigned *)(nca + 0x1200));
+                                       goto do_reset;
+                               }
+                               value =
+                                   pvt_ioread32be((unsigned *)(nca + 0xf0));
+                       } while ((0x80000000UL & value));
+
+                       value = pvt_ioread32be((unsigned *)
+                                              (nca + 0x1000));
+                       wfc_loop++;
+               } while ((value & 0x0200) == 0);
+       }
+
+       dbg_write(0xaaaa0005, (unsigned *)(nca + 0x1200));
+
+       /*
+        * Tell U-Boot to do a DDR retention-reset
+        * (i.e. set bit 0 of persist_scratch register)
+        */
+       pvt_iowrite32(0x00000001, apb + 0x300dc);
+
+       dbg_write(0xaaaa0006, (unsigned *)(nca + 0x1200));
+      do_reset:
+       /*
+        * Issue Chip reset
+        */
+       /* Intrnl Boot, 0xffff0000 Target */
+       pvt_iowrite32(0x00000040, apb + 0x31004);
+       /* Set ResetReadDone */
+       pvt_iowrite32(0x80000000, apb + 0x3180c);
+       /* Chip Reset */
+       pvt_iowrite32(0x00080802, apb + 0x31008);
+
+       while(1);
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+
+       return;
+}
+
+void ncp_ddr_shutdown_dummy(void)
+{
+       wfi();
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+       __asm__ __volatile__(" nop \n\t");
+}
-- 
1.7.9.5

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to