Consolidate and improve NVIDIA Tegra CPUIDLE driver(s)
Subsystems (5)
v2 cover Consolidate and improve NVIDIA Tegra CPUIDLE driver(s)
Hello,
I was spending quite some time recently trying to hunt down CPU-suspend bug on Tegra30 SoC and in the end it was nailed. During that time I realized that the CPU Idle drivers could get some polish and gain new features, thus that's what this series does:
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 driver(s) and of the Tegra's arch code in general. Please review, thanks!
Changelog:
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 (6):
ARM: tegra: Remove cpuidle drivers
ARM: tegra: Expose functions required for cpuidle driver
cpuidle: Add unified driver for NVIDIA Tegra SoCs
cpuidle: tegra: Support CPU cluster power-down on Tegra30
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 | 15 +- 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 | 18 -- arch/arm/mach-tegra/irq.h | 11 - arch/arm/mach-tegra/platsmp.c | 2 - arch/arm/mach-tegra/pm.c | 27 +-- 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 | 190 +--------------- arch/arm/mach-tegra/sleep.h | 13 -- arch/arm/mach-tegra/tegra.c | 7 +- drivers/cpuidle/Kconfig.arm | 8 + drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-tegra.c | 303 +++++++++++++++++++++++++ drivers/soc/tegra/Kconfig | 1 - include/linux/clk/tegra.h | 13 ++ include/soc/tegra/cpuidle.h | 2 +- include/soc/tegra/pm.h | 28 +++ 25 files changed, 375 insertions(+), 794 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 create mode 100644 drivers/cpuidle/cpuidle-tegra.c
Signature · 1 line
2.22.0
PATCH v2 1/6 ARM: tegra: Remove cpuidle drivers
Remove the old drivers to replace them cleanly with a new one later on.
--- 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 | 18 --- 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 | 190 +--------------------- 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, 5 insertions(+), 779 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
@@ -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
@@ -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 -18
@@ -20,28 +20,10 @@#include "board.h" #include "iomap.h" -#include "irq.h" - -#define SGI_MASK 0xFFFF#ifdef CONFIG_PM_SLEEP static void __iomem *tegra_gic_cpu_base; -#endif - -bool tegra_pending_sgi (void ) -{ -u32 pending_set; -void __iomem *distbase =IO_ADDRESS (TEGRA_ARM_INT_DIST_BASE ); - - pending_set =readl_relaxed (distbase +GIC_DIST_PENDING_SET ); -if (pending_set &SGI_MASK ) -return true; - -return false; -} - -#ifdef CONFIG_PM_SLEEP static int tegra_gic_notifier (struct notifier_block *self,unsigned long cmd,void *v) {
arch/arm/mach-tegra/irq.h deleted +0 -11
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 +3 -187
225 lines not on this page · raw message
arch/arm/mach-tegra/sleep.h +0 -12
@@ -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
@@ -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
@@ -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
@@ -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.22.0
PATCH v2 2/6 ARM: tegra: Expose functions required for cpuidle driver
In reply to Dmitry OsipenkoThe upcoming unified CPUIDLE driver will be added to the drivers/cpuidle/ directory and it will require all these Tegra PM-core functions.
--- arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/platsmp.c | 2 -- arch/arm/mach-tegra/pm.c | 16 +++++++--------- arch/arm/mach-tegra/pm.h | 3 --- arch/arm/mach-tegra/sleep.h | 1 - include/linux/clk/tegra.h | 13 +++++++++++++ include/soc/tegra/pm.h | 28 ++++++++++++++++++++++++++++ 7 files changed, 49 insertions(+), 16 deletions(-)
arch/arm/mach-tegra/Makefile +1 -1
@@ -13,7 +13,7 @@ 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-$(CONFIG_SMP) += platsmp.o -obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-y += hotplug.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += sleep-tegra30.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += pm-tegra30.o
arch/arm/mach-tegra/platsmp.c +0 -2
@@ -183,8 +183,6 @@ const struct smp_operations tegra_smp_ops __initconst = { .smp_prepare_cpus = tegra_smp_prepare_cpus, .smp_secondary_init = tegra_secondary_init, .smp_boot_secondary = tegra_boot_secondary, -#ifdef CONFIG_HOTPLUG_CPU .cpu_kill = tegra_cpu_kill, .cpu_die = tegra_cpu_die, -#endif };
arch/arm/mach-tegra/pm.c +7 -9
@@ -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)
@@ -195,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,
@@ -214,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 +0 -3
@@ -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 ); -bool tegra_set_cpu_in_lp2 (void ); -void tegra_idle_lp2_last (void );extern void (*tegra_tear_down_cpu)(void );#ifdef CONFIG_PM_SLEEP
arch/arm/mach-tegra/sleep.h +0 -1
@@ -124,7 +124,6 @@ void tegra30_hotplug_shutdown(void);#endif void tegra20_tear_down_cpu (void ); -int tegra30_sleep_cpu_secondary_finish (unsigned long );void tegra30_tear_down_cpu (void );#endif
include/linux/clk/tegra.h +13 -0
@@ -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 );
include/soc/tegra/pm.h +28 -0
@@ -20,6 +20,12 @@ 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 ); +void tegra_cpu_die (unsigned int cpu);#else static inline enum tegra_suspend_mode tegra_pm_validate_suspend_mode (enum tegra_suspend_mode mode)
@@ -30,6 +36,28 @@ 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 -1 ; +} + +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 -1 ; +} + +static inline void tegra_cpu_die (unsigned int cpu) +{ +}#endif /* CONFIG_PM_SLEEP */ #endif /* __SOC_TEGRA_PM_H__ */
Signature · 1 line
2.22.0
PATCH v2 3/6 cpuidle: Add unified driver for NVIDIA Tegra SoCs
In reply to Dmitry OsipenkoThe 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.
--- arch/arm/mach-tegra/tegra.c | 4 + drivers/cpuidle/Kconfig.arm | 8 + drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-tegra.c | 304 ++++++++++++++++++++++++++++++++ include/soc/tegra/cpuidle.h | 4 + 5 files changed, 321 insertions(+) create mode 100644 drivers/cpuidle/cpuidle-tegra.c
arch/arm/mach-tegra/tegra.c +4 -0
@@ -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[] = {
drivers/cpuidle/Kconfig.arm +8 -0
@@ -76,3 +76,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
@@ -20,6 +20,7 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o 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_TEGRA_CPUIDLE) += cpuidle-tegra.o ############################################################################### # MIPS drivers
drivers/cpuidle/cpuidle-tegra.c new file +304 -0
304 lines not on this page · raw message
include/soc/tegra/cpuidle.h +4 -0
@@ -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.22.0
PATCH v2 4/6 cpuidle: tegra: Support CPU cluster power-down on Tegra30
In reply to Dmitry OsipenkoThe new CPU Idle driver has all necessary features in order to allow the deepest idling state on Tegra30 SoC where the whole CPU cluster is power-gated using the coupled idle state.
Note that outer_disable() now need to be invoked directly since it produces erroneous warning message about secondary CPUs being online because it doesn't know that secondaries are turned off at that point by the cpuidle driver.
--- arch/arm/mach-tegra/pm.c | 4 ++-- drivers/cpuidle/cpuidle-tegra.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/pm.c +2 -2
@@ -146,8 +146,8 @@ 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 (); +if (trusted_foundations_registered () && outer_cache.disable) + outer_cache.disable ();/* * Note that besides of setting up CPU reset vector this firmware
drivers/cpuidle/cpuidle-tegra.c +0 -1
@@ -278,7 +278,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.22.0
PATCH v2 5/6 ARM: multi_v7_defconfig: Enable Tegra cpuidle driver
In reply to Dmitry OsipenkoThe 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
@@ -107,6 +107,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.22.0
PATCH v2 6/6 ARM: tegra: Enable Tegra cpuidle driver in tegra_defconfig
In reply to Dmitry OsipenkoThe 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
@@ -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.22.0
Jon Hunter
maintainerRe: [PATCH v2 1/6] ARM: tegra: Remove cpuidle drivers
In reply to Dmitry OsipenkoQuoted 20 lines · Dmitry Osipenko
Remove the old drivers to replace them cleanly with a new one later on.
Signed-off-by Dmitry Osipenko <[email protected]>--- 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 | 18 --- 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 | 190 +--------------------- arch/arm/mach-tegra/sleep.h | 12 -- arch/arm/mach-tegra/tegra.c | 3 - drivers/soc/tegra/Kconfig | 1 -
Quoted 8 lines
include/soc/tegra/cpuidle.h | 4 - 17 files changed, 5 insertions(+), 779 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
By removing all the above, it is really hard to review the diff. Is there any way you could first consolidate the cpuidle drivers into say the existing arch/arm/mach-tegra/cpuidle-tegra20.c and then move to drivers/cpuidle?
Jon
Signature · 1 line
nvpublic
Jon Hunter
maintainerRe: [PATCH v2 2/6] ARM: tegra: Expose functions required for cpuidle driver
In reply to Dmitry OsipenkoQuoted 58 lines · Dmitry Osipenko
The upcoming unified CPUIDLE driver will be added to the
drivers/cpuidle/directory and it will require all these Tegra PM-core functions.Signed-off-by Dmitry Osipenko <[email protected]>--- arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/platsmp.c | 2 -- arch/arm/mach-tegra/pm.c | 16 +++++++--------- arch/arm/mach-tegra/pm.h | 3 --- arch/arm/mach-tegra/sleep.h | 1 - include/linux/clk/tegra.h | 13 +++++++++++++ include/soc/tegra/pm.h | 28 ++++++++++++++++++++++++++++ 7 files changed, 49 insertions(+), 16 deletions(-)arch/arm/mach-tegra/Makefile +1
-1@@ -13,7 +13,7 @@ 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-$(CONFIG_SMP) += platsmp.o -obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-y += hotplug.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += sleep-tegra30.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += pm-tegra30.oarch/arm/mach-tegra/platsmp.c +0
-2@@ -183,8 +183,6 @@ const struct smp_operations tegra_smp_ops __initconst = { .smp_prepare_cpus = tegra_smp_prepare_cpus, .smp_secondary_init = tegra_secondary_init, .smp_boot_secondary = tegra_boot_secondary, -#ifdef CONFIG_HOTPLUG_CPU .cpu_kill = tegra_cpu_kill, .cpu_die = tegra_cpu_die, -#endif };arch/arm/mach-tegra/pm.c +1
-3@@ -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);
arch/arm/mach-tegra/pm.c bool tegra_set_cpu_in_lp2(void) · line 137
Quoted 9 lines
arch/arm/mach-tegra/pm.c +0
-4@@ -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; }
I think that the commit message should describe what is going on here or this should be a separate change.
Quoted 98 lines
arch/arm/mach-tegra/pm.c +6
-2static int tegra_sleep_cpu (unsigned long v2p)@@ -195,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, @@ -214,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 +0
-3@@ -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 ); -bool tegra_set_cpu_in_lp2 (void ); -void tegra_idle_lp2_last (void );extern void (*tegra_tear_down_cpu)(void );#ifdef CONFIG_PM_SLEEP arch/arm/mach-tegra/sleep.h +0
-1@@ -124,7 +124,6 @@ void tegra30_hotplug_shutdown(void);#endif void tegra20_tear_down_cpu (void ); -int tegra30_sleep_cpu_secondary_finish (unsigned long );void tegra30_tear_down_cpu (void );#endif include/linux/clk/tegra.h +13
-0@@ -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 );include/soc/tegra/pm.h +6
-0@@ -20,6 +20,12 @@ 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 ); +void tegra_cpu_die (unsigned int cpu);#else static inline enum tegra_suspend_mode tegra_pm_validate_suspend_mode (enum tegra_suspend_mode mode)
include/soc/tegra/pm.h tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode) · line 43
Quoted 8 lines
include/soc/tegra/pm.h +5
-0@@ -30,6 +36,28 @@ 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 -1 ; +}
-ENOTSUPP?
Jon
Signature · 1 line
nvpublic
Re: [PATCH v2 1/6] ARM: tegra: Remove cpuidle drivers
In reply to Jon Hunter11.07.2019 12:26, Jon Hunter пишет:
Quoted 31 lines · Dmitry Osipenko
Quoted 20 lines
Remove the old drivers to replace them cleanly with a new one later on.
Signed-off-by Dmitry Osipenko <[email protected]>--- 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 | 18 --- 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 | 190 +--------------------- arch/arm/mach-tegra/sleep.h | 12 -- arch/arm/mach-tegra/tegra.c | 3 - drivers/soc/tegra/Kconfig | 1 -Quoted 8 lines
include/soc/tegra/cpuidle.h | 4 - 17 files changed, 5 insertions(+), 779 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
Quoted 4 lines
By removing all the above, it is really hard to review the diff. Is there any way you could first consolidate the cpuidle drivers into say the existing
arch/arm/mach-tegra/cpuidle-tegra20.cand then move todrivers/cpuidle?
I'm afraid that it will make reviewing even more difficult because everything that is removed here is not returned in the further patches. The new driver is based on the older ones, but I wrote it from scratch and it's not only looks different, but also works a bit different as you may see.
Could you please clarify what exactly makes it hard to review? The diff looks pretty clean to me, while squashing everything into existing driver should be quite a mess.
Re: [PATCH v2 2/6] ARM: tegra: Expose functions required for cpuidle driver
In reply to Jon Hunter11.07.2019 15:42, Jon Hunter пишет:
Quoted 63 lines · Dmitry Osipenko
Quoted 61 lines
The upcoming unified CPUIDLE driver will be added to the
drivers/cpuidle/directory and it will require all these Tegra PM-core functions.Signed-off-by Dmitry Osipenko <[email protected]>--- arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/platsmp.c | 2 -- arch/arm/mach-tegra/pm.c | 16 +++++++--------- arch/arm/mach-tegra/pm.h | 3 --- arch/arm/mach-tegra/sleep.h | 1 - include/linux/clk/tegra.h | 13 +++++++++++++ include/soc/tegra/pm.h | 28 ++++++++++++++++++++++++++++ 7 files changed, 49 insertions(+), 16 deletions(-)arch/arm/mach-tegra/Makefile +1
-1@@ -13,7 +13,7 @@ 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-$(CONFIG_SMP) += platsmp.o -obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-y += hotplug.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += sleep-tegra30.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += pm-tegra30.oarch/arm/mach-tegra/platsmp.c +0
-2@@ -183,8 +183,6 @@ const struct smp_operations tegra_smp_ops __initconst = { .smp_prepare_cpus = tegra_smp_prepare_cpus, .smp_secondary_init = tegra_secondary_init, .smp_boot_secondary = tegra_boot_secondary, -#ifdef CONFIG_HOTPLUG_CPU .cpu_kill = tegra_cpu_kill, .cpu_die = tegra_cpu_die, -#endif };arch/arm/mach-tegra/pm.c +1
-3@@ -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);
Quoted 9 lines
arch/arm/mach-tegra/pm.c bool tegra_set_cpu_in_lp2(void) · line 137
Quoted 6 lines
arch/arm/mach-tegra/pm.c +0
-4-if ((phy_cpu_id ==0 ) &&cpumask_equal (cpu_lp2_mask, cpu_online_mask)) - last_cpu = true; -spin_unlock (&tegra_lp2_lock); -return last_cpu; }I think that the commit message should describe what is going on here or this should be a separate change.
Indeed, it could be not very obvious what's going on here without a thorough review. I'll factor out all these minor changes into separate commits.
In particular there is no need to know whether CPU is the "last_cpu" for the new driver because CPU0 is always the "last" since it awaits for the secondaries in the coupled state.
Quoted 99 lines
Quoted 99 lines
arch/arm/mach-tegra/pm.c +6
-2static int tegra_sleep_cpu (unsigned long v2p)@@ -195,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, @@ -214,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 +0
-3@@ -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 ); -bool tegra_set_cpu_in_lp2 (void ); -void tegra_idle_lp2_last (void );extern void (*tegra_tear_down_cpu)(void );#ifdef CONFIG_PM_SLEEP arch/arm/mach-tegra/sleep.h +0
-1@@ -124,7 +124,6 @@ void tegra30_hotplug_shutdown(void);#endif void tegra20_tear_down_cpu (void ); -int tegra30_sleep_cpu_secondary_finish (unsigned long );void tegra30_tear_down_cpu (void );#endif include/linux/clk/tegra.h +13
-0@@ -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 );include/soc/tegra/pm.h +6
-0@@ -20,6 +20,12 @@ 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 ); +void tegra_cpu_die (unsigned int cpu);#else static inline enum tegra_suspend_mode tegra_pm_validate_suspend_mode (enum tegra_suspend_mode mode)@@ -30,6 +36,28 @@ tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)static inline void tegra_resume (void ) {
Quoted 8 lines
include/soc/tegra/pm.h tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode) · line 43
Quoted 6 lines
include/soc/tegra/pm.h +5
-0} + +static inline int tegra30_sleep_cpu_secondary_finish (unsigned long arg) +{ +return -1 ; +}
-ENOTSUPP?
Good point, thanks!
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Re: [PATCH v2 3/6] cpuidle: Add unified driver for NVIDIA Tegra SoCs
In reply to Dmitry Osipenko11.07.2019 6:13, Dmitry Osipenko пишет:
Quoted 191 lines
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.
Signed-off-by Dmitry Osipenko <[email protected]>--- arch/arm/mach-tegra/tegra.c | 4 + drivers/cpuidle/Kconfig.arm | 8 + drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-tegra.c | 304 ++++++++++++++++++++++++++++++++ include/soc/tegra/cpuidle.h | 4 + 5 files changed, 321 insertions(+) create mode 100644 drivers/cpuidle/cpuidle-tegra.carch/arm/mach-tegra/tegra.c +4
-0@@ -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[] = {drivers/cpuidle/Kconfig.arm +8
-0@@ -76,3 +76,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@@ -20,6 +20,7 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o 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_TEGRA_CPUIDLE) += cpuidle-tegra.o ############################################################################### # MIPS driversdrivers/cpuidle/cpuidle-tegra.c new file +120
-0@@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* CPU idle driver for Tegra CPUs +* +* Copyright (c) 2010-2013, NVIDIA Corporation. +* Copyright (c) 2011 Google, Inc. +* Author: Colin Cross <[email protected]> +* Gary King <[email protected]> +* +* Rework for 3.3 by Peter De Schrijver <[email protected]> +* +* Tegra20/124 driver unification by Dmitry Osipenko <[email protected]> +*/ + +#include <linux/cpuidle.h> +#include <linux/cpumask.h> +#include <linux/cpu_pm.h> +#include <linux/errno.h> +#include <linux/ktime.h> +#include <linux/platform_device.h> +#include <linux/types.h> + +#include <linux/clk/tegra.h> +#include <linux/firmware/trusted_foundations.h> + +#include <soc/tegra/cpuidle.h> +#include <soc/tegra/flowctrl.h> +#include <soc/tegra/fuse.h> +#include <soc/tegra/pm.h> + +#include <asm/cpuidle.h> +#include <asm/firmware.h> +#include <asm/smp_plat.h> +#include <asm/suspend.h> + +#define TEGRA_C1 0 +#define TEGRA_C7 1 +#define TEGRA_CC6 2 + +static atomic_t tegra_idle_barrier; + +static inline bool tegra_cpuidle_using_firmware (void ) +{ +return firmware_ops->prepare_idle && firmware_ops->do_idle; +} + +static int tegra_shutdown_secondary_cpu (unsigned long cpu) +{ +tegra_cpu_die (cpu); + +return -EINVAL ; +} + +static int tegra_await_secondary_cpus_shutdown (void ) +{ +ktime_t timeout =ktime_add_ms (ktime_get (),1 ); + +/* +* The boot CPU shall await for the secondaries shutdown in order +* to power-off CPU's cluster safely. +*/ +do { +if (tegra_cpu_rail_off_ready ()) +return 0 ; + + }while (ktime_compare (ktime_get (), timeout) <0 ); + +return -ETIMEDOUT ; +} + +static void tegra_wake_up_secondary_cpus (void ) +{ +unsigned int cpu, lcpu; + +for_each_cpu (lcpu, cpu_online_mask) { + cpu =cpu_logical_map (lcpu); + +if (cpu >0 ) { +tegra_enable_cpu_clock (cpu); +tegra_cpu_out_of_reset (cpu); +flowctrl_write_cpu_halt (cpu,0 ); + } + } +} + +static int tegra_cpuidle_cc6_enter (void ) +{ +int err; + + err =tegra_await_secondary_cpus_shutdown (); +if (err) +return err; + + err =tegra_idle_lp2_last (); + +tegra_wake_up_secondary_cpus (); + +return err; +} + +static int tegra_cpuidle_c7_enter (void ) +{ +int err; + +if (tegra_cpuidle_using_firmware ()) { + err =call_firmware_op (prepare_idle,TF_PM_MODE_LP2_NOFLUSH_L2 ); +if (err) +return err; + +return call_firmware_op (do_idle,0 ); + } + +return cpu_suspend (0 , tegra30_sleep_cpu_secondary_finish); +} + +static int tegra_cpuidle_enter (struct cpuidle_device *dev, +int index,unsigned int cpu) +{ +int err; +
drivers/cpuidle/cpuidle-tegra.c line 130
Quoted 10 lines
drivers/cpuidle/cpuidle-tegra.c new file +10
-0+local_fiq_disable (); +tegra_set_cpu_in_lp2 (); +cpu_pm_enter (); + +switch (index) { +case TEGRA_C7 : + err =tegra_cpuidle_c7_enter (); +break ; +case TEGRA_CC6 : +cpuidle_coupled_parallel_barrier (dev, &tegra_idle_barrier);
I realized that this is not very correct. We still need to do a proper barrier with SGI checking in order to bail out if other CPU sent IPI during of the awaiting for a coupled barrier to avoid the overhead of unnecessary power-gating. Will correct that in the next revision.
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Jon Hunter
maintainerRe: [PATCH v2 1/6] ARM: tegra: Remove cpuidle drivers
In reply to Dmitry OsipenkoQuoted 43 lines · Dmitry Osipenko
11.07.2019 12:26, Jon Hunter пишет:
Quoted 31 lines · Dmitry Osipenko
Quoted 20 lines
Remove the old drivers to replace them cleanly with a new one later on.
Signed-off-by Dmitry Osipenko <[email protected]>--- 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 | 18 --- 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 | 190 +--------------------- arch/arm/mach-tegra/sleep.h | 12 -- arch/arm/mach-tegra/tegra.c | 3 - drivers/soc/tegra/Kconfig | 1 -Quoted 8 lines
include/soc/tegra/cpuidle.h | 4 - 17 files changed, 5 insertions(+), 779 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.hQuoted 4 lines
By removing all the above, it is really hard to review the diff. Is there any way you could first consolidate the cpuidle drivers into say the existing
arch/arm/mach-tegra/cpuidle-tegra20.cand then move todrivers/cpuidle?I'm afraid that it will make reviewing even more difficult because everything that is removed here is not returned in the further patches. The new driver is based on the older ones, but I wrote it from scratch and it's not only looks different, but also works a bit different as you may see.
Quoted 3 lines
Could you please clarify what exactly makes it hard to review? The diff looks pretty clean to me, while squashing everything into existing driver should be quite a mess.
Ideally a patch should standalone and can be reviewed by itself. However, to review this, we need to review patches 1, 2 and 3 at the same time. So IMO it is not that convenient from a reviewers perspective. Furthermore, patches 1 and 3 are large and so easy to miss something.
Is there really no way to have a patch to combined the existing drivers, then a patch to convert them into the newer rewritten version you have implemented, then move the driver?
Jon
Signature · 1 line
nvpublic
Re: [PATCH v2 1/6] ARM: tegra: Remove cpuidle drivers
12.07.2019 12:39, Jon Hunter пишет:
Quoted 55 lines · Dmitry Osipenko
Quoted 43 lines
11.07.2019 12:26, Jon Hunter пишет:
Quoted 31 lines · Dmitry Osipenko
Quoted 20 lines
Remove the old drivers to replace them cleanly with a new one later on.
Signed-off-by Dmitry Osipenko <[email protected]>--- 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 | 18 --- 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 | 190 +--------------------- arch/arm/mach-tegra/sleep.h | 12 -- arch/arm/mach-tegra/tegra.c | 3 - drivers/soc/tegra/Kconfig | 1 -Quoted 8 lines
include/soc/tegra/cpuidle.h | 4 - 17 files changed, 5 insertions(+), 779 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.hQuoted 4 lines
By removing all the above, it is really hard to review the diff. Is there any way you could first consolidate the cpuidle drivers into say the existing
arch/arm/mach-tegra/cpuidle-tegra20.cand then move todrivers/cpuidle?I'm afraid that it will make reviewing even more difficult because everything that is removed here is not returned in the further patches. The new driver is based on the older ones, but I wrote it from scratch and it's not only looks different, but also works a bit different as you may see.
Quoted 3 lines
Could you please clarify what exactly makes it hard to review? The diff looks pretty clean to me, while squashing everything into existing driver should be quite a mess.
Ideally a patch should standalone and can be reviewed by itself. However, to review this, we need to review patches 1, 2 and 3 at the same time. So IMO it is not that convenient from a reviewers perspective. Furthermore, patches 1 and 3 are large and so easy to miss something.
Quoted 3 lines
Is there really no way to have a patch to combined the existing drivers, then a patch to convert them into the newer rewritten version you have implemented, then move the driver?
Probably I spent a bit too much time with that code, so now yours suggestion looks to me like an unnecessary step. But I will try and see how it goes, at least it should be possible to break down the patch 1 a bit more, hopefully it will help to better understand what's going on in the further patches if you're not familiar or don't remember how it all works.
Re: [PATCH v2 3/6] cpuidle: Add unified driver for NVIDIA Tegra SoCs
In reply to Dmitry Osipenko11.07.2019 21:35, Dmitry Osipenko пишет:
Quoted 199 lines
11.07.2019 6:13, Dmitry Osipenko пишет:
Quoted 198 lines
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.
Signed-off-by Dmitry Osipenko <[email protected]>--- arch/arm/mach-tegra/tegra.c | 4 + drivers/cpuidle/Kconfig.arm | 8 + drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-tegra.c | 304 ++++++++++++++++++++++++++++++++ include/soc/tegra/cpuidle.h | 4 + 5 files changed, 321 insertions(+) create mode 100644 drivers/cpuidle/cpuidle-tegra.carch/arm/mach-tegra/tegra.c +4
-0@@ -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[] = {drivers/cpuidle/Kconfig.arm +8
-0@@ -76,3 +76,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@@ -20,6 +20,7 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o 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_TEGRA_CPUIDLE) += cpuidle-tegra.o ############################################################################### # MIPS driversdrivers/cpuidle/cpuidle-tegra.c new file +127
-0@@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* CPU idle driver for Tegra CPUs +* +* Copyright (c) 2010-2013, NVIDIA Corporation. +* Copyright (c) 2011 Google, Inc. +* Author: Colin Cross <[email protected]> +* Gary King <[email protected]> +* +* Rework for 3.3 by Peter De Schrijver <[email protected]> +* +* Tegra20/124 driver unification by Dmitry Osipenko <[email protected]> +*/ + +#include <linux/cpuidle.h> +#include <linux/cpumask.h> +#include <linux/cpu_pm.h> +#include <linux/errno.h> +#include <linux/ktime.h> +#include <linux/platform_device.h> +#include <linux/types.h> + +#include <linux/clk/tegra.h> +#include <linux/firmware/trusted_foundations.h> + +#include <soc/tegra/cpuidle.h> +#include <soc/tegra/flowctrl.h> +#include <soc/tegra/fuse.h> +#include <soc/tegra/pm.h> + +#include <asm/cpuidle.h> +#include <asm/firmware.h> +#include <asm/smp_plat.h> +#include <asm/suspend.h> + +#define TEGRA_C1 0 +#define TEGRA_C7 1 +#define TEGRA_CC6 2 + +static atomic_t tegra_idle_barrier; + +static inline bool tegra_cpuidle_using_firmware (void ) +{ +return firmware_ops->prepare_idle && firmware_ops->do_idle; +} + +static int tegra_shutdown_secondary_cpu (unsigned long cpu) +{ +tegra_cpu_die (cpu); + +return -EINVAL ; +} + +static int tegra_await_secondary_cpus_shutdown (void ) +{ +ktime_t timeout =ktime_add_ms (ktime_get (),1 ); + +/* +* The boot CPU shall await for the secondaries shutdown in order +* to power-off CPU's cluster safely. +*/ +do { +if (tegra_cpu_rail_off_ready ()) +return 0 ; + + }while (ktime_compare (ktime_get (), timeout) <0 ); + +return -ETIMEDOUT ; +} + +static void tegra_wake_up_secondary_cpus (void ) +{ +unsigned int cpu, lcpu; + +for_each_cpu (lcpu, cpu_online_mask) { + cpu =cpu_logical_map (lcpu); + +if (cpu >0 ) { +tegra_enable_cpu_clock (cpu); +tegra_cpu_out_of_reset (cpu); +flowctrl_write_cpu_halt (cpu,0 ); + } + } +} + +static int tegra_cpuidle_cc6_enter (void ) +{ +int err; + + err =tegra_await_secondary_cpus_shutdown (); +if (err) +return err; + + err =tegra_idle_lp2_last (); + +tegra_wake_up_secondary_cpus (); + +return err; +} + +static int tegra_cpuidle_c7_enter (void ) +{ +int err; + +if (tegra_cpuidle_using_firmware ()) { + err =call_firmware_op (prepare_idle,TF_PM_MODE_LP2_NOFLUSH_L2 ); +if (err) +return err; + +return call_firmware_op (do_idle,0 ); + } + +return cpu_suspend (0 , tegra30_sleep_cpu_secondary_finish); +} + +static int tegra_cpuidle_enter (struct cpuidle_device *dev, +int index,unsigned int cpu) +{ +int err; + +local_fiq_disable (); +tegra_set_cpu_in_lp2 (); +cpu_pm_enter (); + +switch (index) { +case TEGRA_C7 : + err =tegra_cpuidle_c7_enter ();
Quoted 8 lines
drivers/cpuidle/cpuidle-tegra.c line 130
Quoted 3 lines
drivers/cpuidle/cpuidle-tegra.c new file +3
-0+break ; +case TEGRA_CC6 : +cpuidle_coupled_parallel_barrier (dev, &tegra_idle_barrier);I realized that this is not very correct. We still need to do a proper barrier with SGI checking in order to bail out if other CPU sent IPI during of the awaiting for a coupled barrier to avoid the overhead of unnecessary power-gating. Will correct that in the next revision.
UPDATE: Actually, turned out it's even a necessity to handle the SGI because GIC's driver doesn't save and replay SGI across CPU cluster PM.
Re: [PATCH v2 1/6] ARM: tegra: Remove cpuidle drivers
In reply to Dmitry Osipenko12.07.2019 19:23, Dmitry Osipenko пишет:
Quoted 60 lines
12.07.2019 12:39, Jon Hunter пишет:
Quoted 55 lines · Dmitry Osipenko
Quoted 43 lines
11.07.2019 12:26, Jon Hunter пишет:
Quoted 31 lines · Dmitry Osipenko
Quoted 20 lines
Remove the old drivers to replace them cleanly with a new one later on.
Signed-off-by Dmitry Osipenko <[email protected]>--- 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 | 18 --- 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 | 190 +--------------------- arch/arm/mach-tegra/sleep.h | 12 -- arch/arm/mach-tegra/tegra.c | 3 - drivers/soc/tegra/Kconfig | 1 -Quoted 8 lines
include/soc/tegra/cpuidle.h | 4 - 17 files changed, 5 insertions(+), 779 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.hQuoted 4 lines
By removing all the above, it is really hard to review the diff. Is there any way you could first consolidate the cpuidle drivers into say the existing
arch/arm/mach-tegra/cpuidle-tegra20.cand then move todrivers/cpuidle?I'm afraid that it will make reviewing even more difficult because everything that is removed here is not returned in the further patches. The new driver is based on the older ones, but I wrote it from scratch and it's not only looks different, but also works a bit different as you may see.
Quoted 3 lines
Could you please clarify what exactly makes it hard to review? The diff looks pretty clean to me, while squashing everything into existing driver should be quite a mess.
Ideally a patch should standalone and can be reviewed by itself. However, to review this, we need to review patches 1, 2 and 3 at the same time. So IMO it is not that convenient from a reviewers perspective. Furthermore, patches 1 and 3 are large and so easy to miss something.
Quoted 3 lines
Is there really no way to have a patch to combined the existing drivers, then a patch to convert them into the newer rewritten version you have implemented, then move the driver?
Quoted 6 lines
Probably I spent a bit too much time with that code, so now yours suggestion looks to me like an unnecessary step. But I will try and see how it goes, at least it should be possible to break down the patch 1 a bit more, hopefully it will help to better understand what's going on in the further patches if you're not familiar or don't remember how it all works.
I tried (in several attempts) and couldn't find a way how to meaningfully squash the old drivers. It's a lot of unnecessary churning that won't help with reviewing of the code at all because new driver is structured differently and beating of old drivers until they resemble the new one just not worth it. I'll write a bit more detailed commit message, emphasizing the details, hope it will be helpful. The old drivers are ~200 LOC each and the new one will be ~300 LOC + 50 lines of comments, I don't think that it's really very hard to review as it it may initially looked like to you, Jon.
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel