Skip to contentSkip to conversation

Consolidate and improve NVIDIA Tegra CPUIDLE driver(s)

PATCH Superseded Dmitry Osipenko 2 participants 19 messages Sep 29, 2019 – Sep 30, 2019

Subsystems (5)

v5 of 11 Superseded Latest is v11 →

lore
Share & tools
lore
#0 lore raw

v5 cover Consolidate and improve NVIDIA Tegra CPUIDLE driver(s)

Hello,

This series does the following:

1. Unifies Tegra20/30/114 drivers into a single driver and moves it out into common drivers/cpuidle/ directory.

2. Enables CPU cluster power-down idling state on Tegra30.

In the end there is a quite nice clean up of the Tegra CPUIDLE drivers and of the Tegra's arch code in general. Please review, thanks!

Changelog:

v5: - Rebased on a recent linux-next, fixed one minor conflict in Kconfig.

- Improved commit's message of the "Support CPU cluster power-down state on Tegra30" patch.

- The "Support CPU cluster power-down state on Tegra30" patch is also got split and now there is additional "Make outer_disable() open-coded" patch.

- Made minor cosmetic changes to the "Introduce unified driver for NVIDIA Tegra SoCs" patch by improving error message and renaming one variable.

v4: - Fixed compilation with !CONFIG_CACHE_L2X0 (and tested that it still
works).

- Replaced ktime_compare() with ktime_before() in the new driver, for consistency.

v3: - Addressed review comments that were made by Jon Hunter to v2 by
splitting patches into smaller (and simpler) chunks, better documenting changes in the commit messages and using proper error codes in the code.

Warnings are replaced with a useful error messages in the code of "Introduce unified driver for NVIDIA Tegra SoCs" patch.

Secondary CPUs parking timeout increased to 100ms because I found that it actually may happen to take more than 1ms if CPU is running on a *very* low frequency.

Added diagnostic messages that are reporting Flow Controller state when CPU parking fails.

Further polished cpuidle driver's code.

The coupled state entering is now aborted if there is a pending SGI (Software Generated Interrupt) because it will be lost after GIC's power-cycling. Like it was done by the old Tegra20 CPUIDLE driver.

v2: - Added patches to enable the new cpuidle driver in the defconfigs:

ARM: multi_v7_defconfig: Enable Tegra cpuidle driver
ARM: tegra: Enable Tegra cpuidle driver in tegra_defconfig

- Dropped patches that removed CPUIDLE_FLAG_TIMER_STOP from the idling states because that flag actually doesn't have any negative effects, but still is correct for the case of a local CPU timer on older Tegra SoCs:

cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from Tegra114/124 idle-state
cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from all states

- The "Add unified driver for NVIDIA Tegra SoCs" patch got more polish. Tegra30 and Terga114 states are now squashed into a single common C7 state (following Parker TRM terminology, see 17.2.2.2 Power Management States), more comments added, etc minor changes.

Dmitry Osipenko (14):
ARM: tegra: Remove cpuidle drivers to replace them with a new driver
ARM: tegra: Change tegra_set_cpu_in_lp2() type to void
ARM: tegra: Propagate error from tegra_idle_lp2_last()
ARM: tegra: Compile sleep-tegra20/30.S unconditionally
ARM: tegra: Expose PM functions required for new cpuidle driver
ARM: tegra: Rename some of the newly exposed PM functions
ARM: tegra: Add tegra_pm_park_secondary_cpu()
ARM: tegra: Make outer_disable() open-coded
clk: tegra: Add missing stubs for the case of !CONFIG_PM_SLEEP
cpuidle: Introduce unified driver for NVIDIA Tegra SoCs
cpuidle: tegra: Support CPU cluster power-down state on Tegra30
ARM: tegra: Create simple platform device for cpuidle driver
ARM: multi_v7_defconfig: Enable Tegra cpuidle driver
ARM: tegra: Enable Tegra cpuidle driver in tegra_defconfig

 arch/arm/configs/multi_v7_defconfig           |   1 +
 arch/arm/configs/tegra_defconfig              |   1 +
 arch/arm/mach-tegra/Makefile                  |  23 +-
 arch/arm/mach-tegra/cpuidle-tegra114.c        |  89 -----
 arch/arm/mach-tegra/cpuidle-tegra20.c         | 212 -----------
 arch/arm/mach-tegra/cpuidle-tegra30.c         | 132 -------
 arch/arm/mach-tegra/cpuidle.c                 |  50 ---
 arch/arm/mach-tegra/cpuidle.h                 |  21 --
 arch/arm/mach-tegra/irq.c                     |   3 +-
 arch/arm/mach-tegra/pm.c                      |  50 +--
 arch/arm/mach-tegra/pm.h                      |   4 -
 arch/arm/mach-tegra/reset-handler.S           |  11 -
 arch/arm/mach-tegra/reset.h                   |   9 +-
 arch/arm/mach-tegra/sleep-tegra20.S           | 170 ---------
 arch/arm/mach-tegra/sleep-tegra30.S           |   6 +-
 arch/arm/mach-tegra/sleep.h                   |  15 -
 arch/arm/mach-tegra/tegra.c                   |   7 +-
 drivers/cpuidle/Kconfig.arm                   |   8 +
 drivers/cpuidle/Makefile                      |   1 +
 drivers/cpuidle/cpuidle-tegra.c               | 349 ++++++++++++++++++
 drivers/soc/tegra/Kconfig                     |   1 -
 include/linux/clk/tegra.h                     |  13 +
 include/soc/tegra/cpuidle.h                   |   2 +-
 .../mach-tegra => include/soc/tegra}/irq.h    |   8 +-
 include/soc/tegra/pm.h                        |  31 ++
 25 files changed, 453 insertions(+), 764 deletions(-)
 delete mode 100644 arch/arm/mach-tegra/cpuidle-tegra114.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle-tegra20.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle-tegra30.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle.h
 create mode 100644 drivers/cpuidle/cpuidle-tegra.c
 rename {arch/arm/mach-tegra => include/soc/tegra}/irq.h (59%)
Signature · 1 line
2.23.0
#1 lore raw

PATCH v5 1/14 ARM: tegra: Remove cpuidle drivers to replace them with a new driver

Remove the old drivers to replace them cleanly with a new one later on. Please note that old Tegra20 CPUIDLE driver used pen-locking in order to block secondary CPU waking-up if IRQ happened to raise during of the entering into CC6 and primary CPU already crossed point of no return, but that is unnecessary in practice because CPUIDLE simply won't enter the coupled CC6 state if there is some CPU activity going on. The new driver will ensure that all secondary CPUs parked successfully at first and thus primary CPU won't be racing with the secondaries, hence the pen-locking functionality isn't needed anymore at all. This is the most notable thing of this patch.

---
 arch/arm/mach-tegra/Makefile           |  13 --
 arch/arm/mach-tegra/cpuidle-tegra114.c |  89 -----------
 arch/arm/mach-tegra/cpuidle-tegra20.c  | 212 -------------------------
 arch/arm/mach-tegra/cpuidle-tegra30.c  | 132 ---------------
 arch/arm/mach-tegra/cpuidle.c          |  50 ------
 arch/arm/mach-tegra/cpuidle.h          |  21 ---
 arch/arm/mach-tegra/irq.c              |   1 -
 arch/arm/mach-tegra/irq.h              |  11 --
 arch/arm/mach-tegra/pm.c               |   7 -
 arch/arm/mach-tegra/pm.h               |   1 -
 arch/arm/mach-tegra/reset-handler.S    |  11 --
 arch/arm/mach-tegra/reset.h            |   9 +-
 arch/arm/mach-tegra/sleep-tegra20.S    | 170 --------------------
 arch/arm/mach-tegra/sleep.h            |  12 --
 arch/arm/mach-tegra/tegra.c            |   3 -
 drivers/soc/tegra/Kconfig              |   1 -
 include/soc/tegra/cpuidle.h            |   4 -
 17 files changed, 2 insertions(+), 745 deletions(-)
 delete mode 100644 arch/arm/mach-tegra/cpuidle-tegra114.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle-tegra20.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle-tegra30.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle.h
 delete mode 100644 arch/arm/mach-tegra/irq.h
arch/arm/mach-tegra/Makefile +0 -13
index 6c1dff2eccc2..5d93a0b36866 100644
@@ -8,29 +8,16 @@ obj-y					+= reset.o
 obj-y					+= reset-handler.o
 obj-y					+= sleep.o
 obj-y					+= tegra.o
-obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= pm-tegra20.o
-ifeq ($(CONFIG_CPU_IDLE),y)
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= cpuidle-tegra20.o
-endif
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= pm-tegra30.o
-ifeq ($(CONFIG_CPU_IDLE),y)
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= cpuidle-tegra30.o
-endif
 obj-$(CONFIG_SMP)			+= platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
 
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= sleep-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= pm-tegra30.o
-ifeq ($(CONFIG_CPU_IDLE),y)
-obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= cpuidle-tegra114.o
-endif
 obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= sleep-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= pm-tegra30.o
-ifeq ($(CONFIG_CPU_IDLE),y)
-obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= cpuidle-tegra114.o
-endif
 
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-paz00.o
arch/arm/mach-tegra/cpuidle-tegra114.c deleted +0 -89

89 lines not on this page · raw message

arch/arm/mach-tegra/cpuidle-tegra20.c deleted +0 -212

212 lines not on this page · raw message

arch/arm/mach-tegra/cpuidle-tegra30.c deleted +0 -132

132 lines not on this page · raw message

arch/arm/mach-tegra/cpuidle.c deleted +0 -50

50 lines not on this page · raw message

arch/arm/mach-tegra/cpuidle.h deleted +0 -21
deleted file mode 100644
index 4e1f459f5bd8..000000000000
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
- */
-
-#ifndef __MACH_TEGRA_CPUIDLE_H
-#define __MACH_TEGRA_CPUIDLE_H
-
-#ifdef CONFIG_CPU_IDLE
-int tegra20_cpuidle_init(void);
-void tegra20_cpuidle_pcie_irqs_in_use(void);
-int tegra30_cpuidle_init(void);
-int tegra114_cpuidle_init(void);
-void tegra_cpuidle_init(void);
-void tegra_cpuidle_pcie_irqs_in_use(void);
-#else
-static inline void tegra_cpuidle_init(void) {}
-static inline void tegra_cpuidle_pcie_irqs_in_use(void) {}
-#endif
-
-#endif
arch/arm/mach-tegra/irq.c +0 -1
index ace7a390b5fe..4c065b54cbe7 100644
@@ -20,7 +20,6 @@
 
 #include "board.h"
 #include "iomap.h"
-#include "irq.h"
 
 #define SGI_MASK 0xFFFF
 
arch/arm/mach-tegra/irq.h deleted +0 -11
deleted file mode 100644
index 7a94cf121448..000000000000
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
- */
-
-#ifndef __TEGRA_IRQ_H
-#define __TEGRA_IRQ_H
-
-bool tegra_pending_sgi(void);
-
-#endif
arch/arm/mach-tegra/pm.c +0 -7
index 3cab81b82866..6aaacb5757e1 100644
@@ -137,18 +137,11 @@ bool tegra_set_cpu_in_lp2(void)
 
 	if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
 		last_cpu = true;
-	else if (tegra_get_chip_id() == TEGRA20 && phy_cpu_id == 1)
-		tegra20_cpu_set_resettable_soon();
 
 	spin_unlock(&tegra_lp2_lock);
 	return last_cpu;
 }
 
-int tegra_cpu_do_idle(void)
-{
-	return cpu_do_idle();
-}
-
 static int tegra_sleep_cpu(unsigned long v2p)
 {
 	/*
arch/arm/mach-tegra/pm.h +0 -1
index 569151b3edc0..1e51a9b636eb 100644
@@ -25,7 +25,6 @@ void tegra30_sleep_core_init(void);
 
 void tegra_clear_cpu_in_lp2(void);
 bool tegra_set_cpu_in_lp2(void);
-int tegra_cpu_do_idle(void);
 void tegra_idle_lp2_last(void);
 extern void (*tegra_tear_down_cpu)(void);
 
arch/arm/mach-tegra/reset-handler.S +0 -11
index 67b763fea005..df44828a34d3 100644
@@ -183,17 +183,6 @@ after_errata:
 	bleq	__die				@ CPU not present (to OS)
 #endif
 
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-	/* Are we on Tegra20? */
-	cmp	r6, #TEGRA20
-	bne	1f
-	/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
-	mov	r0, #CPU_NOT_RESETTABLE
-	cmp	r10, #0
-	strbne	r0, [r12, #RESET_DATA(RESETTABLE_STATUS)]
-1:
-#endif
-
 	/* Waking up from LP1? */
 	ldr	r8, [r12, #RESET_DATA(MASK_LP1)]
 	tst	r8, r11				@ if in_lp1
arch/arm/mach-tegra/reset.h +2 -7
index a4cfc08159f6..51265592cb1a 100644
@@ -16,9 +16,8 @@
 #define TEGRA_RESET_STARTUP_SECONDARY	3
 #define TEGRA_RESET_STARTUP_LP2		4
 #define TEGRA_RESET_STARTUP_LP1		5
-#define TEGRA_RESET_RESETTABLE_STATUS	6
-#define TEGRA_RESET_TF_PRESENT		7
-#define TEGRA_RESET_DATA_SIZE		8
+#define TEGRA_RESET_TF_PRESENT		6
+#define TEGRA_RESET_DATA_SIZE		7
 
 #define RESET_DATA(x)	((TEGRA_RESET_##x)*4)
 
@@ -42,10 +41,6 @@ void __tegra_cpu_reset_handler_end(void);
 	(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
 	((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_LP2] - \
 	 (u32)__tegra_cpu_reset_handler_start)))
-#define tegra20_cpu1_resettable_status \
-	(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
-	((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_RESETTABLE_STATUS] - \
-	 (u32)__tegra_cpu_reset_handler_start)))
 #endif
 
 #define tegra_cpu_reset_handler_offset \
arch/arm/mach-tegra/sleep-tegra20.S +0 -170

194 lines not on this page · raw message

arch/arm/mach-tegra/sleep.h +0 -12
index 78ef32a907c8..d219872b7546 100644
@@ -114,8 +114,6 @@
 .endm
 
 #else
-void tegra_pen_lock(void);
-void tegra_pen_unlock(void);
 void tegra_resume(void);
 int tegra_sleep_cpu_finish(unsigned long);
 void tegra_disable_clean_inv_dcache(u32 flag);
@@ -125,16 +123,6 @@ void tegra20_hotplug_shutdown(void);
 void tegra30_hotplug_shutdown(void);
 #endif
 
-void tegra20_cpu_shutdown(int cpu);
-int tegra20_cpu_is_resettable_soon(void);
-void tegra20_cpu_clear_resettable(void);
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-void tegra20_cpu_set_resettable_soon(void);
-#else
-static inline void tegra20_cpu_set_resettable_soon(void) {}
-#endif
-
-int tegra20_sleep_cpu_secondary_finish(unsigned long);
 void tegra20_tear_down_cpu(void);
 int tegra30_sleep_cpu_secondary_finish(unsigned long);
 void tegra30_tear_down_cpu(void);
arch/arm/mach-tegra/tegra.c +0 -3
index e512e606eabd..d9237769a37c 100644
@@ -40,9 +40,7 @@
 
 #include "board.h"
 #include "common.h"
-#include "cpuidle.h"
 #include "iomap.h"
-#include "irq.h"
 #include "pm.h"
 #include "reset.h"
 #include "sleep.h"
@@ -86,7 +84,6 @@ static void __init tegra_dt_init(void)
 static void __init tegra_dt_init_late(void)
 {
 	tegra_init_suspend();
-	tegra_cpuidle_init();
 
 	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
 	    of_machine_is_compatible("compal,paz00"))
drivers/soc/tegra/Kconfig +0 -1
index c8ef05d6b8c7..d98c69efb7e0 100644
@@ -6,7 +6,6 @@ if ARM
 
 config ARCH_TEGRA_2x_SOC
 	bool "Enable support for Tegra20 family"
-	select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
 	select ARM_ERRATA_720789
 	select ARM_ERRATA_754327 if SMP
 	select ARM_ERRATA_764369 if SMP
include/soc/tegra/cpuidle.h +0 -4
index 029ba1f4b2cc..f758808342b6 100644
@@ -6,12 +6,8 @@
 #ifndef __SOC_TEGRA_CPUIDLE_H__
 #define __SOC_TEGRA_CPUIDLE_H__
 
-#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_TEGRA) && defined(CONFIG_CPU_IDLE)
-void tegra_cpuidle_pcie_irqs_in_use(void);
-#else
 static inline void tegra_cpuidle_pcie_irqs_in_use(void)
 {
 }
-#endif
 
 #endif /* __SOC_TEGRA_CPUIDLE_H__ */
Signature · 1 line
2.23.0
#2 lore raw

PATCH v5 2/14 ARM: tegra: Change tegra_set_cpu_in_lp2() type to void

In reply to Dmitry Osipenko

The old Tegra30 CPUIDLE driver had intention to check whether primary CPU was the last CPU that entered LP2 (CC6) idle-state, but that functionality never got utilized by the old-removed driver because it never supported the CC6 while secondary CPUs were online. The new driver will properly support CC6 on Tegra30, including the case where secondary CPUs are online, and that knowledge about what CPUs entered CC6 won't be needed at all because new driver will use different approach by making use of the coupled idle-state and explicitly parking secondary CPUs before entering into CC6.

---
 arch/arm/mach-tegra/pm.c | 8 +-------
 arch/arm/mach-tegra/pm.h | 2 +-
 2 files changed, 2 insertions(+), 8 deletions(-)
arch/arm/mach-tegra/pm.c +1 -7
index 6aaacb5757e1..2f6fb54be9f8 100644
@@ -123,11 +123,9 @@ void tegra_clear_cpu_in_lp2(void)
 	spin_unlock(&tegra_lp2_lock);
 }
 
-bool tegra_set_cpu_in_lp2(void)
+void tegra_set_cpu_in_lp2(void)
 {
 	int phy_cpu_id = cpu_logical_map(smp_processor_id());
-	bool last_cpu = false;
-	cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask;
 	u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
 
 	spin_lock(&tegra_lp2_lock);
@@ -135,11 +133,7 @@ bool tegra_set_cpu_in_lp2(void)
 	BUG_ON((*cpu_in_lp2 & BIT(phy_cpu_id)));
 	*cpu_in_lp2 |= BIT(phy_cpu_id);
 
-	if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
-		last_cpu = true;
-
 	spin_unlock(&tegra_lp2_lock);
-	return last_cpu;
 }
 
 static int tegra_sleep_cpu(unsigned long v2p)
arch/arm/mach-tegra/pm.h +1 -1
index 1e51a9b636eb..3f3164ad04b7 100644
@@ -24,7 +24,7 @@ void tegra30_lp1_iram_hook(void);
 void tegra30_sleep_core_init(void);
 
 void tegra_clear_cpu_in_lp2(void);
-bool tegra_set_cpu_in_lp2(void);
+void tegra_set_cpu_in_lp2(void);
 void tegra_idle_lp2_last(void);
 extern void (*tegra_tear_down_cpu)(void);
 
Signature · 1 line
2.23.0
#3 lore raw

PATCH v5 3/14 ARM: tegra: Propagate error from tegra_idle_lp2_last()

In reply to Dmitry Osipenko

The cpu_suspend() may fail, it's never good to lose information about failure because it may become very useful for the caller. The new CPUIDLE driver will handle all of possible error cases, including the case of tegra_idle_lp2_last() failure.

---
 arch/arm/mach-tegra/pm.c | 8 ++++++--
 arch/arm/mach-tegra/pm.h | 2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/pm.c +6 -2
index 2f6fb54be9f8..f9c9bce9e15d 100644
@@ -189,14 +189,16 @@ static void tegra_pm_set(enum tegra_suspend_mode mode)
 	tegra_pmc_enter_suspend_mode(mode);
 }
 
-void tegra_idle_lp2_last(void)
+int tegra_idle_lp2_last(void)
 {
+	int err;
+
 	tegra_pm_set(TEGRA_SUSPEND_LP2);
 
 	cpu_cluster_pm_enter();
 	suspend_cpu_complex();
 
-	cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
+	err = cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
 
 	/*
 	 * Resume L2 cache if it wasn't re-enabled early during resume,
@@ -208,6 +210,8 @@ void tegra_idle_lp2_last(void)
 
 	restore_cpu_complex();
 	cpu_cluster_pm_exit();
+
+	return err;
 }
 
 enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
arch/arm/mach-tegra/pm.h +1 -1
index 3f3164ad04b7..ae68fc7db576 100644
@@ -25,7 +25,7 @@ void tegra30_sleep_core_init(void);
 
 void tegra_clear_cpu_in_lp2(void);
 void tegra_set_cpu_in_lp2(void);
-void tegra_idle_lp2_last(void);
+int tegra_idle_lp2_last(void);
 extern void (*tegra_tear_down_cpu)(void);
 
 #ifdef CONFIG_PM_SLEEP
Signature · 1 line
2.23.0
#4 lore raw

PATCH v5 4/14 ARM: tegra: Compile sleep-tegra20/30.S unconditionally

In reply to Dmitry Osipenko

The sleep-tegra*.S provides functionality required for suspend/resume and CPU hotplugging. The new unified CPUIDLE driver will support multiple hardware generations starting from Terga20 and ending with Tegra124, the driver will utilize functions that are provided by the assembly and thus it is cleaner to compile that code without any build-dependencies in order to avoid churning with #ifdef's.

---
 arch/arm/mach-tegra/Makefile | 10 ++++------
 arch/arm/mach-tegra/sleep.h  |  2 --
 2 files changed, 4 insertions(+), 8 deletions(-)
arch/arm/mach-tegra/Makefile +4 -6
index 5d93a0b36866..3bb44246d928 100644
@@ -8,16 +8,14 @@ obj-y					+= reset.o
 obj-y					+= reset-handler.o
 obj-y					+= sleep.o
 obj-y					+= tegra.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-tegra20.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= pm-tegra20.o
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-tegra30.o
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= pm-tegra30.o
+obj-y					+= sleep-tegra20.o
+obj-y					+= sleep-tegra30.o
 obj-$(CONFIG_SMP)			+= platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
 
-obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= sleep-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= pm-tegra20.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= pm-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= pm-tegra30.o
-obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= sleep-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= pm-tegra30.o
 
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-paz00.o
arch/arm/mach-tegra/sleep.h +0 -2
index d219872b7546..4978def9db46 100644
@@ -118,10 +118,8 @@ void tegra_resume(void);
 int tegra_sleep_cpu_finish(unsigned long);
 void tegra_disable_clean_inv_dcache(u32 flag);
 
-#ifdef CONFIG_HOTPLUG_CPU
 void tegra20_hotplug_shutdown(void);
 void tegra30_hotplug_shutdown(void);
-#endif
 
 void tegra20_tear_down_cpu(void);
 int tegra30_sleep_cpu_secondary_finish(unsigned long);
Signature · 1 line
2.23.0
#5 lore raw

PATCH v5 5/14 ARM: tegra: Expose PM functions required for new cpuidle driver

In reply to Dmitry Osipenko

The upcoming unified CPUIDLE driver will be added to the drivers/cpuidle/ directory and it will require all these exposed Tegra PM-core functions.

---
 arch/arm/mach-tegra/irq.c   |  2 ++
 arch/arm/mach-tegra/pm.h    |  3 ---
 arch/arm/mach-tegra/sleep.h |  1 -
 include/soc/tegra/irq.h     | 13 +++++++++++++
 include/soc/tegra/pm.h      | 25 +++++++++++++++++++++++++
 5 files changed, 40 insertions(+), 4 deletions(-)
 create mode 100644 include/soc/tegra/irq.h
arch/arm/mach-tegra/irq.c +2 -0
index 4c065b54cbe7..4e1ee70b2a3f 100644
@@ -18,6 +18,8 @@
 #include <linux/of.h>
 #include <linux/syscore_ops.h>
 
+#include <soc/tegra/irq.h>
+
 #include "board.h"
 #include "iomap.h"
 
arch/arm/mach-tegra/pm.h +0 -3
index ae68fc7db576..81525f5f4a44 100644
@@ -23,9 +23,6 @@ void tegra20_sleep_core_init(void);
 void tegra30_lp1_iram_hook(void);
 void tegra30_sleep_core_init(void);
 
-void tegra_clear_cpu_in_lp2(void);
-void tegra_set_cpu_in_lp2(void);
-int tegra_idle_lp2_last(void);
 extern void (*tegra_tear_down_cpu)(void);
 
 #ifdef CONFIG_PM_SLEEP
arch/arm/mach-tegra/sleep.h +0 -1
index 4978def9db46..4718a3cb45a1 100644
@@ -122,7 +122,6 @@ void tegra20_hotplug_shutdown(void);
 void tegra30_hotplug_shutdown(void);
 
 void tegra20_tear_down_cpu(void);
-int tegra30_sleep_cpu_secondary_finish(unsigned long);
 void tegra30_tear_down_cpu(void);
 
 #endif
include/soc/tegra/irq.h new file +13 -0
new file mode 100644
index 000000000000..8eb11a7109e4
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
+ */
+
+#ifndef __SOC_TEGRA_IRQ_H
+#define __SOC_TEGRA_IRQ_H
+
+#if defined(CONFIG_ARM)
+bool tegra_pending_sgi(void);
+#endif
+
+#endif /* __SOC_TEGRA_IRQ_H */
include/soc/tegra/pm.h +25 -0
index 951fcd738d55..bc1abdf41d61 100644
@@ -6,6 +6,8 @@
 #ifndef __SOC_TEGRA_PM_H__
 #define __SOC_TEGRA_PM_H__
 
+#include <linux/errno.h>
+
 enum tegra_suspend_mode {
 	TEGRA_SUSPEND_NONE = 0,
 	TEGRA_SUSPEND_LP2, /* CPU voltage off */
@@ -20,6 +22,11 @@ tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);
 
 /* low-level resume entry point */
 void tegra_resume(void);
+
+int tegra30_sleep_cpu_secondary_finish(unsigned long arg);
+void tegra_clear_cpu_in_lp2(void);
+void tegra_set_cpu_in_lp2(void);
+int tegra_idle_lp2_last(void);
 #else
 static inline enum tegra_suspend_mode
 tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
@@ -30,6 +37,24 @@ tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
 static inline void tegra_resume(void)
 {
 }
+
+static inline int tegra30_sleep_cpu_secondary_finish(unsigned long arg)
+{
+	return -ENOTSUPP;
+}
+
+static inline void tegra_clear_cpu_in_lp2(void)
+{
+}
+
+static inline void tegra_set_cpu_in_lp2(void)
+{
+}
+
+static inline int tegra_idle_lp2_last(void)
+{
+	return -ENOTSUPP;
+}
 #endif /* CONFIG_PM_SLEEP */
 
 #endif /* __SOC_TEGRA_PM_H__ */
Signature · 1 line
2.23.0
#6 lore raw

PATCH v5 6/14 ARM: tegra: Rename some of the newly exposed PM functions

In reply to Dmitry Osipenko

Rename some of the recently exposed PM functions, prefixing them with "tegra_pm_" and making naming of those functions more meaningful, for consistency.

---
 arch/arm/mach-tegra/pm.c            | 10 +++++-----
 arch/arm/mach-tegra/sleep-tegra30.S |  6 +++---
 include/soc/tegra/pm.h              | 16 ++++++++--------
 3 files changed, 16 insertions(+), 16 deletions(-)
arch/arm/mach-tegra/pm.c +5 -5
index f9c9bce9e15d..4cc64a135a3e 100644
@@ -110,7 +110,7 @@ static void suspend_cpu_complex(void)
 	flowctrl_cpu_suspend_enter(cpu);
 }
 
-void tegra_clear_cpu_in_lp2(void)
+void tegra_pm_clear_cpu_in_lp2(void)
 {
 	int phy_cpu_id = cpu_logical_map(smp_processor_id());
 	u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
@@ -123,7 +123,7 @@ void tegra_clear_cpu_in_lp2(void)
 	spin_unlock(&tegra_lp2_lock);
 }
 
-void tegra_set_cpu_in_lp2(void)
+void tegra_pm_set_cpu_in_lp2(void)
 {
 	int phy_cpu_id = cpu_logical_map(smp_processor_id());
 	u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
@@ -189,7 +189,7 @@ static void tegra_pm_set(enum tegra_suspend_mode mode)
 	tegra_pmc_enter_suspend_mode(mode);
 }
 
-int tegra_idle_lp2_last(void)
+int tegra_pm_enter_lp2(void)
 {
 	int err;
 
@@ -356,7 +356,7 @@ static int tegra_suspend_enter(suspend_state_t state)
 		tegra_suspend_enter_lp1();
 		break;
 	case TEGRA_SUSPEND_LP2:
-		tegra_set_cpu_in_lp2();
+		tegra_pm_set_cpu_in_lp2();
 		break;
 	default:
 		break;
@@ -377,7 +377,7 @@ static int tegra_suspend_enter(suspend_state_t state)
 		tegra_suspend_exit_lp1();
 		break;
 	case TEGRA_SUSPEND_LP2:
-		tegra_clear_cpu_in_lp2();
+		tegra_pm_clear_cpu_in_lp2();
 		break;
 	default:
 		break;
arch/arm/mach-tegra/sleep-tegra30.S +3 -3
index b408fa56eb89..386319a3d2d2 100644
@@ -262,11 +262,11 @@ ENTRY(tegra30_sleep_core_finish)
 ENDPROC(tegra30_sleep_core_finish)
 
 /*
- * tegra30_sleep_cpu_secondary_finish(unsigned long v2p)
+ * tegra30_pm_secondary_cpu_suspend(unsigned long unused_arg)
  *
  * Enters LP2 on secondary CPU by exiting coherency and powergating the CPU.
  */
-ENTRY(tegra30_sleep_cpu_secondary_finish)
+ENTRY(tegra30_pm_secondary_cpu_suspend)
 	mov	r7, lr
 
 	/* Flush and disable the L1 data cache */
@@ -278,7 +278,7 @@ ENTRY(tegra30_sleep_cpu_secondary_finish)
 	bl	tegra30_cpu_shutdown
 	mov	r0, #1                          @ never return here
 	ret	r7
-ENDPROC(tegra30_sleep_cpu_secondary_finish)
+ENDPROC(tegra30_pm_secondary_cpu_suspend)
 
 /*
  * tegra30_tear_down_cpu
include/soc/tegra/pm.h +8 -8
index bc1abdf41d61..2fbee9efda21 100644
@@ -23,10 +23,10 @@ tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);
 /* low-level resume entry point */
 void tegra_resume(void);
 
-int tegra30_sleep_cpu_secondary_finish(unsigned long arg);
-void tegra_clear_cpu_in_lp2(void);
-void tegra_set_cpu_in_lp2(void);
-int tegra_idle_lp2_last(void);
+int tegra30_pm_secondary_cpu_suspend(unsigned long arg);
+void tegra_pm_clear_cpu_in_lp2(void);
+void tegra_pm_set_cpu_in_lp2(void);
+int tegra_pm_enter_lp2(void);
 #else
 static inline enum tegra_suspend_mode
 tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
@@ -38,20 +38,20 @@ static inline void tegra_resume(void)
 {
 }
 
-static inline int tegra30_sleep_cpu_secondary_finish(unsigned long arg)
+static inline int tegra30_pm_secondary_cpu_suspend(unsigned long arg)
 {
 	return -ENOTSUPP;
 }
 
-static inline void tegra_clear_cpu_in_lp2(void)
+static inline void tegra_pm_clear_cpu_in_lp2(void)
 {
 }
 
-static inline void tegra_set_cpu_in_lp2(void)
+static inline void tegra_pm_set_cpu_in_lp2(void)
 {
 }
 
-static inline int tegra_idle_lp2_last(void)
+static inline int tegra_pm_enter_lp2(void)
 {
 	return -ENOTSUPP;
 }
Signature · 1 line
2.23.0
#7 lore raw

PATCH v5 7/14 ARM: tegra: Add tegra_pm_park_secondary_cpu()

In reply to Dmitry Osipenko

This function resembles tegra_cpu_die() of the hotplug code, but this variant is more suitable to be used for CPU PM because it's made specifically to be used by cpu_suspend(). In short this function puts secondary CPU offline, it will be used by the new CPUIDLE driver.

---
 arch/arm/mach-tegra/pm.c | 14 ++++++++++++++
 include/soc/tegra/pm.h   |  6 ++++++
 2 files changed, 20 insertions(+)
arch/arm/mach-tegra/pm.c +14 -0
index 4cc64a135a3e..7d9ef26e52a7 100644
@@ -427,4 +427,18 @@ void __init tegra_init_suspend(void)
 
 	suspend_set_ops(&tegra_suspend_ops);
 }
+
+int tegra_pm_park_secondary_cpu(unsigned long cpu)
+{
+	if (cpu > 0) {
+		tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
+
+		if (tegra_get_chip_id() == TEGRA20)
+			tegra20_hotplug_shutdown();
+		else
+			tegra30_hotplug_shutdown();
+	}
+
+	return -EINVAL;
+}
 #endif
include/soc/tegra/pm.h +6 -0
index 2fbee9efda21..08477d7bfab9 100644
@@ -27,6 +27,7 @@ int tegra30_pm_secondary_cpu_suspend(unsigned long arg);
 void tegra_pm_clear_cpu_in_lp2(void);
 void tegra_pm_set_cpu_in_lp2(void);
 int tegra_pm_enter_lp2(void);
+int tegra_pm_park_secondary_cpu(unsigned long cpu);
 #else
 static inline enum tegra_suspend_mode
 tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
@@ -55,6 +56,11 @@ static inline int tegra_pm_enter_lp2(void)
 {
 	return -ENOTSUPP;
 }
+
+static inline int tegra_pm_park_secondary_cpu(unsigned long cpu)
+{
+	return -ENOTSUPP;
+}
 #endif /* CONFIG_PM_SLEEP */
 
 #endif /* __SOC_TEGRA_PM_H__ */
Signature · 1 line
2.23.0
#8 lore raw

PATCH v5 8/14 ARM: tegra: Make outer_disable() open-coded

In reply to Dmitry Osipenko

The outer_disable() of Tegra's suspend code is open-coded now since that helper produces spurious warning message about secondary CPUs being online. The secondaries are actually halted by the cpuidle driver on entering into LP2 idle-state. This fixes a storm of warnings once LP2 idling state is enabled on Tegra30.

---
 arch/arm/mach-tegra/pm.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/pm.c +4 -3
index 7d9ef26e52a7..16a02937d3da 100644
@@ -146,9 +146,10 @@ static int tegra_sleep_cpu(unsigned long v2p)
 	 * if any of secondary CPU's is online and this is the LP2-idle
 	 * code-path only for Tegra20/30.
 	 */
-	if (trusted_foundations_registered())
-		outer_disable();
-
+#ifdef CONFIG_OUTER_CACHE
+	if (trusted_foundations_registered() && outer_cache.disable)
+		outer_cache.disable();
+#endif
 	/*
 	 * Note that besides of setting up CPU reset vector this firmware
 	 * call may also do the following, depending on the FW version:
Signature · 1 line
2.23.0
#9 lore raw

Re: [PATCH v5 08/14] ARM: tegra: Make outer_disable() open-coded

Quoted 5 lines · Dmitry Osipenko

The outer_disable() of Tegra's suspend code is open-coded now since that helper produces spurious warning message about secondary CPUs being online. The secondaries are actually halted by the cpuidle driver on entering into LP2 idle-state. This fixes a storm of warnings once LP2 idling state is enabled on Tegra30.

If the cpuidle driver halts the secondaries, shouldn't it set it offline then so that outer_disable() can still work correctly?

Thierry

Quoted 27 lines
---
 arch/arm/mach-tegra/pm.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/pm.c +4 -3
index 7d9ef26e52a7..16a02937d3da 100644
@@ -146,9 +146,10 @@ static int tegra_sleep_cpu(unsigned long v2p)
 	 * if any of secondary CPU's is online and this is the LP2-idle
 	 * code-path only for Tegra20/30.
 	 */
-	if (trusted_foundations_registered())
-		outer_disable();
-
+#ifdef CONFIG_OUTER_CACHE
+	if (trusted_foundations_registered() && outer_cache.disable)
+		outer_cache.disable();
+#endif
 	/*
 	 * Note that besides of setting up CPU reset vector this firmware
 	 * call may also do the following, depending on the FW version:
Signature · 1 line
2.23.0
#10 lore raw

Re: [PATCH v5 08/14] ARM: tegra: Make outer_disable() open-coded

30.09.2019 11:05, Thierry Reding пишет:

Quoted 9 lines · Dmitry Osipenko
Quoted 5 lines

The outer_disable() of Tegra's suspend code is open-coded now since that helper produces spurious warning message about secondary CPUs being online. The secondaries are actually halted by the cpuidle driver on entering into LP2 idle-state. This fixes a storm of warnings once LP2 idling state is enabled on Tegra30.

If the cpuidle driver halts the secondaries, shouldn't it set it offline then so that outer_disable() can still work correctly?

No.. how would you know what CPU's should be resumed?

AFAIK, the online status should be only changed by the hotplug code and nothing else. I don't think that it's a good idea to manually touch the online mask.

It looks to me that the only purpose of outer_disable() checking for the num_online_cpus is to prevent people from doing wrong things by disabling L2 in a random places in their code. Hence it should be absolutely fine to open code when you know what you're doing, which is the case here.

We can check the rail status in tegra_sleep_cpu():

if (trusted_foundations_registered() && outer_cache.disable) {
	if (WARN_ON(!tegra_cpu_rail_off_ready()))
		return -EBUSY;

	outer_cache.disable();
}

Which is equal to the check for num_online_cpus. Does it sound good?

#11 lore raw

PATCH v5 9/14 clk: tegra: Add missing stubs for the case of !CONFIG_PM_SLEEP

In reply to Dmitry Osipenko

The new CPUIDLE driver uses the Tegra's CLK API and that driver won't strictly depend on CONFIG_PM_SLEEP, hence add the required stubs in order to allow compiling of the new driver with the CONFIG_PM_SLEEP=n.

---
 include/linux/clk/tegra.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)
include/linux/clk/tegra.h +13 -0
index b8aef62cc3f5..cf0f2cb5e109 100644
@@ -108,6 +108,19 @@ static inline void tegra_cpu_clock_resume(void)
 
 	tegra_cpu_car_ops->resume();
 }
+#else
+static inline bool tegra_cpu_rail_off_ready(void)
+{
+	return false;
+}
+
+static inline void tegra_cpu_clock_suspend(void)
+{
+}
+
+static inline void tegra_cpu_clock_resume(void)
+{
+}
 #endif
 
 extern void tegra210_xusb_pll_hw_control_enable(void);
Signature · 1 line
2.23.0
#12 lore raw

PATCH v5 10/14 cpuidle: Introduce unified driver for NVIDIA Tegra SoCs

In reply to Dmitry Osipenko

The new driver is based on the old CPU Idle drivers that are removed now from arm/arch/mach-tegra/ directory. Those removed drivers were reworked and squashed into a single unified driver that covers multiple hardware generations, starting from Tegra20 and ending with Tegra124. The new driver takes slightly different approach in regards to handling of CC6 state by parking secondary CPUs explicitly into offline state, in contrast to CPUs suspend/resume racing that old Tegra20 had. The new driver doesn't ignore any possible errors and provides useful diagnostics information in a case of failure.

---
 drivers/cpuidle/Kconfig.arm     |   8 +
 drivers/cpuidle/Makefile        |   1 +
 drivers/cpuidle/cpuidle-tegra.c | 350 ++++++++++++++++++++++++++++++++
 include/soc/tegra/cpuidle.h     |   4 +
 4 files changed, 363 insertions(+)
 create mode 100644 drivers/cpuidle/cpuidle-tegra.c
drivers/cpuidle/Kconfig.arm +8 -0
index d8530475493c..6952bf7bb260 100644
@@ -86,3 +86,11 @@ config ARM_MVEBU_V7_CPUIDLE
 	depends on ARCH_MVEBU && !ARM64
 	help
 	  Select this to enable cpuidle on Armada 370, 38x and XP processors.
+
+config ARM_TEGRA_CPUIDLE
+	bool "CPU Idle Driver for NVIDIA Tegra SoCs"
+	depends on ARCH_TEGRA && !ARM64
+	select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
+	select ARM_CPU_SUSPEND
+	help
+	  Select this to enable cpuidle for NVIDIA Tegra20/30/114/124 SoCs.
drivers/cpuidle/Makefile +1 -0
index ee70d5cc5b99..a15e4808d295 100644
@@ -22,6 +22,7 @@ obj-$(CONFIG_ARM_AT91_CPUIDLE)          += cpuidle-at91.o
 obj-$(CONFIG_ARM_EXYNOS_CPUIDLE)        += cpuidle-exynos.o
 obj-$(CONFIG_ARM_CPUIDLE)		+= cpuidle-arm.o
 obj-$(CONFIG_ARM_PSCI_CPUIDLE)		+= cpuidle-psci.o
+obj-$(CONFIG_ARM_TEGRA_CPUIDLE)		+= cpuidle-tegra.o
 
 ###############################################################################
 # MIPS drivers
drivers/cpuidle/cpuidle-tegra.c new file +350 -0

350 lines not on this page · raw message

include/soc/tegra/cpuidle.h +4 -0
index f758808342b6..5665975015d8 100644
@@ -6,8 +6,12 @@
 #ifndef __SOC_TEGRA_CPUIDLE_H__
 #define __SOC_TEGRA_CPUIDLE_H__
 
+#ifdef CONFIG_ARM_TEGRA_CPUIDLE
+void tegra_cpuidle_pcie_irqs_in_use(void);
+#else
 static inline void tegra_cpuidle_pcie_irqs_in_use(void)
 {
 }
+#endif
 
 #endif /* __SOC_TEGRA_CPUIDLE_H__ */
Signature · 1 line
2.23.0
#13 lore raw

PATCH v5 11/14 cpuidle: tegra: Support CPU cluster power-down state on Tegra30

In reply to Dmitry Osipenko

The new Tegra CPU Idle driver now has a unified code path for the coupled LP2/CC6 state, this allows to enable the deepest idling state on Tegra30 SoC where the whole CPU cluster is power-gated.

---
 drivers/cpuidle/cpuidle-tegra.c | 1 -
 1 file changed, 1 deletion(-)
drivers/cpuidle/cpuidle-tegra.c +0 -1
index a926d2781227..a30a5e4fc863 100644
@@ -325,7 +325,6 @@ static int tegra_cpuidle_probe(struct platform_device *pdev)
 		tegra_idle_driver.states[TEGRA_C7].disabled = true;
 		break;
 	case TEGRA30:
-		tegra_idle_driver.states[TEGRA_CC6].disabled = true;
 		break;
 	case TEGRA114:
 	case TEGRA124:
Signature · 1 line
2.23.0
#14 lore raw

PATCH v5 12/14 ARM: tegra: Create simple platform device for cpuidle driver

In reply to Dmitry Osipenko

The new CPUIDLE driver now is a proper platform driver, hence it needs a platform device in order to be functional. Register the platform device, like we do that for the CPUFreq driver. Note that on some Tegra114(124) devices PSCI may be used for the CPU hotplugging and CPUIDLE driver doesn't support that case, thus CPUIDLE device won't be registered if PCSI presents.

---
 arch/arm/mach-tegra/tegra.c | 4 ++++
 1 file changed, 4 insertions(+)
arch/arm/mach-tegra/tegra.c +4 -0
index d9237769a37c..f1ce2857a251 100644
@@ -36,6 +36,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach-types.h>
+#include <asm/psci.h>
 #include <asm/setup.h>
 
 #include "board.h"
@@ -92,6 +93,9 @@ static void __init tegra_dt_init_late(void)
 	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
 	    of_machine_is_compatible("nvidia,tegra20"))
 		platform_device_register_simple("tegra20-cpufreq", -1, NULL, 0);
+
+	if (IS_ENABLED(CONFIG_ARM_TEGRA_CPUIDLE) && !psci_smp_available())
+		platform_device_register_simple("tegra-cpuidle", -1, NULL, 0);
 }
 
 static const char * const tegra_dt_board_compat[] = {
Signature · 1 line
2.23.0
#15 lore raw

PATCH v5 13/14 ARM: multi_v7_defconfig: Enable Tegra cpuidle driver

In reply to Dmitry Osipenko

The Tegra CPU Idle driver was moved out into driver/cpuidle/ directory and it is now a proper platform driver.

---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)
arch/arm/configs/multi_v7_defconfig +1 -0
index 13ba53286901..539bb60069ee 100644
@@ -110,6 +110,7 @@ CONFIG_CPU_IDLE=y
 CONFIG_ARM_CPUIDLE=y
 CONFIG_ARM_ZYNQ_CPUIDLE=y
 CONFIG_ARM_EXYNOS_CPUIDLE=y
+CONFIG_ARM_TEGRA_CPUIDLE=y
 CONFIG_KERNEL_MODE_NEON=y
 CONFIG_RASPBERRYPI_FIRMWARE=y
 CONFIG_TRUSTED_FOUNDATIONS=y
Signature · 1 line
2.23.0
#16 lore raw

PATCH v5 14/14 ARM: tegra: Enable Tegra cpuidle driver in tegra_defconfig

In reply to Dmitry Osipenko

The Tegra CPU Idle driver was moved out into driver/cpuidle/ directory and it is now a proper platform driver.

---
 arch/arm/configs/tegra_defconfig | 1 +
 1 file changed, 1 insertion(+)
arch/arm/configs/tegra_defconfig +1 -0
index 8f5c6a5b444c..9a2f11a780a8 100644
@@ -25,6 +25,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPUFREQ_DT=y
 CONFIG_CPU_IDLE=y
+CONFIG_ARM_TEGRA_CPUIDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_TRUSTED_FOUNDATIONS=y
Signature · 1 line
2.23.0
#17 lore raw
In reply to Dmitry Osipenko
Quoted 11 lines · Dmitry Osipenko

Hello,

This series does the following:

1. Unifies Tegra20/30/114 drivers into a single driver and moves it out into common drivers/cpuidle/ directory.

2. Enables CPU cluster power-down idling state on Tegra30.

In the end there is a quite nice clean up of the Tegra CPUIDLE drivers and of the Tegra's arch code in general. Please review, thanks!

I generally like this series and it looks really good from a diffstat point of view. However, removing existing drivers completely and then incrementally add a new one make this impossible to review.

If you think about it, it also makes it really difficult to find what went wrong if at any point in the future we find a regression caused by the new driver. A bisection will always point at the commit that removes the old driver because between that and the point where you add the new driver, CPU idle just doesn't work at all anymore.

While I understand that it's very convenient to just throw away old code and rewrite it from scratch, it's also impractical (and a little rude). It's not how we do things in the kernel. Unless maybe under specific circumstances.

Can you please try and make this a little more iterative? At the very least I'd expect a series where you do all the preliminary work in preparatory patches and then replace the old driver by the new driver in a single patch. That way at least there will be an unambiguous commit in a bisection.

Ideally, you'd also break up that last conversion patch into smaller incremental patches to make it easier for people to review. Remember that your chances to attract reviewers increases if you make the patches easy to review, which means your patches should be small, logical changes that (ideally) are obviously correct.

Thierry

Quoted 113 lines

Changelog:

v5: - Rebased on a recent linux-next, fixed one minor conflict in Kconfig.

- Improved commit's message of the "Support CPU cluster power-down state on Tegra30" patch.

- The "Support CPU cluster power-down state on Tegra30" patch is also got split and now there is additional "Make outer_disable() open-coded" patch.

- Made minor cosmetic changes to the "Introduce unified driver for NVIDIA Tegra SoCs" patch by improving error message and renaming one variable.

v4: - Fixed compilation with !CONFIG_CACHE_L2X0 (and tested that it still
works).

- Replaced ktime_compare() with ktime_before() in the new driver, for consistency.

v3: - Addressed review comments that were made by Jon Hunter to v2 by
splitting patches into smaller (and simpler) chunks, better documenting changes in the commit messages and using proper error codes in the code.

Warnings are replaced with a useful error messages in the code of "Introduce unified driver for NVIDIA Tegra SoCs" patch.

Secondary CPUs parking timeout increased to 100ms because I found that it actually may happen to take more than 1ms if CPU is running on a *very* low frequency.

Added diagnostic messages that are reporting Flow Controller state when CPU parking fails.

Further polished cpuidle driver's code.

The coupled state entering is now aborted if there is a pending SGI (Software Generated Interrupt) because it will be lost after GIC's power-cycling. Like it was done by the old Tegra20 CPUIDLE driver.

v2: - Added patches to enable the new cpuidle driver in the defconfigs:

ARM: multi_v7_defconfig: Enable Tegra cpuidle driver
ARM: tegra: Enable Tegra cpuidle driver in tegra_defconfig

- Dropped patches that removed CPUIDLE_FLAG_TIMER_STOP from the idling states because that flag actually doesn't have any negative effects, but still is correct for the case of a local CPU timer on older Tegra SoCs:

cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from Tegra114/124 idle-state
cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from all states

- The "Add unified driver for NVIDIA Tegra SoCs" patch got more polish. Tegra30 and Terga114 states are now squashed into a single common C7 state (following Parker TRM terminology, see 17.2.2.2 Power Management States), more comments added, etc minor changes.

Dmitry Osipenko (14):
ARM: tegra: Remove cpuidle drivers to replace them with a new driver
ARM: tegra: Change tegra_set_cpu_in_lp2() type to void
ARM: tegra: Propagate error from tegra_idle_lp2_last()
ARM: tegra: Compile sleep-tegra20/30.S unconditionally
ARM: tegra: Expose PM functions required for new cpuidle driver
ARM: tegra: Rename some of the newly exposed PM functions
ARM: tegra: Add tegra_pm_park_secondary_cpu()
ARM: tegra: Make outer_disable() open-coded
clk: tegra: Add missing stubs for the case of !CONFIG_PM_SLEEP
cpuidle: Introduce unified driver for NVIDIA Tegra SoCs
cpuidle: tegra: Support CPU cluster power-down state on Tegra30
ARM: tegra: Create simple platform device for cpuidle driver
ARM: multi_v7_defconfig: Enable Tegra cpuidle driver
ARM: tegra: Enable Tegra cpuidle driver in tegra_defconfig

 arch/arm/configs/multi_v7_defconfig           |   1 +
 arch/arm/configs/tegra_defconfig              |   1 +
 arch/arm/mach-tegra/Makefile                  |  23 +-
 arch/arm/mach-tegra/cpuidle-tegra114.c        |  89 -----
 arch/arm/mach-tegra/cpuidle-tegra20.c         | 212 -----------
 arch/arm/mach-tegra/cpuidle-tegra30.c         | 132 -------
 arch/arm/mach-tegra/cpuidle.c                 |  50 ---
 arch/arm/mach-tegra/cpuidle.h                 |  21 --
 arch/arm/mach-tegra/irq.c                     |   3 +-
 arch/arm/mach-tegra/pm.c                      |  50 +--
 arch/arm/mach-tegra/pm.h                      |   4 -
 arch/arm/mach-tegra/reset-handler.S           |  11 -
 arch/arm/mach-tegra/reset.h                   |   9 +-
 arch/arm/mach-tegra/sleep-tegra20.S           | 170 ---------
 arch/arm/mach-tegra/sleep-tegra30.S           |   6 +-
 arch/arm/mach-tegra/sleep.h                   |  15 -
 arch/arm/mach-tegra/tegra.c                   |   7 +-
 drivers/cpuidle/Kconfig.arm                   |   8 +
 drivers/cpuidle/Makefile                      |   1 +
 drivers/cpuidle/cpuidle-tegra.c               | 349 ++++++++++++++++++
 drivers/soc/tegra/Kconfig                     |   1 -
 include/linux/clk/tegra.h                     |  13 +
 include/soc/tegra/cpuidle.h                   |   2 +-
 .../mach-tegra => include/soc/tegra}/irq.h    |   8 +-
 include/soc/tegra/pm.h                        |  31 ++
 25 files changed, 453 insertions(+), 764 deletions(-)
 delete mode 100644 arch/arm/mach-tegra/cpuidle-tegra114.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle-tegra20.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle-tegra30.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle.c
 delete mode 100644 arch/arm/mach-tegra/cpuidle.h
 create mode 100644 drivers/cpuidle/cpuidle-tegra.c
 rename {arch/arm/mach-tegra => include/soc/tegra}/irq.h (59%)
Signature · 1 line
2.23.0
#18 lore raw

30.09.2019 11:26, Thierry Reding пишет:

Quoted 34 lines · Dmitry Osipenko
Quoted 11 lines

Hello,

This series does the following:

1. Unifies Tegra20/30/114 drivers into a single driver and moves it out into common drivers/cpuidle/ directory.

2. Enables CPU cluster power-down idling state on Tegra30.

In the end there is a quite nice clean up of the Tegra CPUIDLE drivers and of the Tegra's arch code in general. Please review, thanks!

I generally like this series and it looks really good from a diffstat point of view. However, removing existing drivers completely and then incrementally add a new one make this impossible to review.

If you think about it, it also makes it really difficult to find what went wrong if at any point in the future we find a regression caused by the new driver. A bisection will always point at the commit that removes the old driver because between that and the point where you add the new driver, CPU idle just doesn't work at all anymore.

While I understand that it's very convenient to just throw away old code and rewrite it from scratch, it's also impractical (and a little rude). It's not how we do things in the kernel. Unless maybe under specific circumstances.

Can you please try and make this a little more iterative? At the very least I'd expect a series where you do all the preliminary work in preparatory patches and then replace the old driver by the new driver in a single patch. That way at least there will be an unambiguous commit in a bisection.

Quoted 5 lines

Ideally, you'd also break up that last conversion patch into smaller incremental patches to make it easier for people to review. Remember that your chances to attract reviewers increases if you make the patches easy to review, which means your patches should be small, logical changes that (ideally) are obviously correct.

Thanks for the detailed explanation, probably this is the same what Jon was asking to do. Now I see what you're are asking for.