[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