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

---
 arch/arm/mach-axxia/ddr_retention.c |  187 ++++++++++++++++++++---------------
 arch/arm/mach-axxia/ncr.c           |   18 +++-
 2 files changed, 121 insertions(+), 84 deletions(-)

diff --git a/arch/arm/mach-axxia/ddr_retention.c 
b/arch/arm/mach-axxia/ddr_retention.c
index 933ff6d..bcedf33 100644
--- a/arch/arm/mach-axxia/ddr_retention.c
+++ b/arch/arm/mach-axxia/ddr_retention.c
@@ -36,9 +36,15 @@
 static void __iomem *nca;
 static void __iomem *apb;
 static void __iomem *dickens;
+static void __iomem *femac;
 static int ddr_retention_enabled;
 
-static unsigned long
+enum {
+       AXXIA_ENGINE_CAAL,
+       AXXIA_ENGINE_CNAL
+};
+
+unsigned long
 ncp_caal_regions_acp55xx[] = {
        NCP_REGION_ID(0x0b, 0x05),      /* SPPV2   */
        NCP_REGION_ID(0x0c, 0x05),      /* SED     */
@@ -57,6 +63,11 @@ ncp_caal_regions_acp55xx[] = {
        NCP_REGION_ID(0x1c, 0x05),      /* PAB     */
        NCP_REGION_ID(0x1f, 0x05),      /* EIOAM0  */
        NCP_REGION_ID(0x31, 0x05),      /* ISB     */
+       NCP_REGION_ID(0xff, 0xff)
+};
+
+unsigned long
+ncp_cnal_regions_acp55xx[] = {
        NCP_REGION_ID(0x28, 0x05),      /* EIOASM0 */
        NCP_REGION_ID(0x29, 0x05),      /* EIOASM1 */
        NCP_REGION_ID(0x2a, 0x05),      /* EIOAS2  */
@@ -67,6 +78,7 @@ ncp_caal_regions_acp55xx[] = {
        NCP_REGION_ID(0xff, 0xff)
 };
 
+
 /*
   
------------------------------------------------------------------------------
   flush_l3
@@ -128,17 +140,36 @@ flush_l3(void)
 }
 
 static void
-quiesce_vp_engine(void)
+quiesce_vp_engine(int engineType)
 {
-       unsigned long   *pCnalRegions = ncp_caal_regions_acp55xx;
-       unsigned long     *pRegion;
+       unsigned long *pEngineRegions;
+       unsigned long ortOff, owtOff;
+       unsigned long *pRegion;
        unsigned ort, owt;
-       unsigned long      buf = 0;
-       unsigned short     node, target;
-       int      loop;
+       unsigned long buf = 0;
+       unsigned short node, target;
+       int loop;
 
        pr_info("quiescing VP engines...\n");
-       pRegion = pCnalRegions;
+
+       switch (engineType) {
+       case AXXIA_ENGINE_CNAL:
+               pEngineRegions = ncp_cnal_regions_acp55xx;
+               ortOff = 0x1c0;
+               owtOff = 0x1c4;
+               break;
+
+       case AXXIA_ENGINE_CAAL:
+               pEngineRegions = ncp_caal_regions_acp55xx;
+               ortOff = 0xf8;
+               owtOff = 0xfc;
+               break;
+
+       default:
+               return;
+       }
+
+       pRegion = pEngineRegions;
 
        while (*pRegion != NCP_REGION_ID(0xff, 0xff)) {
                /* set read/write transaction limits to zero */
@@ -147,15 +178,15 @@ quiesce_vp_engine(void)
                pRegion++;
        }
 
-       pRegion = pCnalRegions;
+       pRegion = pEngineRegions;
        loop = 0;
 
        while (*pRegion != NCP_REGION_ID(0xff, 0xff)) {
                node = (*pRegion & 0xffff0000) >> 16;
                target = *pRegion & 0x0000ffff;
                /* read the number of outstanding read/write transactions */
-               ncr_read(*pRegion, 0xf8, 4, &ort);
-               ncr_read(*pRegion, 0xfc, 4, &owt);
+               ncr_read(*pRegion, ortOff, 4, &ort);
+               ncr_read(*pRegion, owtOff, 4, &owt);
 
                if ((ort == 0) && (owt == 0)) {
                        /* this engine has been quiesced, move on to the next */
@@ -164,8 +195,9 @@ quiesce_vp_engine(void)
                        pRegion++;
                } else {
                        if (loop++ > 10000) {
-                               pr_info("Unable to quiesce region 0x%02x.0x%02x 
ort=0x%x, owt=0x%x\n",
-                                      node, target, ort, owt);
+                               pr_info(
+                                               "Unable to quiesce region 
0x%02x.0x%02x ort=0x%x, owt=0x%x\n",
+                                               node, target, ort, owt);
                                pRegion++;
                                loop = 0;
                                continue;
@@ -176,76 +208,71 @@ quiesce_vp_engine(void)
        return;
 }
 
+static inline void cpu_disable_l2_prefetch(void)
+{
+       unsigned int v;
+
+    /*
+     * MRC p15, 1, <Rt>, c15, c0, 3; Read L2 Prefetch Control Register
+     * MCR p15, 1, <Rt>, c15, c0, 3; Write L2 Prefetch Control Register
+     *
+     */
+       asm volatile(
+       "       mrc     p15, 1, %0, c15, c0, 3\n"
+       "       and     %0, %0, #0x0000\n"
+       "       mcr     p15, 1, %0, c15, c0, 3\n"
+       : "=&r" (v)
+       :
+       : "cc");
+
+       isb();
+}
+
 static inline void
-ncp_ddr_shutdown(void)
+ncp_ddr_shutdown(unsigned long ctl_244)
 {
        unsigned long value;
-       int loop = 1;
-       unsigned long cdr2[2] = {0x00002200, 0x00000f00};
-       int smId;
 
+       cpu_disable_l2_prefetch();
 
        /*
-        * Most of the PIO command has already been set up.
-        * issue config ring write - enter DDR self-refresh mode
+        * put SDRAM in self-refresh mode
         */
-
-       for (smId = 0; smId < 2; smId++) {
-               /* CDR2 - Node.target */
-               ncr_register_write(cdr2[smId], (unsigned *) (nca + 0xf8));
-               /* CDR0 - */
-               ncr_register_write(0x80050003, (unsigned *) (nca + 0xf0));
-               do {
-                       value = ncr_register_read((unsigned *)
-                                                 (nca + 0xf0));
-               } while ((0x80000000UL & value));
-       }
+       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) */
-       ncr_register_write(0x00000104, (unsigned *) (nca + 0xf4));
+       do {
+               ncr_read(NCP_REGION_ID(34, 0), 0x410, 4, &value);
+       } while ((value & 0x0200) == 0);
 
-       for (smId = 0; smId < 2; smId++) {
-               /* CDR2 - Node.target */
-               ncr_register_write(cdr2[smId], (unsigned *) (nca + 0xf8));
-               do {
-                       ncr_register_write(loop, (unsigned *)
-                                          (nca + 0x11f0));
-
-                       /* issue config ring read */
-                       ncr_register_write(0x80040003, (unsigned *)
-                                          (nca + 0xf0));
-                       do {
-                               value = ncr_register_read((unsigned *)
-                                                         (nca + 0xf0));
-                       } while ((0x80000000UL & value));
-
-                       value = ncr_register_read((unsigned *)
-                                                 (nca + 0x1000));
-                       ncr_register_write(value, (unsigned *)
-                                          (nca + 0x1200));
-
-                       loop++;
-               } while ((value & 0x0200) == 0);
-       }
+       do {
+               ncr_read(NCP_REGION_ID(15, 0), 0x410, 4, &value);
+       } while ((value & 0x0200) == 0);
 
        /*
-         Indicate DDR Retention Reset
-       */
+        Indicate DDR Retention Reset
+        */
 
        /* set bit 0 of persist_scratch */
-       writel(0x00000001, apb + 0x300dc);
+       writel_relaxed(0x00000001, apb + 0x300dc);
 
        /*
-         Issue Chip Reset
-       */
+        * Issue Chip Reset
+        */
 
        /* Intrnl Boot, 0xffff0000 Target */
-       writel(0x00000040, apb + 0x31004);
+       writel_relaxed(0x00000040, apb + 0x31004);
        /* Set ResetReadDone */
-       writel(0x80000000, apb + 0x3180c);
+       writel_relaxed(0x80000000, apb + 0x3180c);
        /* Chip Reset */
-       writel(0x00080802, apb + 0x31008);
+       writel_relaxed(0x00080802, apb + 0x31008);
+
+       wfi();
+       while (1)
+               ;
+       __asm__ __volatile__("nop\n\t");
 
        return;
 }
@@ -255,6 +282,7 @@ initiate_retention_reset(void)
 {
        unsigned long ctl_244 = 0;
        unsigned long value;
+       unsigned cpu_id;
 
        if (0 == ddr_retention_enabled) {
                pr_info("DDR Retention Reset is Not Enabled\n");
@@ -264,6 +292,13 @@ 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();
        asm volatile ("dsb" : : : "memory");
@@ -275,10 +310,11 @@ initiate_retention_reset(void)
        flush_l3();
 
        /* TODO - quiesce VP engines */
-       quiesce_vp_engine();
+       quiesce_vp_engine(AXXIA_ENGINE_CAAL);
+       quiesce_vp_engine(AXXIA_ENGINE_CNAL);
+
 
        /* disable sysmem interrupts */
-       pr_info("disabling sysmem interrupts\n");
        value = 0;
        ncr_write(NCP_REGION_ID(34, 0), 0x414, 4, &value);
        ncr_write(NCP_REGION_ID(15, 0), 0x414, 4, &value);
@@ -292,18 +328,10 @@ initiate_retention_reset(void)
        ctl_244 |= 0x000a0000;
 
 
-       /*
-        * set up for CRBW operation
-        */
-
-       /* write register value into CDAR[0] */
-       ncr_register_write(ctl_244, (unsigned *) (nca + 0x1000));
-
-       /* CDR2 - Node.target = 34.0 */
-       ncr_register_write(0x00002200, (unsigned *) (nca + 0xf8));
-
-       /* CDR1 - word offset 0xf4 (byte offset 0x3d0) */
-       ncr_register_write(0x000000f4, (unsigned *) (nca + 0xf4));
+       /* put secondary CPUs into reset */
+       value = ~(1 << cpu_id);
+       value &= 0xffff;
+       ncr_register_write(htonl(value), (unsigned *) (apb + 0x31030));
 
        /*
         * issue instruction barrier
@@ -311,9 +339,9 @@ initiate_retention_reset(void)
         * into cache
         */
        asm volatile ("dsb" : : : "memory");
-       prefetch_range(ncp_ddr_shutdown, 0x1000);
+       asm volatile ("isb" : : : "memory");
 
-       ncp_ddr_shutdown();
+       ncp_ddr_shutdown(ctl_244);
 
        return;
 }
@@ -345,9 +373,10 @@ axxia_ddr_retention_init(void)
                                S_IWUSR, NULL, &axxia_ddr_retention_proc_ops)) {
                        pr_info("Failed to register DDR retention proc 
entry\n");
                } else {
-                       apb = ioremap(0x2010000000, 0x40000);
+                       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/ncr.c b/arch/arm/mach-axxia/ncr.c
index 4112038..51fcf66 100644
--- a/arch/arm/mach-axxia/ncr.c
+++ b/arch/arm/mach-axxia/ncr.c
@@ -92,11 +92,18 @@ typedef union {
 #ifdef CONFIG_ARM
 
 /*
+ * like iowrite32be but without the barrier.
+ * The iowmb barrier in the standard macro includes a outer_cache_sync
+ * which we don't want for Axxia register IO.
+ */
+#define axxia_write32be(v,p) ({  __raw_writel((__force __u32)cpu_to_be32(v), 
p); })
+
+/*
   ----------------------------------------------------------------------
   ncr_register_read
 */
 
-unsigned long
+inline unsigned long
 ncr_register_read(unsigned *address)
 {
        unsigned long value;
@@ -112,9 +119,10 @@ ncr_register_read(unsigned *address)
 */
 
 void
-ncr_register_write(const unsigned value, unsigned *address)
+inline ncr_register_write(const unsigned value, unsigned *address)
 {
-       iowrite32be(value, address);
+       axxia_write32be(value, address);
+    asm volatile ("mcr p15,0,%0,c7,c5,4" : : "r" (0));  /* isb */
 
        return;
 }
@@ -126,7 +134,7 @@ ncr_register_write(const unsigned value, unsigned *address)
   ncr_register_read
 */
 
-unsigned long
+inline unsigned long
 ncr_register_read(unsigned *address)
 {
        unsigned long value;
@@ -141,7 +149,7 @@ ncr_register_read(unsigned *address)
   ncr_register_write
 */
 
-void
+inline void
 ncr_register_write(const unsigned value, unsigned *address)
 {
        out_be32(address, value);
-- 
1.7.9.5

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

Reply via email to