summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2011-04-03 00:47:27 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:34:21 -0800
commitbc2b6b4c1dd531e9c204ac20ca2b790b5182de4d (patch)
treee30d953ddd03b4e7c8fc875217225dc1a295b9fe
parent120c356d1deff9aa1619afa948d07a90aea6959e (diff)
ARM: tegra: simplify platsmp.c
The synchronization between cpus is handled in the generic ARM code, no need to do it in boot_secondary Change-Id: I2c490823d962c88e177e267c2a46278976925a38 Signed-off-by: Colin Cross <ccross@android.com>
-rw-r--r--arch/arm/mach-tegra/platsmp.c76
1 files changed, 17 insertions, 59 deletions
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 7d2b5d03c1df..ae6067e7f039 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -7,101 +7,59 @@
* Copyright (C) 2009 Palm
* All Rights Reserved
*
+ * Copyright (C) 2010 NVIDIA Corporation
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+
+#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/smp.h>
#include <linux/io.h>
+#include <linux/smp.h>
-#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
-#include <asm/mach-types.h>
#include <asm/smp_scu.h>
#include <mach/iomap.h>
-extern void tegra_secondary_startup(void);
-
-static DEFINE_SPINLOCK(boot_lock);
-static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
-
#define EVP_CPU_RESET_VECTOR \
(IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
#define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \
(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c)
+#define CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET \
+ (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x340)
#define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \
(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344)
+extern void tegra_secondary_startup(void);
+
+static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
+
void __cpuinit platform_secondary_init(unsigned int cpu)
{
- /*
- * if any interrupts are already enabled for the primary
- * core (e.g. timer irq), then they will not have been enabled
- * for us: do so
- */
gic_secondary_init(0);
-
- /*
- * Synchronise with the boot thread.
- */
- spin_lock(&boot_lock);
- spin_unlock(&boot_lock);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
- unsigned long old_boot_vector;
- unsigned long boot_vector;
- unsigned long timeout;
u32 reg;
- /*
- * set synchronisation state between this boot processor
- * and the secondary one
- */
- spin_lock(&boot_lock);
-
+ smp_wmb();
/* set the reset vector to point to the secondary_startup routine */
+ writel(virt_to_phys(tegra_secondary_startup), EVP_CPU_RESET_VECTOR);
- boot_vector = virt_to_phys(tegra_secondary_startup);
- old_boot_vector = readl(EVP_CPU_RESET_VECTOR);
- writel(boot_vector, EVP_CPU_RESET_VECTOR);
-
- /* enable cpu clock on cpu1 */
+ /* enable cpu clock on cpu */
reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
- writel(reg & ~(1<<9), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+ writel(reg & ~(1 << (8 + cpu)), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
- reg = (1<<13) | (1<<9) | (1<<5) | (1<<1);
+ reg = 0x1111 << cpu;
writel(reg, CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
- smp_wmb();
- flush_cache_all();
-
/* unhalt the cpu */
- writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x14);
-
- timeout = jiffies + (1 * HZ);
- while (time_before(jiffies, timeout)) {
- if (readl(EVP_CPU_RESET_VECTOR) != boot_vector)
- break;
- udelay(10);
- }
-
- /* put the old boot vector back */
- writel(old_boot_vector, EVP_CPU_RESET_VECTOR);
-
- /*
- * now the secondary core is starting up let it run its
- * calibrations, then wait for it to finish
- */
- spin_unlock(&boot_lock);
+ writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x14 + 0x8 * (cpu - 1));
return 0;
}