All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 0/6] ARM: tegra: add CPU hotplug support
@ 2012-08-15  9:22 ` Joseph Lo
  0 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: Stephen Warren, Olof Johansson, Colin Cross
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Joseph Lo

This patch set adds CPU hotplug support for Tegra20 and Tegra30 SoCs.

The first 3 patches make the CPU clock and reset control be a module and
the abstraction APIs for TegraXX SoCs. And clean up some codes for later
usage. Then add CPU hotplug support for Tegra20 and Tegra30.

Verified on Seaboard(Tegra20) and Cardhu(Tegra30)

V2:
* add one more patch for enable HOTPLUG_CPU [6/6]
* move all the SoC specific CPU shutdown code into platform_cpu_die [4/6]

Joseph Lo (6):
  ARM: tegra: introduce tegra_cpu_car_ops structures
  ARM: tegra: replace the CPU CAR access code by tegra_cpu_car_ops
  ARM: tegra: clean up the common assembly macros into sleep.h
  ARM: tegra30: add CPU hotplug support
  ARM: tegra20: add CPU hotplug support
  ARM: tegra: defconfig: enable HOTPLUG_CPU

 arch/arm/configs/tegra_defconfig          |    1 +
 arch/arm/mach-tegra/Makefile              |    2 +
 arch/arm/mach-tegra/clock.c               |    4 +
 arch/arm/mach-tegra/common.c              |    3 +
 arch/arm/mach-tegra/headsmp.S             |    6 +-
 arch/arm/mach-tegra/hotplug.c             |  118 ++++++++---------------------
 arch/arm/mach-tegra/platsmp.c             |   29 +------
 arch/arm/mach-tegra/sleep-t20.S           |   82 ++++++++++++++++++++
 arch/arm/mach-tegra/sleep-t30.S           |  107 ++++++++++++++++++++++++++
 arch/arm/mach-tegra/sleep.S               |   33 +--------
 arch/arm/mach-tegra/sleep.h               |   80 +++++++++++++++++++
 arch/arm/mach-tegra/tegra20_clocks.c      |   70 +++++++++++++++++
 arch/arm/mach-tegra/tegra20_clocks_data.c |    2 +
 arch/arm/mach-tegra/tegra30_clocks.c      |   72 +++++++++++++++++
 arch/arm/mach-tegra/tegra30_clocks_data.c |    3 +
 arch/arm/mach-tegra/tegra_cpu_car.h       |   87 +++++++++++++++++++++
 16 files changed, 552 insertions(+), 147 deletions(-)
 create mode 100644 arch/arm/mach-tegra/sleep-t20.S
 create mode 100644 arch/arm/mach-tegra/sleep-t30.S
 create mode 100644 arch/arm/mach-tegra/sleep.h
 create mode 100644 arch/arm/mach-tegra/tegra_cpu_car.h

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH V2 0/6] ARM: tegra: add CPU hotplug support
@ 2012-08-15  9:22 ` Joseph Lo
  0 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: linux-arm-kernel

This patch set adds CPU hotplug support for Tegra20 and Tegra30 SoCs.

The first 3 patches make the CPU clock and reset control be a module and
the abstraction APIs for TegraXX SoCs. And clean up some codes for later
usage. Then add CPU hotplug support for Tegra20 and Tegra30.

Verified on Seaboard(Tegra20) and Cardhu(Tegra30)

V2:
* add one more patch for enable HOTPLUG_CPU [6/6]
* move all the SoC specific CPU shutdown code into platform_cpu_die [4/6]

Joseph Lo (6):
  ARM: tegra: introduce tegra_cpu_car_ops structures
  ARM: tegra: replace the CPU CAR access code by tegra_cpu_car_ops
  ARM: tegra: clean up the common assembly macros into sleep.h
  ARM: tegra30: add CPU hotplug support
  ARM: tegra20: add CPU hotplug support
  ARM: tegra: defconfig: enable HOTPLUG_CPU

 arch/arm/configs/tegra_defconfig          |    1 +
 arch/arm/mach-tegra/Makefile              |    2 +
 arch/arm/mach-tegra/clock.c               |    4 +
 arch/arm/mach-tegra/common.c              |    3 +
 arch/arm/mach-tegra/headsmp.S             |    6 +-
 arch/arm/mach-tegra/hotplug.c             |  118 ++++++++---------------------
 arch/arm/mach-tegra/platsmp.c             |   29 +------
 arch/arm/mach-tegra/sleep-t20.S           |   82 ++++++++++++++++++++
 arch/arm/mach-tegra/sleep-t30.S           |  107 ++++++++++++++++++++++++++
 arch/arm/mach-tegra/sleep.S               |   33 +--------
 arch/arm/mach-tegra/sleep.h               |   80 +++++++++++++++++++
 arch/arm/mach-tegra/tegra20_clocks.c      |   70 +++++++++++++++++
 arch/arm/mach-tegra/tegra20_clocks_data.c |    2 +
 arch/arm/mach-tegra/tegra30_clocks.c      |   72 +++++++++++++++++
 arch/arm/mach-tegra/tegra30_clocks_data.c |    3 +
 arch/arm/mach-tegra/tegra_cpu_car.h       |   87 +++++++++++++++++++++
 16 files changed, 552 insertions(+), 147 deletions(-)
 create mode 100644 arch/arm/mach-tegra/sleep-t20.S
 create mode 100644 arch/arm/mach-tegra/sleep-t30.S
 create mode 100644 arch/arm/mach-tegra/sleep.h
 create mode 100644 arch/arm/mach-tegra/tegra_cpu_car.h

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH V2 1/6] ARM: tegra: introduce tegra_cpu_car_ops structures
  2012-08-15  9:22 ` Joseph Lo
@ 2012-08-15  9:22     ` Joseph Lo
  -1 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: Stephen Warren, Olof Johansson, Colin Cross
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Joseph Lo

The tegra_cpu_car_ops provide the interface for CPU to control
it's clock gating and reset status. The other drivers should use
this for CPU control. And should not directly access CAR registers
to control CPU.

Signed-off-by: Joseph Lo <josephl-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 arch/arm/mach-tegra/clock.c               |    4 +
 arch/arm/mach-tegra/tegra20_clocks.c      |   70 +++++++++++++++++++++++
 arch/arm/mach-tegra/tegra20_clocks_data.c |    2 +
 arch/arm/mach-tegra/tegra30_clocks.c      |   72 ++++++++++++++++++++++++
 arch/arm/mach-tegra/tegra30_clocks_data.c |    3 +
 arch/arm/mach-tegra/tegra_cpu_car.h       |   87 +++++++++++++++++++++++++++++
 6 files changed, 238 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-tegra/tegra_cpu_car.h

diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 632133f..fd82085 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -31,6 +31,10 @@
 
 #include "board.h"
 #include "clock.h"
+#include "tegra_cpu_car.h"
+
+/* Global data of Tegra CPU CAR ops */
+struct tegra_cpu_car_ops *tegra_cpu_car_ops;
 
 /*
  * Locking:
diff --git a/arch/arm/mach-tegra/tegra20_clocks.c b/arch/arm/mach-tegra/tegra20_clocks.c
index a1e0f8a..b073396 100644
--- a/arch/arm/mach-tegra/tegra20_clocks.c
+++ b/arch/arm/mach-tegra/tegra20_clocks.c
@@ -33,6 +33,7 @@
 #include "clock.h"
 #include "fuse.h"
 #include "tegra2_emc.h"
+#include "tegra_cpu_car.h"
 
 #define RST_DEVICES			0x004
 #define RST_DEVICES_SET			0x300
@@ -152,6 +153,14 @@
 #define PMC_BLINK_TIMER_DATA_OFF_SHIFT	16
 #define PMC_BLINK_TIMER_DATA_OFF_MASK	0xffff
 
+/* Tegra CPU clock and reset control regs */
+#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX		0x4c
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET	0x340
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR	0x344
+
+#define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
+#define CPU_RESET(cpu)	(0x1111ul << (cpu))
+
 static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
 static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
 
@@ -1524,3 +1533,64 @@ struct clk_ops tegra_cdev_clk_ops = {
 	.disable = tegra20_cdev_clk_disable,
 	.recalc_rate = tegra20_cdev_recalc_rate,
 };
+
+/* Tegra20 CPU clock and reset control functions */
+static void tegra20_wait_cpu_in_reset(u32 cpu)
+{
+	unsigned int reg;
+
+	do {
+		reg = readl(reg_clk_base +
+			    TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+		cpu_relax();
+	} while (!(reg & (1 << cpu)));	/* check CPU been reset or not */
+
+	return;
+}
+
+static void tegra20_put_cpu_in_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+	dmb();
+}
+
+static void tegra20_cpu_out_of_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+	wmb();
+}
+
+static void tegra20_enable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg & ~CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	barrier();
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+static void tegra20_disable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg | CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+static struct tegra_cpu_car_ops tegra20_cpu_car_ops = {
+	.wait_for_reset	= tegra20_wait_cpu_in_reset,
+	.put_in_reset	= tegra20_put_cpu_in_reset,
+	.out_of_reset	= tegra20_cpu_out_of_reset,
+	.enable_clock	= tegra20_enable_cpu_clock,
+	.disable_clock	= tegra20_disable_cpu_clock,
+};
+
+void __init tegra20_cpu_car_ops_init(void)
+{
+	tegra_cpu_car_ops = &tegra20_cpu_car_ops;
+}
diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c
index b5c518e..56552f9 100644
--- a/arch/arm/mach-tegra/tegra20_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra20_clocks_data.c
@@ -34,6 +34,7 @@
 #include "fuse.h"
 #include "tegra2_emc.h"
 #include "tegra20_clocks.h"
+#include "tegra_cpu_car.h"
 
 /* Clock definitions */
 
@@ -1110,4 +1111,5 @@ void __init tegra2_init_clocks(void)
 	}
 
 	init_audio_sync_clock_mux();
+	tegra20_cpu_car_ops_init();
 }
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c
index a9fa8ea..b2d0864 100644
--- a/arch/arm/mach-tegra/tegra30_clocks.c
+++ b/arch/arm/mach-tegra/tegra30_clocks.c
@@ -35,6 +35,7 @@
 
 #include "clock.h"
 #include "fuse.h"
+#include "tegra_cpu_car.h"
 
 #define USE_PLL_LOCK_BITS 0
 
@@ -299,6 +300,16 @@
 /* FIXME: recommended safety delay after lock is detected */
 #define PLL_POST_LOCK_DELAY		100
 
+/* Tegra CPU clock and reset control regs */
+#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX		0x4c
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET	0x340
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR	0x344
+#define TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR	0x34c
+#define TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS	0x470
+
+#define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
+#define CPU_RESET(cpu)	(0x1111ul << (cpu))
+
 /**
 * Structure defining the fields for USB UTMI clocks Parameters.
 */
@@ -2221,3 +2232,64 @@ struct clk_ops tegra_cml_clk_ops = {
 struct clk_ops tegra_pciex_clk_ops = {
 	.recalc_rate = tegra30_clk_fixed_recalc_rate,
 };
+
+/* Tegra30 CPU clock and reset control functions */
+static void tegra30_wait_cpu_in_reset(u32 cpu)
+{
+	unsigned int reg;
+
+	do {
+		reg = readl(reg_clk_base +
+			    TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
+		cpu_relax();
+	} while (!(reg & (1 << cpu)));	/* check CPU been reset or not */
+
+	return;
+}
+
+static void tegra30_put_cpu_in_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+	dmb();
+}
+
+static void tegra30_cpu_out_of_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+	wmb();
+}
+
+static void tegra30_enable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	writel(CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+	reg = readl(reg_clk_base +
+		    TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+}
+
+static void tegra30_disable_cpu_clock(u32 cpu)
+{
+
+	unsigned int reg;
+
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg | CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
+	.wait_for_reset	= tegra30_wait_cpu_in_reset,
+	.put_in_reset	= tegra30_put_cpu_in_reset,
+	.out_of_reset	= tegra30_cpu_out_of_reset,
+	.enable_clock	= tegra30_enable_cpu_clock,
+	.disable_clock	= tegra30_disable_cpu_clock,
+};
+
+void __init tegra30_cpu_car_ops_init(void)
+{
+	tegra_cpu_car_ops = &tegra30_cpu_car_ops;
+}
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c
index c924240..8252f88 100644
--- a/arch/arm/mach-tegra/tegra30_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra30_clocks_data.c
@@ -32,6 +32,7 @@
 #include "clock.h"
 #include "fuse.h"
 #include "tegra30_clocks.h"
+#include "tegra_cpu_car.h"
 
 #define DEFINE_CLK_TEGRA(_name, _rate, _ops, _flags,		\
 		   _parent_names, _parents, _parent)		\
@@ -1367,4 +1368,6 @@ void __init tegra30_init_clocks(void)
 
 	for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++)
 		tegra30_init_one_clock(tegra_clk_out_list[i]);
+
+	tegra30_cpu_car_ops_init();
 }
diff --git a/arch/arm/mach-tegra/tegra_cpu_car.h b/arch/arm/mach-tegra/tegra_cpu_car.h
new file mode 100644
index 0000000..30d063a
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_cpu_car.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MACH_TEGRA_CPU_CAR_H
+#define __MACH_TEGRA_CPU_CAR_H
+
+/*
+ * Tegra CPU clock and reset control ops
+ *
+ * wait_for_reset:
+ *	keep waiting until the CPU in reset state
+ * put_in_reset:
+ *	put the CPU in reset state
+ * out_of_reset:
+ *	release the CPU from reset state
+ * enable_clock:
+ *	CPU clock un-gate
+ * disable_clock:
+ *	CPU clock gate
+ */
+struct tegra_cpu_car_ops {
+	void (*wait_for_reset)(u32 cpu);
+	void (*put_in_reset)(u32 cpu);
+	void (*out_of_reset)(u32 cpu);
+	void (*enable_clock)(u32 cpu);
+	void (*disable_clock)(u32 cpu);
+};
+
+extern struct tegra_cpu_car_ops *tegra_cpu_car_ops;
+
+static inline void tegra_wait_cpu_in_reset(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->wait_for_reset))
+		return;
+
+	tegra_cpu_car_ops->wait_for_reset(cpu);
+}
+
+static inline void tegra_put_cpu_in_reset(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->put_in_reset))
+		return;
+
+	tegra_cpu_car_ops->put_in_reset(cpu);
+}
+
+static inline void tegra_cpu_out_of_reset(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->out_of_reset))
+		return;
+
+	tegra_cpu_car_ops->out_of_reset(cpu);
+}
+
+static inline void tegra_enable_cpu_clock(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->enable_clock))
+		return;
+
+	tegra_cpu_car_ops->enable_clock(cpu);
+}
+
+static inline void tegra_disable_cpu_clock(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->disable_clock))
+		return;
+
+	tegra_cpu_car_ops->disable_clock(cpu);
+}
+
+void tegra20_cpu_car_ops_init(void);
+void tegra30_cpu_car_ops_init(void);
+
+#endif /* __MACH_TEGRA_CPU_CAR_H */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 1/6] ARM: tegra: introduce tegra_cpu_car_ops structures
@ 2012-08-15  9:22     ` Joseph Lo
  0 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: linux-arm-kernel

The tegra_cpu_car_ops provide the interface for CPU to control
it's clock gating and reset status. The other drivers should use
this for CPU control. And should not directly access CAR registers
to control CPU.

Signed-off-by: Joseph Lo <josephl@nvidia.com>
---
 arch/arm/mach-tegra/clock.c               |    4 +
 arch/arm/mach-tegra/tegra20_clocks.c      |   70 +++++++++++++++++++++++
 arch/arm/mach-tegra/tegra20_clocks_data.c |    2 +
 arch/arm/mach-tegra/tegra30_clocks.c      |   72 ++++++++++++++++++++++++
 arch/arm/mach-tegra/tegra30_clocks_data.c |    3 +
 arch/arm/mach-tegra/tegra_cpu_car.h       |   87 +++++++++++++++++++++++++++++
 6 files changed, 238 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-tegra/tegra_cpu_car.h

diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 632133f..fd82085 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -31,6 +31,10 @@
 
 #include "board.h"
 #include "clock.h"
+#include "tegra_cpu_car.h"
+
+/* Global data of Tegra CPU CAR ops */
+struct tegra_cpu_car_ops *tegra_cpu_car_ops;
 
 /*
  * Locking:
diff --git a/arch/arm/mach-tegra/tegra20_clocks.c b/arch/arm/mach-tegra/tegra20_clocks.c
index a1e0f8a..b073396 100644
--- a/arch/arm/mach-tegra/tegra20_clocks.c
+++ b/arch/arm/mach-tegra/tegra20_clocks.c
@@ -33,6 +33,7 @@
 #include "clock.h"
 #include "fuse.h"
 #include "tegra2_emc.h"
+#include "tegra_cpu_car.h"
 
 #define RST_DEVICES			0x004
 #define RST_DEVICES_SET			0x300
@@ -152,6 +153,14 @@
 #define PMC_BLINK_TIMER_DATA_OFF_SHIFT	16
 #define PMC_BLINK_TIMER_DATA_OFF_MASK	0xffff
 
+/* Tegra CPU clock and reset control regs */
+#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX		0x4c
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET	0x340
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR	0x344
+
+#define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
+#define CPU_RESET(cpu)	(0x1111ul << (cpu))
+
 static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
 static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
 
@@ -1524,3 +1533,64 @@ struct clk_ops tegra_cdev_clk_ops = {
 	.disable = tegra20_cdev_clk_disable,
 	.recalc_rate = tegra20_cdev_recalc_rate,
 };
+
+/* Tegra20 CPU clock and reset control functions */
+static void tegra20_wait_cpu_in_reset(u32 cpu)
+{
+	unsigned int reg;
+
+	do {
+		reg = readl(reg_clk_base +
+			    TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+		cpu_relax();
+	} while (!(reg & (1 << cpu)));	/* check CPU been reset or not */
+
+	return;
+}
+
+static void tegra20_put_cpu_in_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+	dmb();
+}
+
+static void tegra20_cpu_out_of_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+	wmb();
+}
+
+static void tegra20_enable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg & ~CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	barrier();
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+static void tegra20_disable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg | CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+static struct tegra_cpu_car_ops tegra20_cpu_car_ops = {
+	.wait_for_reset	= tegra20_wait_cpu_in_reset,
+	.put_in_reset	= tegra20_put_cpu_in_reset,
+	.out_of_reset	= tegra20_cpu_out_of_reset,
+	.enable_clock	= tegra20_enable_cpu_clock,
+	.disable_clock	= tegra20_disable_cpu_clock,
+};
+
+void __init tegra20_cpu_car_ops_init(void)
+{
+	tegra_cpu_car_ops = &tegra20_cpu_car_ops;
+}
diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c
index b5c518e..56552f9 100644
--- a/arch/arm/mach-tegra/tegra20_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra20_clocks_data.c
@@ -34,6 +34,7 @@
 #include "fuse.h"
 #include "tegra2_emc.h"
 #include "tegra20_clocks.h"
+#include "tegra_cpu_car.h"
 
 /* Clock definitions */
 
@@ -1110,4 +1111,5 @@ void __init tegra2_init_clocks(void)
 	}
 
 	init_audio_sync_clock_mux();
+	tegra20_cpu_car_ops_init();
 }
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c
index a9fa8ea..b2d0864 100644
--- a/arch/arm/mach-tegra/tegra30_clocks.c
+++ b/arch/arm/mach-tegra/tegra30_clocks.c
@@ -35,6 +35,7 @@
 
 #include "clock.h"
 #include "fuse.h"
+#include "tegra_cpu_car.h"
 
 #define USE_PLL_LOCK_BITS 0
 
@@ -299,6 +300,16 @@
 /* FIXME: recommended safety delay after lock is detected */
 #define PLL_POST_LOCK_DELAY		100
 
+/* Tegra CPU clock and reset control regs */
+#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX		0x4c
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET	0x340
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR	0x344
+#define TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR	0x34c
+#define TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS	0x470
+
+#define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
+#define CPU_RESET(cpu)	(0x1111ul << (cpu))
+
 /**
 * Structure defining the fields for USB UTMI clocks Parameters.
 */
@@ -2221,3 +2232,64 @@ struct clk_ops tegra_cml_clk_ops = {
 struct clk_ops tegra_pciex_clk_ops = {
 	.recalc_rate = tegra30_clk_fixed_recalc_rate,
 };
+
+/* Tegra30 CPU clock and reset control functions */
+static void tegra30_wait_cpu_in_reset(u32 cpu)
+{
+	unsigned int reg;
+
+	do {
+		reg = readl(reg_clk_base +
+			    TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
+		cpu_relax();
+	} while (!(reg & (1 << cpu)));	/* check CPU been reset or not */
+
+	return;
+}
+
+static void tegra30_put_cpu_in_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+	dmb();
+}
+
+static void tegra30_cpu_out_of_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+	wmb();
+}
+
+static void tegra30_enable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	writel(CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+	reg = readl(reg_clk_base +
+		    TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+}
+
+static void tegra30_disable_cpu_clock(u32 cpu)
+{
+
+	unsigned int reg;
+
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg | CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
+	.wait_for_reset	= tegra30_wait_cpu_in_reset,
+	.put_in_reset	= tegra30_put_cpu_in_reset,
+	.out_of_reset	= tegra30_cpu_out_of_reset,
+	.enable_clock	= tegra30_enable_cpu_clock,
+	.disable_clock	= tegra30_disable_cpu_clock,
+};
+
+void __init tegra30_cpu_car_ops_init(void)
+{
+	tegra_cpu_car_ops = &tegra30_cpu_car_ops;
+}
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c
index c924240..8252f88 100644
--- a/arch/arm/mach-tegra/tegra30_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra30_clocks_data.c
@@ -32,6 +32,7 @@
 #include "clock.h"
 #include "fuse.h"
 #include "tegra30_clocks.h"
+#include "tegra_cpu_car.h"
 
 #define DEFINE_CLK_TEGRA(_name, _rate, _ops, _flags,		\
 		   _parent_names, _parents, _parent)		\
@@ -1367,4 +1368,6 @@ void __init tegra30_init_clocks(void)
 
 	for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++)
 		tegra30_init_one_clock(tegra_clk_out_list[i]);
+
+	tegra30_cpu_car_ops_init();
 }
diff --git a/arch/arm/mach-tegra/tegra_cpu_car.h b/arch/arm/mach-tegra/tegra_cpu_car.h
new file mode 100644
index 0000000..30d063a
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_cpu_car.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MACH_TEGRA_CPU_CAR_H
+#define __MACH_TEGRA_CPU_CAR_H
+
+/*
+ * Tegra CPU clock and reset control ops
+ *
+ * wait_for_reset:
+ *	keep waiting until the CPU in reset state
+ * put_in_reset:
+ *	put the CPU in reset state
+ * out_of_reset:
+ *	release the CPU from reset state
+ * enable_clock:
+ *	CPU clock un-gate
+ * disable_clock:
+ *	CPU clock gate
+ */
+struct tegra_cpu_car_ops {
+	void (*wait_for_reset)(u32 cpu);
+	void (*put_in_reset)(u32 cpu);
+	void (*out_of_reset)(u32 cpu);
+	void (*enable_clock)(u32 cpu);
+	void (*disable_clock)(u32 cpu);
+};
+
+extern struct tegra_cpu_car_ops *tegra_cpu_car_ops;
+
+static inline void tegra_wait_cpu_in_reset(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->wait_for_reset))
+		return;
+
+	tegra_cpu_car_ops->wait_for_reset(cpu);
+}
+
+static inline void tegra_put_cpu_in_reset(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->put_in_reset))
+		return;
+
+	tegra_cpu_car_ops->put_in_reset(cpu);
+}
+
+static inline void tegra_cpu_out_of_reset(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->out_of_reset))
+		return;
+
+	tegra_cpu_car_ops->out_of_reset(cpu);
+}
+
+static inline void tegra_enable_cpu_clock(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->enable_clock))
+		return;
+
+	tegra_cpu_car_ops->enable_clock(cpu);
+}
+
+static inline void tegra_disable_cpu_clock(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->disable_clock))
+		return;
+
+	tegra_cpu_car_ops->disable_clock(cpu);
+}
+
+void tegra20_cpu_car_ops_init(void);
+void tegra30_cpu_car_ops_init(void);
+
+#endif /* __MACH_TEGRA_CPU_CAR_H */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 2/6] ARM: tegra: replace the CPU CAR access code by tegra_cpu_car_ops
  2012-08-15  9:22 ` Joseph Lo
@ 2012-08-15  9:22     ` Joseph Lo
  -1 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: Stephen Warren, Olof Johansson, Colin Cross
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Joseph Lo

Replacing the code that directly access to CAR registers with
tegra_cpu_car_ops. This ops hides CPU CAR access inside and
provides control interface for it.

Signed-off-by: Joseph Lo <josephl-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 arch/arm/mach-tegra/platsmp.c |   29 +++++------------------------
 1 files changed, 5 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 1a208db..96ed171 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -31,6 +31,7 @@
 #include "fuse.h"
 #include "flowctrl.h"
 #include "reset.h"
+#include "tegra_cpu_car.h"
 
 extern void tegra_secondary_startup(void);
 
@@ -38,17 +39,6 @@ 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)
-#define CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR \
-	(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x34c)
-
-#define CPU_CLOCK(cpu)	(0x1<<(8+cpu))
-#define CPU_RESET(cpu)	(0x1111ul<<(cpu))
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
@@ -63,13 +53,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 
 static int tegra20_power_up_cpu(unsigned int cpu)
 {
-	u32 reg;
-
 	/* Enable the CPU clock. */
-	reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-	writel(reg & ~CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-	barrier();
-	reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	tegra_enable_cpu_clock(cpu);
 
 	/* Clear flow controller CSR. */
 	flowctrl_write_cpu_csr(cpu, 0);
@@ -79,7 +64,6 @@ static int tegra20_power_up_cpu(unsigned int cpu)
 
 static int tegra30_power_up_cpu(unsigned int cpu)
 {
-	u32 reg;
 	int ret, pwrgateid;
 	unsigned long timeout;
 
@@ -103,8 +87,7 @@ static int tegra30_power_up_cpu(unsigned int cpu)
 	}
 
 	/* CPU partition is powered. Enable the CPU clock. */
-	writel(CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
-	reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+	tegra_enable_cpu_clock(cpu);
 	udelay(10);
 
 	/* Remove I/O clamps. */
@@ -128,8 +111,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 * via the flow controller). This will have no effect on first boot
 	 * of the CPU since it should already be in reset.
 	 */
-	writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
-	dmb();
+	tegra_put_cpu_in_reset(cpu);
 
 	/*
 	 * Unhalt the CPU. If the flow controller was used to power-gate the
@@ -155,8 +137,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 		goto done;
 
 	/* Take the CPU out of reset. */
-	writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
-	wmb();
+	tegra_cpu_out_of_reset(cpu);
 done:
 	return status;
 }
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 2/6] ARM: tegra: replace the CPU CAR access code by tegra_cpu_car_ops
@ 2012-08-15  9:22     ` Joseph Lo
  0 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: linux-arm-kernel

Replacing the code that directly access to CAR registers with
tegra_cpu_car_ops. This ops hides CPU CAR access inside and
provides control interface for it.

Signed-off-by: Joseph Lo <josephl@nvidia.com>
---
 arch/arm/mach-tegra/platsmp.c |   29 +++++------------------------
 1 files changed, 5 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 1a208db..96ed171 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -31,6 +31,7 @@
 #include "fuse.h"
 #include "flowctrl.h"
 #include "reset.h"
+#include "tegra_cpu_car.h"
 
 extern void tegra_secondary_startup(void);
 
@@ -38,17 +39,6 @@ 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)
-#define CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR \
-	(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x34c)
-
-#define CPU_CLOCK(cpu)	(0x1<<(8+cpu))
-#define CPU_RESET(cpu)	(0x1111ul<<(cpu))
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
@@ -63,13 +53,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 
 static int tegra20_power_up_cpu(unsigned int cpu)
 {
-	u32 reg;
-
 	/* Enable the CPU clock. */
-	reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-	writel(reg & ~CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-	barrier();
-	reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	tegra_enable_cpu_clock(cpu);
 
 	/* Clear flow controller CSR. */
 	flowctrl_write_cpu_csr(cpu, 0);
@@ -79,7 +64,6 @@ static int tegra20_power_up_cpu(unsigned int cpu)
 
 static int tegra30_power_up_cpu(unsigned int cpu)
 {
-	u32 reg;
 	int ret, pwrgateid;
 	unsigned long timeout;
 
@@ -103,8 +87,7 @@ static int tegra30_power_up_cpu(unsigned int cpu)
 	}
 
 	/* CPU partition is powered. Enable the CPU clock. */
-	writel(CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
-	reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+	tegra_enable_cpu_clock(cpu);
 	udelay(10);
 
 	/* Remove I/O clamps. */
@@ -128,8 +111,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 * via the flow controller). This will have no effect on first boot
 	 * of the CPU since it should already be in reset.
 	 */
-	writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
-	dmb();
+	tegra_put_cpu_in_reset(cpu);
 
 	/*
 	 * Unhalt the CPU. If the flow controller was used to power-gate the
@@ -155,8 +137,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 		goto done;
 
 	/* Take the CPU out of reset. */
-	writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
-	wmb();
+	tegra_cpu_out_of_reset(cpu);
 done:
 	return status;
 }
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 3/6] ARM: tegra: clean up the common assembly macros into sleep.h
  2012-08-15  9:22 ` Joseph Lo
@ 2012-08-15  9:22     ` Joseph Lo
  -1 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: Stephen Warren, Olof Johansson, Colin Cross
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Joseph Lo

There are some common macros for Tegra low-level assembly code. Clean
up them into one header file and move the definitions that will be
re-used into it as well.

Signed-off-by: Joseph Lo <josephl-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 arch/arm/mach-tegra/headsmp.S |    6 +---
 arch/arm/mach-tegra/sleep.S   |   33 +-----------------------
 arch/arm/mach-tegra/sleep.h   |   56 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 37 deletions(-)
 create mode 100644 arch/arm/mach-tegra/sleep.h

diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index fef9c2c..6addc78 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -7,17 +7,13 @@
 
 #include "flowctrl.h"
 #include "reset.h"
+#include "sleep.h"
 
 #define APB_MISC_GP_HIDREV	0x804
 #define PMC_SCRATCH41	0x140
 
 #define RESET_DATA(x)	((TEGRA_RESET_##x)*4)
 
-	.macro mov32, reg, val
-	movw	\reg, #:lower16:\val
-	movt	\reg, #:upper16:\val
-	.endm
-
         .section ".text.head", "ax"
 	__CPUINIT
 
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index d29b156..ea81554 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -29,36 +29,5 @@
 #include <mach/iomap.h>
 
 #include "flowctrl.h"
+#include "sleep.h"
 
-#define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
-					+ IO_PPSB_VIRT)
-
-/* returns the offset of the flow controller halt register for a cpu */
-.macro cpu_to_halt_reg rd, rcpu
-	cmp	\rcpu, #0
-	subne	\rd, \rcpu, #1
-	movne	\rd, \rd, lsl #3
-	addne	\rd, \rd, #0x14
-	moveq	\rd, #0
-.endm
-
-/* returns the offset of the flow controller csr register for a cpu */
-.macro cpu_to_csr_reg rd, rcpu
-	cmp	\rcpu, #0
-	subne	\rd, \rcpu, #1
-	movne	\rd, \rd, lsl #3
-	addne	\rd, \rd, #0x18
-	moveq	\rd, #8
-.endm
-
-/* returns the ID of the current processor */
-.macro cpu_id, rd
-	mrc	p15, 0, \rd, c0, c0, 5
-	and	\rd, \rd, #0xF
-.endm
-
-/* loads a 32-bit value into a register without a data access */
-.macro mov32, reg, val
-	movw	\reg, #:lower16:\val
-	movt	\reg, #:upper16:\val
-.endm
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
new file mode 100644
index 0000000..d0c7a8b
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MACH_TEGRA_SLEEP_H
+#define __MACH_TEGRA_SLEEP_H
+
+#include <mach/iomap.h>
+
+#define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
+					+ IO_PPSB_VIRT)
+
+#ifdef __ASSEMBLY__
+/* returns the offset of the flow controller halt register for a cpu */
+.macro cpu_to_halt_reg rd, rcpu
+	cmp	\rcpu, #0
+	subne	\rd, \rcpu, #1
+	movne	\rd, \rd, lsl #3
+	addne	\rd, \rd, #0x14
+	moveq	\rd, #0
+.endm
+
+/* returns the offset of the flow controller csr register for a cpu */
+.macro cpu_to_csr_reg rd, rcpu
+	cmp	\rcpu, #0
+	subne	\rd, \rcpu, #1
+	movne	\rd, \rd, lsl #3
+	addne	\rd, \rd, #0x18
+	moveq	\rd, #8
+.endm
+
+/* returns the ID of the current processor */
+.macro cpu_id, rd
+	mrc	p15, 0, \rd, c0, c0, 5
+	and	\rd, \rd, #0xF
+.endm
+
+/* loads a 32-bit value into a register without a data access */
+.macro mov32, reg, val
+	movw	\reg, #:lower16:\val
+	movt	\reg, #:upper16:\val
+.endm
+#endif
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 3/6] ARM: tegra: clean up the common assembly macros into sleep.h
@ 2012-08-15  9:22     ` Joseph Lo
  0 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: linux-arm-kernel

There are some common macros for Tegra low-level assembly code. Clean
up them into one header file and move the definitions that will be
re-used into it as well.

Signed-off-by: Joseph Lo <josephl@nvidia.com>
---
 arch/arm/mach-tegra/headsmp.S |    6 +---
 arch/arm/mach-tegra/sleep.S   |   33 +-----------------------
 arch/arm/mach-tegra/sleep.h   |   56 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 37 deletions(-)
 create mode 100644 arch/arm/mach-tegra/sleep.h

diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index fef9c2c..6addc78 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -7,17 +7,13 @@
 
 #include "flowctrl.h"
 #include "reset.h"
+#include "sleep.h"
 
 #define APB_MISC_GP_HIDREV	0x804
 #define PMC_SCRATCH41	0x140
 
 #define RESET_DATA(x)	((TEGRA_RESET_##x)*4)
 
-	.macro mov32, reg, val
-	movw	\reg, #:lower16:\val
-	movt	\reg, #:upper16:\val
-	.endm
-
         .section ".text.head", "ax"
 	__CPUINIT
 
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index d29b156..ea81554 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -29,36 +29,5 @@
 #include <mach/iomap.h>
 
 #include "flowctrl.h"
+#include "sleep.h"
 
-#define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
-					+ IO_PPSB_VIRT)
-
-/* returns the offset of the flow controller halt register for a cpu */
-.macro cpu_to_halt_reg rd, rcpu
-	cmp	\rcpu, #0
-	subne	\rd, \rcpu, #1
-	movne	\rd, \rd, lsl #3
-	addne	\rd, \rd, #0x14
-	moveq	\rd, #0
-.endm
-
-/* returns the offset of the flow controller csr register for a cpu */
-.macro cpu_to_csr_reg rd, rcpu
-	cmp	\rcpu, #0
-	subne	\rd, \rcpu, #1
-	movne	\rd, \rd, lsl #3
-	addne	\rd, \rd, #0x18
-	moveq	\rd, #8
-.endm
-
-/* returns the ID of the current processor */
-.macro cpu_id, rd
-	mrc	p15, 0, \rd, c0, c0, 5
-	and	\rd, \rd, #0xF
-.endm
-
-/* loads a 32-bit value into a register without a data access */
-.macro mov32, reg, val
-	movw	\reg, #:lower16:\val
-	movt	\reg, #:upper16:\val
-.endm
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
new file mode 100644
index 0000000..d0c7a8b
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MACH_TEGRA_SLEEP_H
+#define __MACH_TEGRA_SLEEP_H
+
+#include <mach/iomap.h>
+
+#define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
+					+ IO_PPSB_VIRT)
+
+#ifdef __ASSEMBLY__
+/* returns the offset of the flow controller halt register for a cpu */
+.macro cpu_to_halt_reg rd, rcpu
+	cmp	\rcpu, #0
+	subne	\rd, \rcpu, #1
+	movne	\rd, \rd, lsl #3
+	addne	\rd, \rd, #0x14
+	moveq	\rd, #0
+.endm
+
+/* returns the offset of the flow controller csr register for a cpu */
+.macro cpu_to_csr_reg rd, rcpu
+	cmp	\rcpu, #0
+	subne	\rd, \rcpu, #1
+	movne	\rd, \rd, lsl #3
+	addne	\rd, \rd, #0x18
+	moveq	\rd, #8
+.endm
+
+/* returns the ID of the current processor */
+.macro cpu_id, rd
+	mrc	p15, 0, \rd, c0, c0, 5
+	and	\rd, \rd, #0xF
+.endm
+
+/* loads a 32-bit value into a register without a data access */
+.macro mov32, reg, val
+	movw	\reg, #:lower16:\val
+	movt	\reg, #:upper16:\val
+.endm
+#endif
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 4/6] ARM: tegra30: add CPU hotplug support
  2012-08-15  9:22 ` Joseph Lo
@ 2012-08-15  9:22     ` Joseph Lo
  -1 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: Stephen Warren, Olof Johansson, Colin Cross
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Joseph Lo

Hotplug function put CPUs in offline or online state at runtime.
When the CPU been put in the offline state, it was been clock and
power gated. Except primary CPU other CPUs can be hotplugged.

Based on the work by:
Scott Williams <scwilliams-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Colin Cross <ccross-z5hGa2qSFaRBDgjK7y7TUQ@public.gmane.org>
Gary King <gking-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Joseph Lo <josephl-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 arch/arm/mach-tegra/Makefile    |    1 +
 arch/arm/mach-tegra/common.c    |    2 +
 arch/arm/mach-tegra/hotplug.c   |  110 +++++++++------------------------------
 arch/arm/mach-tegra/sleep-t30.S |  107 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-tegra/sleep.h     |   21 +++++++
 5 files changed, 155 insertions(+), 86 deletions(-)
 create mode 100644 arch/arm/mach-tegra/sleep-t30.S

diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 060592a..211e279 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks_data.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-t30.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_SMP)                       += reset.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index f3654f8..0652056 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -34,6 +34,7 @@
 #include "fuse.h"
 #include "pmc.h"
 #include "apbio.h"
+#include "sleep.h"
 
 /*
  * Storage for debug-macro.S's state.
@@ -147,6 +148,7 @@ void __init tegra30_init_early(void)
 	tegra_init_cache(0x441, 0x551);
 	tegra_pmc_init();
 	tegra_powergate_init();
+	tegra30_hotplug_init();
 }
 #endif
 
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index d8dc9dd..be92d4c 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -1,91 +1,23 @@
 /*
- *  linux/arch/arm/mach-realview/hotplug.c
  *
  *  Copyright (C) 2002 ARM Ltd.
  *  All Rights Reserved
+ *  Copyright (c) 2010, 2012 NVIDIA Corporation. All rights reserved.
  *
  * 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/errno.h>
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
-#include <asm/cp15.h>
+#include <asm/smp_plat.h>
 
-static inline void cpu_enter_lowpower(void)
-{
-	unsigned int v;
+#include "sleep.h"
+#include "tegra_cpu_car.h"
 
-	flush_cache_all();
-	asm volatile(
-	"	mcr	p15, 0, %1, c7, c5, 0\n"
-	"	mcr	p15, 0, %1, c7, c10, 4\n"
-	/*
-	 * Turn off coherency
-	 */
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	bic	%0, %0, #0x20\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	"	mrc	p15, 0, %0, c1, c0, 0\n"
-	"	bic	%0, %0, %2\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	  : "=&r" (v)
-	  : "r" (0), "Ir" (CR_C)
-	  : "cc");
-}
-
-static inline void cpu_leave_lowpower(void)
-{
-	unsigned int v;
-
-	asm volatile(
-	"mrc	p15, 0, %0, c1, c0, 0\n"
-	"	orr	%0, %0, %1\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	orr	%0, %0, #0x20\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	  : "=&r" (v)
-	  : "Ir" (CR_C)
-	  : "cc");
-}
-
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
-{
-	/*
-	 * there is no power-control hardware on this platform, so all
-	 * we can do is put the core into WFI; this is safe as the calling
-	 * code will have already disabled interrupts
-	 */
-	for (;;) {
-		/*
-		 * here's the WFI
-		 */
-		asm(".word	0xe320f003\n"
-		    :
-		    :
-		    : "memory", "cc");
-
-		/*if (pen_release == cpu) {*/
-			/*
-			 * OK, proper wakeup, we're done
-			 */
-			break;
-		/*}*/
-
-		/*
-		 * Getting here, means that we have come out of WFI without
-		 * having been woken up - this shouldn't happen
-		 *
-		 * Just note it happening - when we're woken, we can report
-		 * its occurrence.
-		 */
-		(*spurious)++;
-	}
-}
+static void (*tegra_hotplug_shutdown)(void);
 
 int platform_cpu_kill(unsigned int cpu)
 {
@@ -99,22 +31,20 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-	int spurious = 0;
+	cpu = cpu_logical_map(cpu);
 
-	/*
-	 * we're ready for shutdown now, so do it
-	 */
-	cpu_enter_lowpower();
-	platform_do_lowpower(cpu, &spurious);
+	/* Flush the L1 data cache. */
+	flush_cache_all();
 
-	/*
-	 * bring this CPU back into the world of cache
-	 * coherency, and then restore interrupts
-	 */
-	cpu_leave_lowpower();
+	/* Shut down the current CPU. */
+	tegra_hotplug_shutdown();
+
+	/* Clock gate the CPU */
+	tegra_wait_cpu_in_reset(cpu);
+	tegra_disable_cpu_clock(cpu);
 
-	if (spurious)
-		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+	/* Should never return here. */
+	BUG();
 }
 
 int platform_cpu_disable(unsigned int cpu)
@@ -125,3 +55,11 @@ int platform_cpu_disable(unsigned int cpu)
 	 */
 	return cpu == 0 ? -EPERM : 0;
 }
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+extern void tegra30_hotplug_shutdown(void);
+void __init tegra30_hotplug_init(void)
+{
+	tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+}
+#endif
diff --git a/arch/arm/mach-tegra/sleep-t30.S b/arch/arm/mach-tegra/sleep-t30.S
new file mode 100644
index 0000000..777d9ce
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep-t30.S
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+
+#include <mach/iomap.h>
+
+#include "sleep.h"
+#include "flowctrl.h"
+
+#define TEGRA30_POWER_HOTPLUG_SHUTDOWN	(1 << 27) /* Hotplug shutdown */
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
+/*
+ * tegra30_hotplug_shutdown(void)
+ *
+ * Powergates the current CPU.
+ * Should never return.
+ */
+ENTRY(tegra30_hotplug_shutdown)
+	/* Turn off SMP coherency */
+	exit_smp r4, r5
+
+	/* Powergate this CPU */
+	mov	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
+	bl	tegra30_cpu_shutdown
+	mov	pc, lr			@ should never get here
+ENDPROC(tegra30_hotplug_shutdown)
+
+/*
+ * tegra30_cpu_shutdown(unsigned long flags)
+ *
+ * Puts the current CPU in wait-for-event mode on the flow controller
+ * and powergates it -- flags (in R0) indicate the request type.
+ * Must never be called for CPU 0.
+ *
+ * corrupts r0-r4, r12
+ */
+ENTRY(tegra30_cpu_shutdown)
+	cpu_id	r3
+	cmp	r3, #0
+	moveq	pc, lr		@ Must never be called for CPU 0
+
+	ldr	r12, =TEGRA_FLOW_CTRL_VIRT
+	cpu_to_csr_reg r1, r3
+	add	r1, r1, r12	@ virtual CSR address for this CPU
+	cpu_to_halt_reg r2, r3
+	add	r2, r2, r12	@ virtual HALT_EVENTS address for this CPU
+
+	/*
+	 * Clear this CPU's "event" and "interrupt" flags and power gate
+	 * it when halting but not before it is in the "WFE" state.
+	 */
+	movw	r12, \
+		FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \
+		FLOW_CTRL_CSR_ENABLE
+	mov	r4, #(1 << 4)
+	orr	r12, r12, r4, lsl r3
+	str	r12, [r1]
+
+	/* Halt this CPU. */
+	mov	r3, #0x400
+delay_1:
+	subs	r3, r3, #1			@ delay as a part of wfe war.
+	bge	delay_1;
+	cpsid	a				@ disable imprecise aborts.
+	ldr	r3, [r1]			@ read CSR
+	str	r3, [r1]			@ clear CSR
+	tst	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
+	movne	r3, #FLOW_CTRL_WAITEVENT		@ For hotplug
+	str	r3, [r2]
+	ldr	r0, [r2]
+	b	wfe_war
+
+__cpu_reset_again:
+	dsb
+	.align 5
+	wfe					@ CPU should be power gated here
+wfe_war:
+	b	__cpu_reset_again
+
+	/*
+	 * 38 nop's, which fills reset of wfe cache line and
+	 * 4 more cachelines with nop
+	 */
+	.rept 38
+	nop
+	.endr
+	b	.				@ should never get here
+
+ENDPROC(tegra30_cpu_shutdown)
+#endif
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index d0c7a8b..2ad9b6d 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -19,6 +19,8 @@
 
 #include <mach/iomap.h>
 
+#define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \
+					+ IO_CPU_VIRT)
 #define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
 					+ IO_PPSB_VIRT)
 
@@ -52,5 +54,24 @@
 	movw	\reg, #:lower16:\val
 	movt	\reg, #:upper16:\val
 .endm
+
+/* Macro to exit SMP coherency. */
+.macro exit_smp, tmp1, tmp2
+	mrc	p15, 0, \tmp1, c1, c0, 1	@ ACTLR
+	bic	\tmp1, \tmp1, #(1<<6) | (1<<0)	@ clear ACTLR.SMP | ACTLR.FW
+	mcr	p15, 0, \tmp1, c1, c0, 1	@ ACTLR
+	isb
+	cpu_id	\tmp1
+	mov	\tmp1, \tmp1, lsl #2
+	mov	\tmp2, #0xf
+	mov	\tmp2, \tmp2, lsl \tmp1
+	mov32	\tmp1, TEGRA_ARM_PERIF_VIRT + 0xC
+	str	\tmp2, [\tmp1]			@ invalidate SCU tags for CPU
+	dsb
+.endm
+#else
+
+void tegra30_hotplug_init(void);
+
 #endif
 #endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 4/6] ARM: tegra30: add CPU hotplug support
@ 2012-08-15  9:22     ` Joseph Lo
  0 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hotplug function put CPUs in offline or online state at runtime.
When the CPU been put in the offline state, it was been clock and
power gated. Except primary CPU other CPUs can be hotplugged.

Based on the work by:
Scott Williams <scwilliams@nvidia.com>
Colin Cross <ccross@android.com>
Gary King <gking@nvidia.com>

Signed-off-by: Joseph Lo <josephl@nvidia.com>
---
 arch/arm/mach-tegra/Makefile    |    1 +
 arch/arm/mach-tegra/common.c    |    2 +
 arch/arm/mach-tegra/hotplug.c   |  110 +++++++++------------------------------
 arch/arm/mach-tegra/sleep-t30.S |  107 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-tegra/sleep.h     |   21 +++++++
 5 files changed, 155 insertions(+), 86 deletions(-)
 create mode 100644 arch/arm/mach-tegra/sleep-t30.S

diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 060592a..211e279 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks_data.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-t30.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_SMP)                       += reset.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index f3654f8..0652056 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -34,6 +34,7 @@
 #include "fuse.h"
 #include "pmc.h"
 #include "apbio.h"
+#include "sleep.h"
 
 /*
  * Storage for debug-macro.S's state.
@@ -147,6 +148,7 @@ void __init tegra30_init_early(void)
 	tegra_init_cache(0x441, 0x551);
 	tegra_pmc_init();
 	tegra_powergate_init();
+	tegra30_hotplug_init();
 }
 #endif
 
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index d8dc9dd..be92d4c 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -1,91 +1,23 @@
 /*
- *  linux/arch/arm/mach-realview/hotplug.c
  *
  *  Copyright (C) 2002 ARM Ltd.
  *  All Rights Reserved
+ *  Copyright (c) 2010, 2012 NVIDIA Corporation. All rights reserved.
  *
  * 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/errno.h>
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
-#include <asm/cp15.h>
+#include <asm/smp_plat.h>
 
-static inline void cpu_enter_lowpower(void)
-{
-	unsigned int v;
+#include "sleep.h"
+#include "tegra_cpu_car.h"
 
-	flush_cache_all();
-	asm volatile(
-	"	mcr	p15, 0, %1, c7, c5, 0\n"
-	"	mcr	p15, 0, %1, c7, c10, 4\n"
-	/*
-	 * Turn off coherency
-	 */
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	bic	%0, %0, #0x20\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	"	mrc	p15, 0, %0, c1, c0, 0\n"
-	"	bic	%0, %0, %2\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	  : "=&r" (v)
-	  : "r" (0), "Ir" (CR_C)
-	  : "cc");
-}
-
-static inline void cpu_leave_lowpower(void)
-{
-	unsigned int v;
-
-	asm volatile(
-	"mrc	p15, 0, %0, c1, c0, 0\n"
-	"	orr	%0, %0, %1\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	orr	%0, %0, #0x20\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	  : "=&r" (v)
-	  : "Ir" (CR_C)
-	  : "cc");
-}
-
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
-{
-	/*
-	 * there is no power-control hardware on this platform, so all
-	 * we can do is put the core into WFI; this is safe as the calling
-	 * code will have already disabled interrupts
-	 */
-	for (;;) {
-		/*
-		 * here's the WFI
-		 */
-		asm(".word	0xe320f003\n"
-		    :
-		    :
-		    : "memory", "cc");
-
-		/*if (pen_release == cpu) {*/
-			/*
-			 * OK, proper wakeup, we're done
-			 */
-			break;
-		/*}*/
-
-		/*
-		 * Getting here, means that we have come out of WFI without
-		 * having been woken up - this shouldn't happen
-		 *
-		 * Just note it happening - when we're woken, we can report
-		 * its occurrence.
-		 */
-		(*spurious)++;
-	}
-}
+static void (*tegra_hotplug_shutdown)(void);
 
 int platform_cpu_kill(unsigned int cpu)
 {
@@ -99,22 +31,20 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-	int spurious = 0;
+	cpu = cpu_logical_map(cpu);
 
-	/*
-	 * we're ready for shutdown now, so do it
-	 */
-	cpu_enter_lowpower();
-	platform_do_lowpower(cpu, &spurious);
+	/* Flush the L1 data cache. */
+	flush_cache_all();
 
-	/*
-	 * bring this CPU back into the world of cache
-	 * coherency, and then restore interrupts
-	 */
-	cpu_leave_lowpower();
+	/* Shut down the current CPU. */
+	tegra_hotplug_shutdown();
+
+	/* Clock gate the CPU */
+	tegra_wait_cpu_in_reset(cpu);
+	tegra_disable_cpu_clock(cpu);
 
-	if (spurious)
-		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+	/* Should never return here. */
+	BUG();
 }
 
 int platform_cpu_disable(unsigned int cpu)
@@ -125,3 +55,11 @@ int platform_cpu_disable(unsigned int cpu)
 	 */
 	return cpu == 0 ? -EPERM : 0;
 }
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+extern void tegra30_hotplug_shutdown(void);
+void __init tegra30_hotplug_init(void)
+{
+	tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+}
+#endif
diff --git a/arch/arm/mach-tegra/sleep-t30.S b/arch/arm/mach-tegra/sleep-t30.S
new file mode 100644
index 0000000..777d9ce
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep-t30.S
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+
+#include <mach/iomap.h>
+
+#include "sleep.h"
+#include "flowctrl.h"
+
+#define TEGRA30_POWER_HOTPLUG_SHUTDOWN	(1 << 27) /* Hotplug shutdown */
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
+/*
+ * tegra30_hotplug_shutdown(void)
+ *
+ * Powergates the current CPU.
+ * Should never return.
+ */
+ENTRY(tegra30_hotplug_shutdown)
+	/* Turn off SMP coherency */
+	exit_smp r4, r5
+
+	/* Powergate this CPU */
+	mov	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
+	bl	tegra30_cpu_shutdown
+	mov	pc, lr			@ should never get here
+ENDPROC(tegra30_hotplug_shutdown)
+
+/*
+ * tegra30_cpu_shutdown(unsigned long flags)
+ *
+ * Puts the current CPU in wait-for-event mode on the flow controller
+ * and powergates it -- flags (in R0) indicate the request type.
+ * Must never be called for CPU 0.
+ *
+ * corrupts r0-r4, r12
+ */
+ENTRY(tegra30_cpu_shutdown)
+	cpu_id	r3
+	cmp	r3, #0
+	moveq	pc, lr		@ Must never be called for CPU 0
+
+	ldr	r12, =TEGRA_FLOW_CTRL_VIRT
+	cpu_to_csr_reg r1, r3
+	add	r1, r1, r12	@ virtual CSR address for this CPU
+	cpu_to_halt_reg r2, r3
+	add	r2, r2, r12	@ virtual HALT_EVENTS address for this CPU
+
+	/*
+	 * Clear this CPU's "event" and "interrupt" flags and power gate
+	 * it when halting but not before it is in the "WFE" state.
+	 */
+	movw	r12, \
+		FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \
+		FLOW_CTRL_CSR_ENABLE
+	mov	r4, #(1 << 4)
+	orr	r12, r12, r4, lsl r3
+	str	r12, [r1]
+
+	/* Halt this CPU. */
+	mov	r3, #0x400
+delay_1:
+	subs	r3, r3, #1			@ delay as a part of wfe war.
+	bge	delay_1;
+	cpsid	a				@ disable imprecise aborts.
+	ldr	r3, [r1]			@ read CSR
+	str	r3, [r1]			@ clear CSR
+	tst	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
+	movne	r3, #FLOW_CTRL_WAITEVENT		@ For hotplug
+	str	r3, [r2]
+	ldr	r0, [r2]
+	b	wfe_war
+
+__cpu_reset_again:
+	dsb
+	.align 5
+	wfe					@ CPU should be power gated here
+wfe_war:
+	b	__cpu_reset_again
+
+	/*
+	 * 38 nop's, which fills reset of wfe cache line and
+	 * 4 more cachelines with nop
+	 */
+	.rept 38
+	nop
+	.endr
+	b	.				@ should never get here
+
+ENDPROC(tegra30_cpu_shutdown)
+#endif
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index d0c7a8b..2ad9b6d 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -19,6 +19,8 @@
 
 #include <mach/iomap.h>
 
+#define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \
+					+ IO_CPU_VIRT)
 #define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
 					+ IO_PPSB_VIRT)
 
@@ -52,5 +54,24 @@
 	movw	\reg, #:lower16:\val
 	movt	\reg, #:upper16:\val
 .endm
+
+/* Macro to exit SMP coherency. */
+.macro exit_smp, tmp1, tmp2
+	mrc	p15, 0, \tmp1, c1, c0, 1	@ ACTLR
+	bic	\tmp1, \tmp1, #(1<<6) | (1<<0)	@ clear ACTLR.SMP | ACTLR.FW
+	mcr	p15, 0, \tmp1, c1, c0, 1	@ ACTLR
+	isb
+	cpu_id	\tmp1
+	mov	\tmp1, \tmp1, lsl #2
+	mov	\tmp2, #0xf
+	mov	\tmp2, \tmp2, lsl \tmp1
+	mov32	\tmp1, TEGRA_ARM_PERIF_VIRT + 0xC
+	str	\tmp2, [\tmp1]			@ invalidate SCU tags for CPU
+	dsb
+.endm
+#else
+
+void tegra30_hotplug_init(void);
+
 #endif
 #endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 5/6] ARM: tegra20: add CPU hotplug support
  2012-08-15  9:22 ` Joseph Lo
@ 2012-08-15  9:22     ` Joseph Lo
  -1 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: Stephen Warren, Olof Johansson, Colin Cross
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Joseph Lo

Hotplug function put CPU in offline or online mode at runtime.
When the CPU been put into offline, it was been clock gated. The
offline CPU can be power gated, when the remaining CPU goes into
LP2.

Based on the worked by:
Colin Cross <ccross-z5hGa2qSFaRBDgjK7y7TUQ@public.gmane.org>
Gary King <gking-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Joseph Lo <josephl-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 arch/arm/mach-tegra/Makefile    |    1 +
 arch/arm/mach-tegra/common.c    |    1 +
 arch/arm/mach-tegra/hotplug.c   |    8 ++++
 arch/arm/mach-tegra/sleep-t20.S |   82 +++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-tegra/sleep.h     |    3 +
 5 files changed, 95 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-tegra/sleep-t20.S

diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 211e279..959a429 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_CPU_IDLE)			+= sleep.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-t20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-t30.o
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 0652056..0560538 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -136,6 +136,7 @@ void __init tegra20_init_early(void)
 	tegra_init_cache(0x331, 0x441);
 	tegra_pmc_init();
 	tegra_powergate_init();
+	tegra20_hotplug_init();
 }
 #endif
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index be92d4c..d02a354 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -56,6 +56,14 @@ int platform_cpu_disable(unsigned int cpu)
 	return cpu == 0 ? -EPERM : 0;
 }
 
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+extern void tegra20_hotplug_shutdown(void);
+void __init tegra20_hotplug_init(void)
+{
+	tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
+}
+#endif
+
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 extern void tegra30_hotplug_shutdown(void);
 void __init tegra30_hotplug_init(void)
diff --git a/arch/arm/mach-tegra/sleep-t20.S b/arch/arm/mach-tegra/sleep-t20.S
new file mode 100644
index 0000000..a36ae41
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep-t20.S
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2011, Google, Inc.
+ *
+ * Author: Colin Cross <ccross-z5hGa2qSFaRBDgjK7y7TUQ@public.gmane.org>
+ *         Gary King <gking-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+
+#include <mach/iomap.h>
+
+#include "sleep.h"
+#include "flowctrl.h"
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
+/*
+ * tegra20_hotplug_shutdown(void)
+ *
+ * puts the current cpu in reset
+ * should never return
+ */
+ENTRY(tegra20_hotplug_shutdown)
+	/* Turn off SMP coherency */
+	exit_smp r4, r5
+
+	/* Put this CPU down */
+	cpu_id	r0
+	bl	tegra20_cpu_shutdown
+	mov	pc, lr			@ should never get here
+ENDPROC(tegra20_hotplug_shutdown)
+
+/*
+ * tegra20_cpu_shutdown(int cpu)
+ *
+ * r0 is cpu to reset
+ *
+ * puts the specified CPU in wait-for-event mode on the flow controller
+ * and puts the CPU in reset
+ * can be called on the current cpu or another cpu
+ * if called on the current cpu, does not return
+ * MUST NOT BE CALLED FOR CPU 0.
+ *
+ * corrupts r0-r3, r12
+ */
+ENTRY(tegra20_cpu_shutdown)
+	cmp	r0, #0
+	moveq	pc, lr			@ must not be called for CPU 0
+
+	cpu_to_halt_reg r1, r0
+	ldr	r3, =TEGRA_FLOW_CTRL_VIRT
+	mov	r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
+	str	r2, [r3, r1]		@ put flow controller in wait event mode
+	ldr	r2, [r3, r1]
+	isb
+	dsb
+	movw	r1, 0x1011
+	mov	r1, r1, lsl r0
+	ldr	r3, =TEGRA_CLK_RESET_VIRT
+	str	r1, [r3, #0x340]	@ put slave CPU in reset
+	isb
+	dsb
+	cpu_id	r3
+	cmp	r3, r0
+	beq	.
+	mov	pc, lr
+ENDPROC(tegra20_cpu_shutdown)
+#endif
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 2ad9b6d..42236e1 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -23,6 +23,8 @@
 					+ IO_CPU_VIRT)
 #define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
 					+ IO_PPSB_VIRT)
+#define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS \
+					+ IO_PPSB_VIRT)
 
 #ifdef __ASSEMBLY__
 /* returns the offset of the flow controller halt register for a cpu */
@@ -71,6 +73,7 @@
 .endm
 #else
 
+void tegra20_hotplug_init(void);
 void tegra30_hotplug_init(void);
 
 #endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 5/6] ARM: tegra20: add CPU hotplug support
@ 2012-08-15  9:22     ` Joseph Lo
  0 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hotplug function put CPU in offline or online mode at runtime.
When the CPU been put into offline, it was been clock gated. The
offline CPU can be power gated, when the remaining CPU goes into
LP2.

Based on the worked by:
Colin Cross <ccross@android.com>
Gary King <gking@nvidia.com>

Signed-off-by: Joseph Lo <josephl@nvidia.com>
---
 arch/arm/mach-tegra/Makefile    |    1 +
 arch/arm/mach-tegra/common.c    |    1 +
 arch/arm/mach-tegra/hotplug.c   |    8 ++++
 arch/arm/mach-tegra/sleep-t20.S |   82 +++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-tegra/sleep.h     |    3 +
 5 files changed, 95 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-tegra/sleep-t20.S

diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 211e279..959a429 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_CPU_IDLE)			+= sleep.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-t20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-t30.o
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 0652056..0560538 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -136,6 +136,7 @@ void __init tegra20_init_early(void)
 	tegra_init_cache(0x331, 0x441);
 	tegra_pmc_init();
 	tegra_powergate_init();
+	tegra20_hotplug_init();
 }
 #endif
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index be92d4c..d02a354 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -56,6 +56,14 @@ int platform_cpu_disable(unsigned int cpu)
 	return cpu == 0 ? -EPERM : 0;
 }
 
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+extern void tegra20_hotplug_shutdown(void);
+void __init tegra20_hotplug_init(void)
+{
+	tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
+}
+#endif
+
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 extern void tegra30_hotplug_shutdown(void);
 void __init tegra30_hotplug_init(void)
diff --git a/arch/arm/mach-tegra/sleep-t20.S b/arch/arm/mach-tegra/sleep-t20.S
new file mode 100644
index 0000000..a36ae41
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep-t20.S
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2011, Google, Inc.
+ *
+ * Author: Colin Cross <ccross@android.com>
+ *         Gary King <gking@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+
+#include <mach/iomap.h>
+
+#include "sleep.h"
+#include "flowctrl.h"
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
+/*
+ * tegra20_hotplug_shutdown(void)
+ *
+ * puts the current cpu in reset
+ * should never return
+ */
+ENTRY(tegra20_hotplug_shutdown)
+	/* Turn off SMP coherency */
+	exit_smp r4, r5
+
+	/* Put this CPU down */
+	cpu_id	r0
+	bl	tegra20_cpu_shutdown
+	mov	pc, lr			@ should never get here
+ENDPROC(tegra20_hotplug_shutdown)
+
+/*
+ * tegra20_cpu_shutdown(int cpu)
+ *
+ * r0 is cpu to reset
+ *
+ * puts the specified CPU in wait-for-event mode on the flow controller
+ * and puts the CPU in reset
+ * can be called on the current cpu or another cpu
+ * if called on the current cpu, does not return
+ * MUST NOT BE CALLED FOR CPU 0.
+ *
+ * corrupts r0-r3, r12
+ */
+ENTRY(tegra20_cpu_shutdown)
+	cmp	r0, #0
+	moveq	pc, lr			@ must not be called for CPU 0
+
+	cpu_to_halt_reg r1, r0
+	ldr	r3, =TEGRA_FLOW_CTRL_VIRT
+	mov	r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
+	str	r2, [r3, r1]		@ put flow controller in wait event mode
+	ldr	r2, [r3, r1]
+	isb
+	dsb
+	movw	r1, 0x1011
+	mov	r1, r1, lsl r0
+	ldr	r3, =TEGRA_CLK_RESET_VIRT
+	str	r1, [r3, #0x340]	@ put slave CPU in reset
+	isb
+	dsb
+	cpu_id	r3
+	cmp	r3, r0
+	beq	.
+	mov	pc, lr
+ENDPROC(tegra20_cpu_shutdown)
+#endif
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 2ad9b6d..42236e1 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -23,6 +23,8 @@
 					+ IO_CPU_VIRT)
 #define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
 					+ IO_PPSB_VIRT)
+#define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS \
+					+ IO_PPSB_VIRT)
 
 #ifdef __ASSEMBLY__
 /* returns the offset of the flow controller halt register for a cpu */
@@ -71,6 +73,7 @@
 .endm
 #else
 
+void tegra20_hotplug_init(void);
 void tegra30_hotplug_init(void);
 
 #endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 6/6] ARM: tegra: defconfig: enable HOTPLUG_CPU
  2012-08-15  9:22 ` Joseph Lo
@ 2012-08-15  9:22     ` Joseph Lo
  -1 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: Stephen Warren, Olof Johansson, Colin Cross
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Joseph Lo

Enable HOTPLUG_CPU after the SoC specific code to hotplug a CPU
been merged.

Signed-off-by: Joseph Lo <josephl-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 arch/arm/configs/tegra_defconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index db22453..e16fd61 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -31,6 +31,7 @@ CONFIG_MACH_PAZ00=y
 CONFIG_MACH_TRIMSLICE=y
 CONFIG_TEGRA_EMC_SCALING_ENABLE=y
 CONFIG_SMP=y
+CONFIG_HOTPLUG_CPU=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V2 6/6] ARM: tegra: defconfig: enable HOTPLUG_CPU
@ 2012-08-15  9:22     ` Joseph Lo
  0 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-15  9:22 UTC (permalink / raw)
  To: linux-arm-kernel

Enable HOTPLUG_CPU after the SoC specific code to hotplug a CPU
been merged.

Signed-off-by: Joseph Lo <josephl@nvidia.com>
---
 arch/arm/configs/tegra_defconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index db22453..e16fd61 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -31,6 +31,7 @@ CONFIG_MACH_PAZ00=y
 CONFIG_MACH_TRIMSLICE=y
 CONFIG_TEGRA_EMC_SCALING_ENABLE=y
 CONFIG_SMP=y
+CONFIG_HOTPLUG_CPU=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH V2 0/6] ARM: tegra: add CPU hotplug support
  2012-08-15  9:22 ` Joseph Lo
@ 2012-08-15 16:05     ` Stephen Warren
  -1 siblings, 0 replies; 18+ messages in thread
From: Stephen Warren @ 2012-08-15 16:05 UTC (permalink / raw)
  To: Joseph Lo
  Cc: Olof Johansson, Colin Cross, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On 08/15/2012 03:22 AM, Joseph Lo wrote:
> This patch set adds CPU hotplug support for Tegra20 and Tegra30 SoCs.
> 
> The first 3 patches make the CPU clock and reset control be a module and
> the abstraction APIs for TegraXX SoCs. And clean up some codes for later
> usage. Then add CPU hotplug support for Tegra20 and Tegra30.
> 
> Verified on Seaboard(Tegra20) and Cardhu(Tegra30)
> 
> V2:
> * add one more patch for enable HOTPLUG_CPU [6/6]

The build problem when HOTPLUG_CPU is disabled is still present. The
kernel needs to build with this option disabled.

Enabling HOTPLUG_CPU in defconfig doesn't force everyone to enable that
configuration option; not everyone uses tegra_defconfig, people don't
always update to the latest defconfig, people should be free to disable
functionality they don't need and still get a buildable & working
kernel, etc.

Besides, even if defconfig were a legitimate solution to this problem,
this series still wouldn't work with "git bisect", since the defconfig
patch comes after the patch that causes the build failure.

> * move all the SoC specific CPU shutdown code into platform_cpu_die [4/6]

The reboot problem is indeed solved.

P.S. It'd be nice to include a summary of what changed in each affected
patch, as well as in the cover letter.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH V2 0/6] ARM: tegra: add CPU hotplug support
@ 2012-08-15 16:05     ` Stephen Warren
  0 siblings, 0 replies; 18+ messages in thread
From: Stephen Warren @ 2012-08-15 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/15/2012 03:22 AM, Joseph Lo wrote:
> This patch set adds CPU hotplug support for Tegra20 and Tegra30 SoCs.
> 
> The first 3 patches make the CPU clock and reset control be a module and
> the abstraction APIs for TegraXX SoCs. And clean up some codes for later
> usage. Then add CPU hotplug support for Tegra20 and Tegra30.
> 
> Verified on Seaboard(Tegra20) and Cardhu(Tegra30)
> 
> V2:
> * add one more patch for enable HOTPLUG_CPU [6/6]

The build problem when HOTPLUG_CPU is disabled is still present. The
kernel needs to build with this option disabled.

Enabling HOTPLUG_CPU in defconfig doesn't force everyone to enable that
configuration option; not everyone uses tegra_defconfig, people don't
always update to the latest defconfig, people should be free to disable
functionality they don't need and still get a buildable & working
kernel, etc.

Besides, even if defconfig were a legitimate solution to this problem,
this series still wouldn't work with "git bisect", since the defconfig
patch comes after the patch that causes the build failure.

> * move all the SoC specific CPU shutdown code into platform_cpu_die [4/6]

The reboot problem is indeed solved.

P.S. It'd be nice to include a summary of what changed in each affected
patch, as well as in the cover letter.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH V2 0/6] ARM: tegra: add CPU hotplug support
  2012-08-15 16:05     ` Stephen Warren
@ 2012-08-16  9:30         ` Joseph Lo
  -1 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-16  9:30 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Olof Johansson, Colin Cross, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Stephen,

On Thu, 2012-08-16 at 00:05 +0800, Stephen Warren wrote:
> On 08/15/2012 03:22 AM, Joseph Lo wrote:
> > This patch set adds CPU hotplug support for Tegra20 and Tegra30 SoCs.
> > 
> > The first 3 patches make the CPU clock and reset control be a module and
> > the abstraction APIs for TegraXX SoCs. And clean up some codes for later
> > usage. Then add CPU hotplug support for Tegra20 and Tegra30.
> > 
> > Verified on Seaboard(Tegra20) and Cardhu(Tegra30)
> > 
> > V2:
> > * add one more patch for enable HOTPLUG_CPU [6/6]
> 
> The build problem when HOTPLUG_CPU is disabled is still present. The
> kernel needs to build with this option disabled.
> 
> Enabling HOTPLUG_CPU in defconfig doesn't force everyone to enable that
> configuration option; not everyone uses tegra_defconfig, people don't
> always update to the latest defconfig, people should be free to disable
> functionality they don't need and still get a buildable & working
> kernel, etc.
> 
Obviously, I didn't get your problem at your first reply. Sorry.

I fixed that and re-checked it again with Tegra20-only, Tegra30-only and
both supported kernel. And checked with "git bisect" as well. It should
be OK now.

Thanks,
Joseph

> Besides, even if defconfig were a legitimate solution to this problem,
> this series still wouldn't work with "git bisect", since the defconfig
> patch comes after the patch that causes the build failure.
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH V2 0/6] ARM: tegra: add CPU hotplug support
@ 2012-08-16  9:30         ` Joseph Lo
  0 siblings, 0 replies; 18+ messages in thread
From: Joseph Lo @ 2012-08-16  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Stephen,

On Thu, 2012-08-16 at 00:05 +0800, Stephen Warren wrote:
> On 08/15/2012 03:22 AM, Joseph Lo wrote:
> > This patch set adds CPU hotplug support for Tegra20 and Tegra30 SoCs.
> > 
> > The first 3 patches make the CPU clock and reset control be a module and
> > the abstraction APIs for TegraXX SoCs. And clean up some codes for later
> > usage. Then add CPU hotplug support for Tegra20 and Tegra30.
> > 
> > Verified on Seaboard(Tegra20) and Cardhu(Tegra30)
> > 
> > V2:
> > * add one more patch for enable HOTPLUG_CPU [6/6]
> 
> The build problem when HOTPLUG_CPU is disabled is still present. The
> kernel needs to build with this option disabled.
> 
> Enabling HOTPLUG_CPU in defconfig doesn't force everyone to enable that
> configuration option; not everyone uses tegra_defconfig, people don't
> always update to the latest defconfig, people should be free to disable
> functionality they don't need and still get a buildable & working
> kernel, etc.
> 
Obviously, I didn't get your problem at your first reply. Sorry.

I fixed that and re-checked it again with Tegra20-only, Tegra30-only and
both supported kernel. And checked with "git bisect" as well. It should
be OK now.

Thanks,
Joseph

> Besides, even if defconfig were a legitimate solution to this problem,
> this series still wouldn't work with "git bisect", since the defconfig
> patch comes after the patch that causes the build failure.
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2012-08-16  9:30 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-15  9:22 [PATCH V2 0/6] ARM: tegra: add CPU hotplug support Joseph Lo
2012-08-15  9:22 ` Joseph Lo
     [not found] ` <1345022554-26292-1-git-send-email-josephl-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2012-08-15  9:22   ` [PATCH V2 1/6] ARM: tegra: introduce tegra_cpu_car_ops structures Joseph Lo
2012-08-15  9:22     ` Joseph Lo
2012-08-15  9:22   ` [PATCH V2 2/6] ARM: tegra: replace the CPU CAR access code by tegra_cpu_car_ops Joseph Lo
2012-08-15  9:22     ` Joseph Lo
2012-08-15  9:22   ` [PATCH V2 3/6] ARM: tegra: clean up the common assembly macros into sleep.h Joseph Lo
2012-08-15  9:22     ` Joseph Lo
2012-08-15  9:22   ` [PATCH V2 4/6] ARM: tegra30: add CPU hotplug support Joseph Lo
2012-08-15  9:22     ` Joseph Lo
2012-08-15  9:22   ` [PATCH V2 5/6] ARM: tegra20: " Joseph Lo
2012-08-15  9:22     ` Joseph Lo
2012-08-15  9:22   ` [PATCH V2 6/6] ARM: tegra: defconfig: enable HOTPLUG_CPU Joseph Lo
2012-08-15  9:22     ` Joseph Lo
2012-08-15 16:05   ` [PATCH V2 0/6] ARM: tegra: add CPU hotplug support Stephen Warren
2012-08-15 16:05     ` Stephen Warren
     [not found]     ` <502BC8BE.8060800-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2012-08-16  9:30       ` Joseph Lo
2012-08-16  9:30         ` Joseph Lo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.