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