[linux-yocto] [PATCH 26/30] LSI AXM55xx arm/axxia: improved robustness for DDR retention

Charlie Paul cpaul.windriver at gmail.com
Tue May 6 09:36:58 PDT 2014


From: Gary McGee <gary.mcgee at lsi.com>

    - add new ncp_ddr_shutdown() function using private i/o functions.
      This eliminates unwanted code that may be introduced by use of
      the standard i/o macros/functions.
    - do explicit memory copy to preload ncp_ddr_shutdown() into L2 cache
    - initialize ELM sysmem capture to provide post-mortem debug capability
    - fix VP engine quiesce to account for engines with different CMSI
      adaptation layers  (CAAL vs. CNAL).

Signed-off-by: Gary McGee <gary.mcgee at lsi.com>
---
 arch/arm/mach-axxia/Makefile        |    2 +-
 arch/arm/mach-axxia/ddr_retention.c |  231 ++++++++++++------------
 arch/arm/mach-axxia/ddr_shutdown.c  |  332 +++++++++++++++++++++++++++++++++++
 3 files changed, 446 insertions(+), 119 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 47e386b..1352c37d 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_AXXIA_RIO)			+= rapidio.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
diff --git a/arch/arm/mach-axxia/ddr_retention.c b/arch/arm/mach-axxia/ddr_retention.c
index 7e4687d..6429151 100644
--- a/arch/arm/mach-axxia/ddr_retention.c
+++ b/arch/arm/mach-axxia/ddr_retention.c
@@ -26,7 +26,9 @@
 #include <linux/syscore_ops.h>
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
+#include <linux/prefetch.h>
 #include <linux/of.h>
+
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 #include <mach/ncr.h>
@@ -36,7 +38,13 @@ static void __iomem *apb;
 static void __iomem *dickens;
 static int ddr_retention_enabled;
 
-unsigned long ncp_caal_regions_acp55xx[] = {
+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     */
 	NCP_REGION_ID(0x0e, 0x05),      /* DPI_HFA */
@@ -54,16 +62,22 @@ unsigned long 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(0x28, 0x05),      /* EIOASM0 */
-	NCP_REGION_ID(0x29, 0x05),      /* EIOASM1 */
-	NCP_REGION_ID(0x2a, 0x05),      /* EIOAS2  */
-	NCP_REGION_ID(0x2b, 0x05),      /* EIOAS3  */
-	NCP_REGION_ID(0x2c, 0x05),      /* EIOAS4  */
-	NCP_REGION_ID(0x2d, 0x05),      /* EIOAS5  */
-	NCP_REGION_ID(0x32, 0x05),      /* ISBS    */
 	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  */
+	NCP_REGION_ID(0x2b, 0x05), /* EIOAS3  */
+	NCP_REGION_ID(0x2c, 0x05), /* EIOAS4  */
+	NCP_REGION_ID(0x2d, 0x05), /* EIOAS5  */
+	NCP_REGION_ID(0x32, 0x05), /* ISBS    */
+	NCP_REGION_ID(0xff, 0xff)
+};
+
+
 /*
   ------------------------------------------------------------------------------
   flush_l3
@@ -120,23 +134,41 @@ flush_l3(void)
 	}
 
 	asm volatile ("dsb" : : : "memory");
-	asm volatile ("dmb" : : : "memory");
 
 	return;
 }
 
 static void
-quiesce_vp_engine(void)
+quiesce_vp_engine(int engineType)
 {
-	unsigned long   *pCnalRegions = ncp_caal_regions_acp55xx;
+	unsigned long   *pEngineRegions;
 	unsigned long     *pRegion;
+	unsigned long    ortOff, owtOff;
 	unsigned ort, owt;
 	unsigned long      buf = 0;
 	unsigned short     node, target;
 	int      loop;
 
 	printk(KERN_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 */
@@ -145,15 +177,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 */
@@ -173,86 +205,54 @@ quiesce_vp_engine(void)
 	return;
 }
 
-static inline void
-ncp_ddr_shutdown(void)
+static inline void cpu_disable_l2_prefetch(void)
 {
-	unsigned long value;
-	int loop = 1;
-	unsigned long cdr2[2] = {0x00002200, 0x00000f00};
-	int smId;
-
-
-	/*
-	 * Most of the PIO command has already been set up.
-	 * issue config ring write - enter DDR 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));
-	}
-
-	/* check interrupt status for completion */
-	/* CDR1 - word offset 0x104 (byte offset 0x410) */
-	ncr_register_write(0x00000104, (unsigned *) (nca + 0xf4));
+	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();
+}
 
-	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);
-	}
+static inline void
+reset_elm_trace(void)
+{
+	/* reset and disable ELM trace */
+	ncr_register_write(htonl(0x000fff04), (unsigned *) (apb + 0x68000));
+	ncr_register_write(htonl(0x000fff04), (unsigned *) (apb + 0x78000));
 
-	/*
-	  Indicate DDR Retention Reset
-	*/
+	/* reset ELM statistics */
+	ncr_register_write(htonl(0x00001), (unsigned *) (apb + 0x60230));
+	ncr_register_write(htonl(0x00001), (unsigned *) (apb + 0x70230));
 
-	/* set bit 0 of persist_scratch */
-	writel(0x00000001, apb + 0x300dc);
+	/* enable ELM trace */
+	ncr_register_write(htonl(0x000fff01), (unsigned *) (apb + 0x68000));
+	ncr_register_write(htonl(0x000fff01), (unsigned *) (apb + 0x78000));
+}
 
-	/*
-	  Issue Chip Reset
-	*/
 
-	/* Intrnl Boot, 0xffff0000 Target */
-	writel(0x00000040, apb + 0x31004);
-	/* Set ResetReadDone */
-	writel(0x80000000, apb + 0x3180c);
-	/* Chip Reset */
-	writel(0x00080802, apb + 0x31008);
+extern void ncp_ddr_shutdown(void *, void *,  unsigned long);
 
-	return;
-}
 
 void
 initiate_retention_reset(void)
 {
 	unsigned long ctl_244 = 0;
 	unsigned long value;
-	unsigned long delay;
+	unsigned cpu_id ;
+	volatile long tmp;
+	volatile long *ptmp;
 
 	if (0 == ddr_retention_enabled) {
 		pr_info("DDR Retention Reset is Not Enabled\n");
@@ -262,27 +262,25 @@ initiate_retention_reset(void)
 	if (NULL == nca || NULL == apb || NULL == dickens)
 		BUG();
 
-	system_state = SYSTEM_RESTART;
+	preempt_disable();
+	cpu_id = smp_processor_id();
+
+	/* send stop message to other CPUs */
+	local_irq_disable();
+	local_fiq_disable();
 	asm volatile ("dsb" : : : "memory");
 	asm volatile ("dmb" : : : "memory");
-	device_shutdown();
-	syscore_shutdown();
+	system_state = SYSTEM_RESTART;
 	smp_send_stop();
 
-	for (delay = 0; delay < 10000; ++delay)
-		udelay(1000);
+	udelay(1000);
 
 	flush_cache_all();
 	flush_l3();
 
-	/* TODO - quiesce VP engines */
-	quiesce_vp_engine();
-
-	/* disable sysmem interrupts */
-	printk(KERN_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);
+	/*  quiesce VP engines */
+	quiesce_vp_engine(AXXIA_ENGINE_CAAL);
+	quiesce_vp_engine(AXXIA_ENGINE_CNAL);
 
 	/* unlock reset register for later */
 	writel(0x000000ab, apb + 0x31000); /* Access Key */
@@ -292,27 +290,27 @@ initiate_retention_reset(void)
 	ncr_read(NCP_REGION_ID(34, 0), 0x3d0, 4, &ctl_244);
 	ctl_244 |= 0x000a0000;
 
-	/*
-	 * set up for CRBW operation
-	 */
-	/* write register value into CDAR[0] */
-	ncr_register_write(ctl_244, (unsigned *) (nca + 0x1000));
+	/* belts & braces: put secondary CPUs into reset */
+	value = ~(1 << cpu_id);
+	value &= 0xffff;
+	ncr_register_write(htonl(value), (unsigned *) (apb + 0x31030));
 
-	/* CDR2 - Node.target = 34.0 */
-	ncr_register_write(0x00002200, (unsigned *) (nca + 0xf8));
+	/* load entire ddr_shutdown function into L2 cache */
+	ptmp = (long *) ncp_ddr_shutdown;
+	do {
+		tmp += *ptmp++;
+	} while (ptmp < (long *) (ncp_ddr_shutdown + 0x1000));
 
-	/* CDR1 - word offset 0xf4 (byte offset 0x3d0) */
-	ncr_register_write(0x000000f4, (unsigned *) (nca + 0xf4));
+	asm volatile ("isb" : : : "memory");
 
-	/*
-	 * issue instruction barrier
-	 * this should cause the next few instructions to be fetched
-	 * into cache
-	 */
-	asm volatile ("dsb" : : : "memory");
-	prefetch(ncp_ddr_shutdown);
+	/* disable L2 prefetching */
+	cpu_disable_l2_prefetch();
 
-	ncp_ddr_shutdown();
+	/* reset ELM DDR access trace buffer */
+	reset_elm_trace();
+
+	/* call cache resident ddr shutdown function */
+	ncp_ddr_shutdown(nca, apb, ctl_244);
 
 	return;
 }
@@ -326,13 +324,11 @@ axxia_ddr_retention_trigger(struct file *file, const char __user *buf,
 	return 0;
 }
 
-static const struct file_operations proc_ops = {
+static const struct file_operations axxia_ddr_retention_proc_ops = {
 	.write      = axxia_ddr_retention_trigger,
 	.llseek     = noop_llseek,
 };
 
-#define PROC_PATH "driver/axxia_ddr_retention_reset"
-
 void
 axxia_ddr_retention_init(void)
 {
@@ -343,11 +339,10 @@ axxia_ddr_retention_init(void)
 	if (of_find_compatible_node(NULL, NULL, "lsi,axm5516")) {
 		/* Create /proc entry. */
 		if (!proc_create("driver/axxia_ddr_retention_reset",
-				 S_IWUSR, NULL,
-				 &proc_ops)) {
+				 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);
 			ddr_retention_enabled = 1;
diff --git a/arch/arm/mach-axxia/ddr_shutdown.c b/arch/arm/mach-axxia/ddr_shutdown.c
new file mode 100644
index 0000000..a10a4cb
--- /dev/null
+++ b/arch/arm/mach-axxia/ddr_shutdown.c
@@ -0,0 +1,332 @@
+
+#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



More information about the linux-yocto mailing list