[linux-yocto] [PATCH 23/42] Revert "arch/arm/mach-axxia: fixed failure to power up cluster"

Cristian Bercaru cristian.bercaru at windriver.com
Thu Jun 11 01:32:08 PDT 2015


From: Magnus Karlsson <magnus.karlsson at intel.com>

This is a port of commit 2445bd5ff062fb45c03a4e50edd014e7d4fd885c from
linux-yocto-3.10, branch standard/axxia/base, that reverts
c6bc0772d9fff6571364dedfe0bf05b122d3b5c2 from the same branch.

Signed-off-by: Magnus Karlsson <magnus.karlsson at intel.com>
---
 arch/arm/mach-axxia/hotplug.c              |   36 +++---
 arch/arm/mach-axxia/lsi_power_management.c |  191 +++++++++++-----------------
 arch/arm/mach-axxia/lsi_power_management.h |    9 +-
 arch/arm/mach-axxia/platsmp.c              |   39 +++---
 4 files changed, 118 insertions(+), 157 deletions(-)

diff --git a/arch/arm/mach-axxia/hotplug.c b/arch/arm/mach-axxia/hotplug.c
index 5def7c3..8878346 100644
--- a/arch/arm/mach-axxia/hotplug.c
+++ b/arch/arm/mach-axxia/hotplug.c
@@ -85,19 +85,13 @@ static inline void pm_L2_logical_shutdown(u32 cpu)
 			: "Ir" (0x400)
 			: "cc");
 
-	asm volatile(
-	"	mrc		p15, 1, %0, c15, c0, 4\n"
-	"	orr	%0, %0, %1\n"
-	"	mcr		p15, 1, %0, c15, c0, 4\n"
-	: "=&r" (val)
-	: "Ir" (0x1)
-	: "cc");
-
 	isb();
 	dsb();
 
+	/* Clear and invalidate all L1 and L2 data cache */
 	flush_cache_all();
 
+
 	/* Turn the DBG Double Lock quiet */
 	asm volatile(
 			/*
@@ -169,8 +163,6 @@ static inline void cpu_leave_lowpower(void)
 			: "=&r" (v)
 			: "Ir" (CR_C), "Ir" (0x40)
 			: "cc");
-	isb();
-	dsb();
 }
 
 static void __ref platform_do_lowpower(unsigned int cpu, int *spurious)
@@ -197,9 +189,9 @@ static void __ref platform_do_lowpower(unsigned int cpu, int *spurious)
 	phys_cpu = cluster + (phys_cpu % 4);
 
 	if (pen_release == phys_cpu) {
-	/*
-	 * OK, proper wakeup, we're done
-	 */
+		/*
+		 * OK, proper wakeup, we're done
+		 */
 		break;
 	}
 
@@ -219,9 +211,7 @@ int axxia_platform_cpu_kill(unsigned int cpu)
 {
 
 #ifdef CONFIG_HOTPLUG_CPU_COMPLETE_POWER_DOWN
-	get_cpu();
 	pm_cpu_shutdown(cpu);
-	put_cpu();
 #endif
 	return 1;
 }
@@ -237,6 +227,21 @@ void axxia_platform_cpu_die(unsigned int cpu)
 #ifdef CONFIG_HOTPLUG_CPU_COMPLETE_POWER_DOWN
 	bool last_cpu;
 
+	int timeout;
+	timeout = 30;
+
+	/* make sure no migrations are happening */
+	while (!axxia_is_empty(&axxia_circ_q)) {
+
+		if (timeout-- == 0)
+			break;
+
+		mdelay(1);
+	}
+
+	if (timeout == 0)
+		pr_err("ERROR: tried to shut down and Q was still full\n");
+
 	last_cpu = pm_cpu_last_of_cluster(cpu);
 	if (last_cpu)
 		pm_L2_logical_shutdown(cpu);
@@ -246,6 +251,7 @@ void axxia_platform_cpu_die(unsigned int cpu)
 	for (;;)
 		wfi();
 
+
 #else /* CPU low power mode */
 
 	int spurious = 0;
diff --git a/arch/arm/mach-axxia/lsi_power_management.c b/arch/arm/mach-axxia/lsi_power_management.c
index dbf35e2..93e8ac9 100644
--- a/arch/arm/mach-axxia/lsi_power_management.c
+++ b/arch/arm/mach-axxia/lsi_power_management.c
@@ -53,13 +53,6 @@ PORESET_CLUSTER1,
 PORESET_CLUSTER2,
 PORESET_CLUSTER3 };
 
-static const u32 cluster_to_mask[MAX_CLUSTER] = {
-		IPI0_MASK,
-		IPI1_MASK,
-		IPI2_MASK,
-		IPI3_MASK
-};
-
 static const u32 ipi_register[MAX_IPI] = {
 		NCP_SYSCON_MASK_IPI0,
 		NCP_SYSCON_MASK_IPI1,
@@ -99,7 +92,6 @@ u32 pm_cpu_powered_down;
 
 /*======================= LOCAL FUNCTIONS ==============================*/
 static void pm_set_bits_syscon_register(u32 reg, u32 data);
-static void pm_or_bits_syscon_register(u32 reg, u32 data);
 static void pm_clear_bits_syscon_register(u32 reg, u32 data);
 static bool pm_test_for_bit_with_timeout(u32 reg, u32 bit);
 static bool pm_wait_for_bit_clear_with_timeout(u32 reg,
@@ -245,11 +237,6 @@ bool pm_cpu_last_of_cluster(u32 cpu)
 
 static void pm_set_bits_syscon_register(u32 reg, u32 data)
 {
-	writel(data, syscon + reg);
-}
-
-static void pm_or_bits_syscon_register(u32 reg, u32 data)
-{
 	u32 tmp;
 
 	tmp = readl(syscon + reg);
@@ -257,7 +244,6 @@ static void pm_or_bits_syscon_register(u32 reg, u32 data)
 	writel(tmp, syscon + reg);
 }
 
-
 static void pm_clear_bits_syscon_register(u32 reg, u32 data)
 {
 	u32 tmp;
@@ -433,25 +419,23 @@ dickens_power_up:
 	return rval;
 }
 
-static void pm_disable_ipi_interrupts(u32 cpu)
-{
-	pm_clear_bits_syscon_register(ipi_register[cpu], IPI_IRQ_MASK);
-}
-
-static void pm_enable_ipi_interrupts(u32 cpu)
+static int pm_enable_ipi_interrupts(u32 cpu)
 {
 
 	u32 i;
+	u32 cpumask = 1 << cpu;
 	u32 powered_on_cpu = (~(pm_cpu_powered_down) & IPI_IRQ_MASK);
 
+	/* Enable the CPU IPI */
 	pm_set_bits_syscon_register(ipi_register[cpu], powered_on_cpu);
 
-	for (i = 0; i < MAX_CPUS; i++) {
+	for (i = 0; i < MAX_IPI; i++) {
 		if ((1 << i) & powered_on_cpu)
-			pm_or_bits_syscon_register(ipi_register[i], (1 << cpu));
+			pm_set_bits_syscon_register(ipi_register[i], cpumask);
 	}
 
-	return;
+	return 0;
+
 }
 
 void pm_init_syscon(void)
@@ -499,7 +483,7 @@ void pm_cpu_shutdown(u32 cpu)
 	if (last_cpu) {
 
 		/* Disable all the interrupts to the cluster gic */
-		pm_or_bits_syscon_register(NCP_SYSCON_GIC_DISABLE, cluster_mask);
+		pm_set_bits_syscon_register(NCP_SYSCON_GIC_DISABLE, cluster_mask);
 
 		/* Remove the cluster from the Dickens coherency domain */
 		pm_dickens_logical_shutdown(cluster);
@@ -517,7 +501,7 @@ void pm_cpu_shutdown(u32 cpu)
 		}
 
 		/* Turn off the ACE */
-		pm_or_bits_syscon_register(NCP_SYSCON_PWR_ACEPWRDNRQ, cluster_mask);
+		pm_set_bits_syscon_register(NCP_SYSCON_PWR_ACEPWRDNRQ, cluster_mask);
 
 		/* Wait for ACE to complete power off */
 		success = pm_wait_for_bit_clear_with_timeout(NCP_SYSCON_PWR_NACEPWRDNACK, cluster);
@@ -528,7 +512,7 @@ void pm_cpu_shutdown(u32 cpu)
 		}
 
 		/* Isolate the cluster */
-		pm_or_bits_syscon_register(NCP_SYSCON_PWR_ISOLATEL2MISC, cluster_mask);
+		pm_set_bits_syscon_register(NCP_SYSCON_PWR_ISOLATEL2MISC, cluster_mask);
 
 		/* Wait for WFI L2 to go to standby */
 		success = pm_test_for_bit_with_timeout(NCP_SYSCON_PWR_STANDBYWFIL2, cluster);
@@ -571,10 +555,21 @@ int pm_cpu_powerup(u32 cpu)
 	u32 reqcpu = cpu_logical_map(cpu);
 	u32 cluster = reqcpu / CORES_PER_CLUSTER;
 	u32 cluster_mask = (0x01 << cluster);
+	u32 timeout;
 
 	pm_init_syscon();
 
 	/*
+	 * The key value has to be written before the CPU RST can be written.
+	 */
+	pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWRUP_CPU_RST, cpu_mask);
+
+	/* Hold the CPU in reset */
+	pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE);
+	pm_set_bits_syscon_register(NCP_SYSCON_HOLD_CPU, cpu_mask);
+
+	/*
 	 * Is this the first cpu of a cluster to come back on?
 	 * Then power up the L2 cache.
 	 */
@@ -586,19 +581,10 @@ int pm_cpu_powerup(u32 cpu)
 			pr_err("CPU: Failed the logical L2 power up\n");
 			goto pm_power_up;
 		}
-		cluster_power_up[cluster] = true;
 		pm_clear_bits_syscon_register(NCP_SYSCON_GIC_DISABLE, cluster_mask);
-
-
-	}
-	else {
-		/* Set the CPU into reset */
-		pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE);
-		pm_or_bits_syscon_register(NCP_SYSCON_PWRUP_CPU_RST, cpu_mask);
-
+		cluster_power_up[cluster] = true;
 	}
 
-
 	/*
 	 * Power up the CPU
 	 */
@@ -608,6 +594,22 @@ int pm_cpu_powerup(u32 cpu)
 		goto pm_power_up;
 	}
 
+	timeout = 30;
+
+	/* wait max 10 ms until cpuX is on */
+	while (!pm_cpu_active(cpu)) {
+
+		if (timeout-- == 0)
+			break;
+
+		mdelay(1);
+	}
+
+	if (timeout == 0) {
+		rval =  -ETIMEDOUT;
+		goto pm_power_up;
+	}
+
 	/*
 	 * The key value must be written before the CPU RST can be written.
 	 */
@@ -615,6 +617,12 @@ int pm_cpu_powerup(u32 cpu)
 	pm_clear_bits_syscon_register(NCP_SYSCON_PWRUP_CPU_RST,	cpu_mask);
 
 	/*
+	 * The key value must be written before HOLD CPU can be written.
+	 */
+	pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE);
+	pm_clear_bits_syscon_register(NCP_SYSCON_HOLD_CPU, cpu_mask);
+
+	/*
 	 * Clear the powered down mask
 	 */
 	pm_cpu_powered_down &= ~(1 << cpu);
@@ -622,9 +630,8 @@ int pm_cpu_powerup(u32 cpu)
 	/* Enable the CPU IPI */
 	pm_enable_ipi_interrupts(cpu);
 
-
-
 pm_power_up:
+
 	iounmap(syscon);
 	return rval;
 }
@@ -646,61 +653,19 @@ inline void pm_cpu_logical_powerup(void)
 	"	mrc	p15, 0, %0, c1, c0, 0\n"
 	"	orr	%0, %0, %2\n"
 	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	orr	%0, %0, %3\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
 	  : "=&r" (v)
-	  : "Ir" (CR_C), "Ir" (CR_I)
+	  : "Ir" (CR_C), "Ir" (CR_I), "Ir" (0x40)
 	  : "cc");
 
-	/*
-	 *  Iniitalize the ACTLR2 register (all cores).
-	 */
-
 	asm volatile(
-	"	mrc		p15, 1, %0, c15, c0, 4\n"
-	"	bic	%0, %0, %1\n"
-	"	mcr		p15, 1, %0, c15, c0, 4\n"
+	"       mrc     p15, 1, %0, c9, c0, 2\n"
 	: "=&r" (v)
 	: "Ir" (0x1)
 	: "cc");
 
-	isb();
-	dsb();
-}
-
-inline void pm_cluster_logical_powerup(void)
-{
-	unsigned int v;
-
-	/*
-	 * Initialize the L2CTLR register (primary core in each cluster).
-	 */
-	asm volatile(
-	"	mrc	p15, 1, %0, c9, c0, 2\n"
-	"	orr	%0, %0, %1\n"
-	"	orr	%0, %0, %2\n"
-	"	mcr	p15, 1, %0, c9, c0, 2"
-	  : "=&r" (v)
-	  : "Ir" (0x01), "Ir" (0x1 << 21)
-	  : "cc");
-	isb();
-	dsb();
-
-	/*
-	 * Initialize the L2ACTLR register (primary core in each cluster).
-	 */
-	asm volatile(
-	"	mrc	p15, 1, r0, c15, c0, 0\n"
-	"	orr	%0, %0, %1\n"
-	"	orr	%0, %0, %2\n"
-	"	orr	%0, %0, %3\n"
-	"	orr	%0, %0, %4\n"
-	"	orr	%0, %0, %5\n"
-	"	mcr	p15, 1, %0, c15, c0, 0"
-	  : "=&r" (v)
-	  : "Ir" (0x1 << 3), "Ir" (0x1 << 7), "Ir" (0x1 << 12), "Ir" (0x1 << 13), "Ir" (0x1 << 14)
-	  : "cc");
-	isb();
-	dsb();
-
 }
 
 static int pm_cpu_physical_isolation_and_power_down(int cpu)
@@ -712,7 +677,7 @@ static int pm_cpu_physical_isolation_and_power_down(int cpu)
 	u32 mask = (0x01 << cpu);
 
 	/* Disable the CPU IPI */
-	pm_disable_ipi_interrupts(cpu);
+	pm_clear_bits_syscon_register(ipi_register[cpu], IPI_IRQ_MASK);
 
 	/* Initiate power down of the CPU's HS Rams */
 	pm_clear_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPURAM, mask);
@@ -726,12 +691,12 @@ static int pm_cpu_physical_isolation_and_power_down(int cpu)
 	}
 
 	/* Activate the CPU's isolation clamps */
-	pm_or_bits_syscon_register(NCP_SYSCON_PWR_ISOLATECPU, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWR_ISOLATECPU, mask);
 
 	/* Initiate power down of the CPU logic */
 	pm_clear_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG2, mask);
 
-	udelay(16);
+	udelay(10);
 
 	/* Continue power down of the CPU logic */
 	pm_clear_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG1, mask);
@@ -756,7 +721,7 @@ static int pm_cpu_physical_connection_and_power_up(int cpu)
 	u32 mask = (0x01 << cpu);
 
 	/* Initiate power up of the CPU */
-	pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG1, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG1, mask);
 
 	/* Wait until CPU logic power is compete */
 	success = pm_wait_for_bit_clear_with_timeout(NCP_SYSCON_PWR_NPWRUPCPUSTG1_ACK, cpu);
@@ -767,12 +732,12 @@ static int pm_cpu_physical_connection_and_power_up(int cpu)
 	}
 
 	/* Continue stage 2 power up of the CPU*/
-	pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG2, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG2, mask);
 
-	udelay(16);
+	udelay(20);
 
 	/* Initiate power up of HS Rams */
-	pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPURAM, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPURAM, mask);
 
 	/* Wait until the RAM power up is complete */
 	success = pm_wait_for_bit_clear_with_timeout(NCP_SYSCON_PWR_NPWRUPCPURAM_ACK, cpu);
@@ -785,8 +750,6 @@ static int pm_cpu_physical_connection_and_power_up(int cpu)
 	/* Release the CPU's isolation clamps */
 	pm_clear_bits_syscon_register(NCP_SYSCON_PWR_ISOLATECPU, mask);
 
-	udelay(16);
-
 power_up_cleanup:
 
 
@@ -801,7 +764,7 @@ static void pm_L2_isolation_and_power_down(int cluster)
 	u32 mask = (0x1 << cluster);
 
 	/* Enable the chip select for the cluster */
-	pm_or_bits_syscon_register(NCP_SYSCON_PWR_CHIPSELECTEN, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWR_CHIPSELECTEN, mask);
 
 	/* Disable the hsram */
 	pm_clear_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2HSRAM, mask);
@@ -936,7 +899,7 @@ static int pm_L2_physical_connection_and_power_up(u32 cluster)
 	int rval = 0;
 
 	/* Power up stage 1 */
-	pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2LGCSTG1, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2LGCSTG1, mask);
 
 	/* Wait for the stage 1 power up to complete */
 	success = pm_wait_for_bit_clear_with_timeout(NCP_SYSCON_PWR_NPWRUPL2LGCSTG1_ACK, cluster);
@@ -947,13 +910,13 @@ static int pm_L2_physical_connection_and_power_up(u32 cluster)
 	}
 
 	/* Power on stage 2 */
-	pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2LGCSTG2, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2LGCSTG2, mask);
 
 	/* Set the chip select */
-	pm_or_bits_syscon_register(NCP_SYSCON_PWR_CHIPSELECTEN, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWR_CHIPSELECTEN, mask);
 
 	/* Power up the snoop ram */
-	pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2HSRAM, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2HSRAM, mask);
 
 	/* Wait for the stage 1 power up to complete */
 	success = pm_wait_for_bit_clear_with_timeout(NCP_SYSCON_PWR_NPWRUPL2HSRAM_ACK, cluster);
@@ -997,7 +960,7 @@ static int pm_L2_physical_connection_and_power_up(u32 cluster)
 
 		pm_set_bits_syscon_register(syscon,
 				NCP_SYSCON_PWR_PWRUPL21RAM_PWRUPL2RAM1, RAM_BANK0_MASK);
-	udelay(20);
+		udelay(20);
 		pm_set_bits_syscon_register(syscon,
 				NCP_SYSCON_PWR_PWRUPL21RAM_PWRUPL2RAM1, RAM_BANK1_LS_MASK);
 		pm_set_bits_syscon_register(syscon,
@@ -1095,37 +1058,28 @@ static int pm_L2_logical_powerup(u32 cluster, u32 cpu)
 
 	u32 mask = (0x1 << cluster);
 	int rval = 0;
-	u32 cluster_mask;
-
-	if (cluster == 0)
-		cluster_mask = 0xe;
-	else
-		cluster_mask = 0xf << (cluster * 4);
 
 	/* put the cluster into a cpu hold */
-	pm_or_bits_syscon_register(NCP_SYSCON_RESET_AXIS,
+	pm_set_bits_syscon_register(NCP_SYSCON_RESET_AXIS,
 			cluster_to_poreset[cluster]);
 
-	/*
-	 * The key value has to be written before the CPU RST can be written.
-	 */
-	pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE);
-	pm_or_bits_syscon_register(NCP_SYSCON_PWRUP_CPU_RST, cluster_mask);
+	/* Allow the L2 to be reset */
+	pm_clear_bits_syscon_register(NCP_SYSCON_LRSTDISABLE, mask);
 
 	/* Hold the chip debug cluster */
 	pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE);
-	pm_or_bits_syscon_register(NCP_SYSCON_HOLD_DBG, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_HOLD_DBG, mask);
 
 	/* Hold the L2 cluster */
 	pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE);
-	pm_or_bits_syscon_register(NCP_SYSCON_HOLD_L2, mask);
-
+	pm_set_bits_syscon_register(NCP_SYSCON_HOLD_L2, mask);
 
 	/* Cluster physical power up */
 	rval = pm_L2_physical_connection_and_power_up(cluster);
 	if (rval)
 		goto exit_pm_L2_logical_powerup;
 
+
 	udelay(16);
 
 	/* take the cluster out of a cpu hold */
@@ -1135,7 +1089,7 @@ static int pm_L2_logical_powerup(u32 cluster, u32 cpu)
 	udelay(64);
 
 	/* Enable the system counter */
-	pm_or_bits_syscon_register(NCP_SYSCON_PWR_CSYSREQ_CNT, mask);
+	pm_set_bits_syscon_register(NCP_SYSCON_PWR_CSYSREQ_CNT, mask);
 
 	/* Release the L2 cluster */
 	pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE);
@@ -1153,6 +1107,11 @@ static int pm_L2_logical_powerup(u32 cluster, u32 cpu)
 	/* start L2 */
 	pm_clear_bits_syscon_register(NCP_SYSCON_PWR_ACINACTM, mask);
 
+	/* Disable the L2 reset */
+	pm_set_bits_syscon_register(NCP_SYSCON_LRSTDISABLE, mask);
+
+	udelay(64);
+
 exit_pm_L2_logical_powerup:
 
 	return rval;
diff --git a/arch/arm/mach-axxia/lsi_power_management.h b/arch/arm/mach-axxia/lsi_power_management.h
index ef70af3..4de6bd7 100644
--- a/arch/arm/mach-axxia/lsi_power_management.h
+++ b/arch/arm/mach-axxia/lsi_power_management.h
@@ -150,19 +150,12 @@
 #define		PORESET_CLUSTER2		(0x40000)
 #define		PORESET_CLUSTER3		(0x80000)
 
-/* IPI Masks */
-#define		IPI0_MASK				(0x1111)
-#define		IPI1_MASK				(0x2222)
-#define		IPI2_MASK				(0x4444)
-#define 	IPI3_MASK				(0x8888)
-
 /* SYSCON KEY Value */
 #define VALID_KEY_VALUE			(0xAB)
 
 #define MAX_NUM_CLUSTERS    (4)
 #define CORES_PER_CLUSTER   (4)
 #define MAX_IPI				(19)
-#define MAX_CPUS			(MAX_NUM_CLUSTERS * CORES_PER_CLUSTER)
 
 typedef struct {
 	u32 cpu;
@@ -181,9 +174,9 @@ bool pm_cpu_last_of_cluster(u32 cpu);
 void pm_dump_dickens(void);
 void pm_init_cpu(u32 cpu);
 void pm_cpu_logical_powerup(void);
-void pm_cluster_logical_powerup(void);
 bool pm_cpu_active(u32 cpu);
 void pm_init_syscon(void);
+
 extern bool pm_in_progress[];
 extern bool cluster_power_up[];
 extern u32 pm_cpu_powered_down;
diff --git a/arch/arm/mach-axxia/platsmp.c b/arch/arm/mach-axxia/platsmp.c
index 2804fce..4bbcbed 100644
--- a/arch/arm/mach-axxia/platsmp.c
+++ b/arch/arm/mach-axxia/platsmp.c
@@ -24,13 +24,11 @@
 
 #include "axxia.h"
 #include "lsi_power_management.h"
-#include "axxia_circular_queue.h"
 #include <mach/axxia-gic.h>
 
 extern void axxia_secondary_startup(void);
 extern void axxia_cpu_power_management_gic_control(u32 cpu, bool enable);
 extern void axxia_dist_power_management_gic_control(bool enable);
-extern struct circular_queue_t axxia_circ_q;
 
 #define SYSCON_PHYS_ADDR 0x002010030000ULL
 
@@ -64,7 +62,7 @@ static void __init check_fixup_sev(void __iomem *syscon)
 	pr_info("axxia: Cross-cluster SEV fixup: %s\n", wfe_fixup ? "yes" : "no");
 }
 
-static void  do_fixup_sev(void)
+static void __cpuinit do_fixup_sev(void)
 {
 	u32 tmp;
 
@@ -81,9 +79,10 @@ static void  do_fixup_sev(void)
  * observers, irrespective of whether they're taking part in coherency
  * or not.  This is necessary for the hotplug code to work reliably.
  */
-static void  write_pen_release(int val)
+static void __cpuinit write_pen_release(int val)
 {
 	pen_release = val;
+	/* Memory Barrier */
 	smp_wmb();
 	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
 	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
@@ -91,7 +90,7 @@ static void  write_pen_release(int val)
 
 static DEFINE_RAW_SPINLOCK(boot_lock);
 
-void  axxia_secondary_init(unsigned int cpu)
+void __cpuinit axxia_secondary_init(unsigned int cpu)
 {
 	int phys_cpu;
 	int phys_cluster;
@@ -102,7 +101,7 @@ void  axxia_secondary_init(unsigned int cpu)
 	/*
 	 * Only execute this when powering up a cpu for hotplug.
 	 */
-	if (!pm_in_progress[phys_cpu]) {
+	if (!pm_in_progress[cpu]) {
 		/* Fixup for cross-cluster SEV */
 		do_fixup_sev();
 
@@ -110,16 +109,16 @@ void  axxia_secondary_init(unsigned int cpu)
 	} else {
 
 #ifdef CONFIG_HOTPLUG_CPU_COMPLETE_POWER_DOWN
-		if (cluster_power_up[phys_cluster])
-			pm_cluster_logical_powerup();
 		pm_cpu_logical_powerup();
+		mdelay(16);
 #endif
-		get_cpu();
+
 		axxia_gic_secondary_init();
-		put_cpu();
 
 #ifdef CONFIG_HOTPLUG_CPU_COMPLETE_POWER_DOWN
-		cluster_power_up[phys_cluster] = false;
+		pm_cpu_logical_powerup();
+		if (cluster_power_up[phys_cluster])
+			cluster_power_up[phys_cluster] = false;
 		pm_in_progress[phys_cpu] = false;
 #endif
 	}
@@ -137,14 +136,13 @@ void  axxia_secondary_init(unsigned int cpu)
 	_raw_spin_unlock(&boot_lock);
 }
 
-int  axxia_boot_secondary(unsigned int cpu, struct task_struct *idle)
+int __cpuinit axxia_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 
 	int phys_cpu, cluster;
 	unsigned long timeout;
 	unsigned long powered_down_cpu;
-	u32 i;
-	u32 dummy;
+	int rVal = 0;
 
 
 	/*
@@ -159,7 +157,12 @@ int  axxia_boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 	if (powered_down_cpu & (1 << phys_cpu)) {
 		pm_in_progress[phys_cpu] = true;
-		pm_cpu_powerup(phys_cpu);
+
+		rVal = pm_cpu_powerup(phys_cpu);
+		if (rVal) {
+			_raw_spin_unlock(&boot_lock);
+			return rVal;
+		}
 	}
 
 	/*
@@ -193,14 +196,13 @@ int  axxia_boot_secondary(unsigned int cpu, struct task_struct *idle)
 	/* Wait for so long, then give up if nothing happens ... */
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
+		/* Memory Barrier */
 		smp_rmb();
 
 		if (pen_release == -1)
 			break;
 
-		/* Wait 10 cycles */
-		for (i = 0; i < 10; i++)
-			dummy = i;
+		udelay(10);
 	}
 
 	/*
@@ -292,6 +294,7 @@ static void __init axxia_smp_prepare_cpus(unsigned int max_cpus)
 			else
 				release_virt = ioremap(release_phys, PAGE_SIZE);
 			*release_virt = virt_to_phys(axxia_secondary_startup);
+			/* Memory Barrier */
 			smp_wmb();
 			__cpuc_flush_dcache_area(release_virt, sizeof(u32));
 			if (!is_kmapped)
-- 
1.7.9.5



More information about the linux-yocto mailing list