[linux-yocto] [PATCH 11/57] fixes for VP engine quiesce and DDR shutdown
Bruce Ashfield
bruce.ashfield at windriver.com
Tue Mar 18 14:30:12 PDT 2014
nit picking on this, but we are conforming to upstream standards. This
is missing a subsystem in the shortlog, and it doesn't actually tell us
what it is fixing.
Bruce
On 14-03-18 12:56 AM, Charlie Paul wrote:
> From: Gary McGee <gary.mcgee at 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);
>
More information about the linux-yocto
mailing list