* [PATCH v1 0/6] Consolidate and improve NVIDIA Tegra CPUIDLE driver(s)
@ 2019-07-07 23:38 Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 1/6] ARM: tegra: Remove cpuidle drivers Dmitry Osipenko
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Dmitry Osipenko @ 2019-07-07 23:38 UTC (permalink / raw)
To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
Rafael J. Wysocki, Daniel Lezcano
Cc: linux-pm, linux-tegra, linux-kernel
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.
3. Removes CPUIDLE_FLAG_TIMER_STOP from all of the states since that
flag is not relevant anymore.
In the end there is a quite nice clean up of the Terga CPUIDLE driver(s)
and of the Tegra's arch code in general. Please review, thanks!
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
cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from Tegra114/124
idle-state
cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from all states
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 | 232 +++++++++++++++++++++++++
drivers/soc/tegra/Kconfig | 1 -
include/linux/clk/tegra.h | 13 ++
include/soc/tegra/cpuidle.h | 2 +-
include/soc/tegra/pm.h | 28 +++
23 files changed, 302 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
--
2.22.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v1 1/6] ARM: tegra: Remove cpuidle drivers
2019-07-07 23:38 [PATCH v1 0/6] Consolidate and improve NVIDIA Tegra CPUIDLE driver(s) Dmitry Osipenko
@ 2019-07-07 23:38 ` Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 2/6] ARM: tegra: Expose functions required for cpuidle driver Dmitry Osipenko
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Dmitry Osipenko @ 2019-07-07 23:38 UTC (permalink / raw)
To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
Rafael J. Wysocki, Daniel Lezcano
Cc: linux-pm, linux-tegra, linux-kernel
Remove the old drivers to replace them cleanly with a new one later on.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
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
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 6c1dff2eccc2..5d93a0b36866 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -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
diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c
deleted file mode 100644
index 5118f777fd66..000000000000
--- a/arch/arm/mach-tegra/cpuidle-tegra114.c
+++ /dev/null
@@ -1,89 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
- */
-
-#include <asm/firmware.h>
-#include <linux/tick.h>
-#include <linux/cpuidle.h>
-#include <linux/cpu_pm.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <linux/firmware/trusted_foundations.h>
-
-#include <asm/cpuidle.h>
-#include <asm/smp_plat.h>
-#include <asm/suspend.h>
-#include <asm/psci.h>
-
-#include "cpuidle.h"
-#include "pm.h"
-#include "sleep.h"
-
-#ifdef CONFIG_PM_SLEEP
-#define TEGRA114_MAX_STATES 2
-#else
-#define TEGRA114_MAX_STATES 1
-#endif
-
-#ifdef CONFIG_PM_SLEEP
-static int tegra114_idle_power_down(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- local_fiq_disable();
-
- tegra_set_cpu_in_lp2();
- cpu_pm_enter();
-
- call_firmware_op(prepare_idle, TF_PM_MODE_LP2_NOFLUSH_L2);
-
- /* Do suspend by ourselves if the firmware does not implement it */
- if (call_firmware_op(do_idle, 0) == -ENOSYS)
- cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
-
- cpu_pm_exit();
- tegra_clear_cpu_in_lp2();
-
- local_fiq_enable();
-
- return index;
-}
-
-static void tegra114_idle_enter_s2idle(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- tegra114_idle_power_down(dev, drv, index);
-}
-#endif
-
-static struct cpuidle_driver tegra_idle_driver = {
- .name = "tegra_idle",
- .owner = THIS_MODULE,
- .state_count = TEGRA114_MAX_STATES,
- .states = {
- [0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
-#ifdef CONFIG_PM_SLEEP
- [1] = {
- .enter = tegra114_idle_power_down,
- .enter_s2idle = tegra114_idle_enter_s2idle,
- .exit_latency = 500,
- .target_residency = 1000,
- .flags = CPUIDLE_FLAG_TIMER_STOP,
- .power_usage = 0,
- .name = "powered-down",
- .desc = "CPU power gated",
- },
-#endif
- },
-};
-
-int __init tegra114_cpuidle_init(void)
-{
- if (!psci_smp_available())
- return cpuidle_register(&tegra_idle_driver, NULL);
-
- return 0;
-}
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
deleted file mode 100644
index 2447427cb4a8..000000000000
--- a/arch/arm/mach-tegra/cpuidle-tegra20.c
+++ /dev/null
@@ -1,212 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * CPU idle driver for Tegra CPUs
- *
- * Copyright (c) 2010-2012, NVIDIA Corporation.
- * Copyright (c) 2011 Google, Inc.
- * Author: Colin Cross <ccross@android.com>
- * Gary King <gking@nvidia.com>
- *
- * Rework for 3.3 by Peter De Schrijver <pdeschrijver@nvidia.com>
- */
-
-#include <linux/clk/tegra.h>
-#include <linux/tick.h>
-#include <linux/cpuidle.h>
-#include <linux/cpu_pm.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <soc/tegra/flowctrl.h>
-
-#include <asm/cpuidle.h>
-#include <asm/smp_plat.h>
-#include <asm/suspend.h>
-
-#include "cpuidle.h"
-#include "iomap.h"
-#include "irq.h"
-#include "pm.h"
-#include "reset.h"
-#include "sleep.h"
-
-#ifdef CONFIG_PM_SLEEP
-static bool abort_flag;
-static atomic_t abort_barrier;
-static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index);
-#define TEGRA20_MAX_STATES 2
-#else
-#define TEGRA20_MAX_STATES 1
-#endif
-
-static struct cpuidle_driver tegra_idle_driver = {
- .name = "tegra_idle",
- .owner = THIS_MODULE,
- .states = {
- ARM_CPUIDLE_WFI_STATE_PWR(600),
-#ifdef CONFIG_PM_SLEEP
- {
- .enter = tegra20_idle_lp2_coupled,
- .exit_latency = 5000,
- .target_residency = 10000,
- .power_usage = 0,
- .flags = CPUIDLE_FLAG_COUPLED |
- CPUIDLE_FLAG_TIMER_STOP,
- .name = "powered-down",
- .desc = "CPU power gated",
- },
-#endif
- },
- .state_count = TEGRA20_MAX_STATES,
- .safe_state_index = 0,
-};
-
-#ifdef CONFIG_PM_SLEEP
-#ifdef CONFIG_SMP
-static int tegra20_reset_sleeping_cpu_1(void)
-{
- int ret = 0;
-
- tegra_pen_lock();
-
- if (readb(tegra20_cpu1_resettable_status) == CPU_RESETTABLE)
- tegra20_cpu_shutdown(1);
- else
- ret = -EINVAL;
-
- tegra_pen_unlock();
-
- return ret;
-}
-
-static void tegra20_wake_cpu1_from_reset(void)
-{
- tegra_pen_lock();
-
- tegra20_cpu_clear_resettable();
-
- /* enable cpu clock on cpu */
- tegra_enable_cpu_clock(1);
-
- /* take the CPU out of reset */
- tegra_cpu_out_of_reset(1);
-
- /* unhalt the cpu */
- flowctrl_write_cpu_halt(1, 0);
-
- tegra_pen_unlock();
-}
-
-static int tegra20_reset_cpu_1(void)
-{
- if (!cpu_online(1) || !tegra20_reset_sleeping_cpu_1())
- return 0;
-
- tegra20_wake_cpu1_from_reset();
- return -EBUSY;
-}
-#else
-static inline void tegra20_wake_cpu1_from_reset(void)
-{
-}
-
-static inline int tegra20_reset_cpu_1(void)
-{
- return 0;
-}
-#endif
-
-static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- while (tegra20_cpu_is_resettable_soon())
- cpu_relax();
-
- if (tegra20_reset_cpu_1() || !tegra_cpu_rail_off_ready())
- return false;
-
- tegra_idle_lp2_last();
-
- if (cpu_online(1))
- tegra20_wake_cpu1_from_reset();
-
- return true;
-}
-
-#ifdef CONFIG_SMP
-static bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- cpu_suspend(0, tegra20_sleep_cpu_secondary_finish);
-
- tegra20_cpu_clear_resettable();
-
- return true;
-}
-#else
-static inline bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- return true;
-}
-#endif
-
-static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- bool entered_lp2 = false;
-
- if (tegra_pending_sgi())
- WRITE_ONCE(abort_flag, true);
-
- cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
-
- if (abort_flag) {
- cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
- abort_flag = false; /* clean flag for next coming */
- return -EINTR;
- }
-
- local_fiq_disable();
-
- tegra_set_cpu_in_lp2();
- cpu_pm_enter();
-
- if (dev->cpu == 0)
- entered_lp2 = tegra20_cpu_cluster_power_down(dev, drv, index);
- else
- entered_lp2 = tegra20_idle_enter_lp2_cpu_1(dev, drv, index);
-
- cpu_pm_exit();
- tegra_clear_cpu_in_lp2();
-
- local_fiq_enable();
-
- smp_rmb();
-
- return entered_lp2 ? index : 0;
-}
-#endif
-
-/*
- * Tegra20 HW appears to have a bug such that PCIe device interrupts, whether
- * they are legacy IRQs or MSI, are lost when LP2 is enabled. To work around
- * this, simply disable LP2 if the PCI driver and DT node are both enabled.
- */
-void tegra20_cpuidle_pcie_irqs_in_use(void)
-{
- pr_info_once(
- "Disabling cpuidle LP2 state, since PCIe IRQs are in use\n");
- tegra_idle_driver.states[1].disabled = true;
-}
-
-int __init tegra20_cpuidle_init(void)
-{
- return cpuidle_register(&tegra_idle_driver, cpu_possible_mask);
-}
diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
deleted file mode 100644
index c6128526877d..000000000000
--- a/arch/arm/mach-tegra/cpuidle-tegra30.c
+++ /dev/null
@@ -1,132 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * CPU idle driver for Tegra CPUs
- *
- * Copyright (c) 2010-2012, NVIDIA Corporation.
- * Copyright (c) 2011 Google, Inc.
- * Author: Colin Cross <ccross@android.com>
- * Gary King <gking@nvidia.com>
- *
- * Rework for 3.3 by Peter De Schrijver <pdeschrijver@nvidia.com>
- */
-
-#include <linux/clk/tegra.h>
-#include <linux/tick.h>
-#include <linux/cpuidle.h>
-#include <linux/cpu_pm.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <asm/cpuidle.h>
-#include <asm/smp_plat.h>
-#include <asm/suspend.h>
-
-#include "cpuidle.h"
-#include "pm.h"
-#include "sleep.h"
-
-#ifdef CONFIG_PM_SLEEP
-static int tegra30_idle_lp2(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index);
-#endif
-
-static struct cpuidle_driver tegra_idle_driver = {
- .name = "tegra_idle",
- .owner = THIS_MODULE,
-#ifdef CONFIG_PM_SLEEP
- .state_count = 2,
-#else
- .state_count = 1,
-#endif
- .states = {
- [0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
-#ifdef CONFIG_PM_SLEEP
- [1] = {
- .enter = tegra30_idle_lp2,
- .exit_latency = 2000,
- .target_residency = 2200,
- .power_usage = 0,
- .flags = CPUIDLE_FLAG_TIMER_STOP,
- .name = "powered-down",
- .desc = "CPU power gated",
- },
-#endif
- },
-};
-
-#ifdef CONFIG_PM_SLEEP
-static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- /* All CPUs entering LP2 is not working.
- * Don't let CPU0 enter LP2 when any secondary CPU is online.
- */
- if (num_online_cpus() > 1 || !tegra_cpu_rail_off_ready()) {
- cpu_do_idle();
- return false;
- }
-
- tegra_idle_lp2_last();
-
- return true;
-}
-
-#ifdef CONFIG_SMP
-static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- smp_wmb();
-
- cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
-
- return true;
-}
-#else
-static inline bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- return true;
-}
-#endif
-
-static int tegra30_idle_lp2(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- bool entered_lp2 = false;
- bool last_cpu;
-
- local_fiq_disable();
-
- last_cpu = tegra_set_cpu_in_lp2();
- cpu_pm_enter();
-
- if (dev->cpu == 0) {
- if (last_cpu)
- entered_lp2 = tegra30_cpu_cluster_power_down(dev, drv,
- index);
- else
- cpu_do_idle();
- } else {
- entered_lp2 = tegra30_cpu_core_power_down(dev, drv, index);
- }
-
- cpu_pm_exit();
- tegra_clear_cpu_in_lp2();
-
- local_fiq_enable();
-
- smp_rmb();
-
- return (entered_lp2) ? index : 0;
-}
-#endif
-
-int __init tegra30_cpuidle_init(void)
-{
- return cpuidle_register(&tegra_idle_driver, NULL);
-}
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
deleted file mode 100644
index d565c44cfc93..000000000000
--- a/arch/arm/mach-tegra/cpuidle.c
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * arch/arm/mach-tegra/cpuidle.c
- *
- * CPU idle driver for Tegra CPUs
- *
- * Copyright (c) 2010-2012, NVIDIA Corporation.
- * Copyright (c) 2011 Google, Inc.
- * Author: Colin Cross <ccross@android.com>
- * Gary King <gking@nvidia.com>
- *
- * Rework for 3.3 by Peter De Schrijver <pdeschrijver@nvidia.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <soc/tegra/fuse.h>
-
-#include "cpuidle.h"
-
-void __init tegra_cpuidle_init(void)
-{
- switch (tegra_get_chip_id()) {
- case TEGRA20:
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
- tegra20_cpuidle_init();
- break;
- case TEGRA30:
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC))
- tegra30_cpuidle_init();
- break;
- case TEGRA114:
- case TEGRA124:
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) ||
- IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC))
- tegra114_cpuidle_init();
- break;
- }
-}
-
-void tegra_cpuidle_pcie_irqs_in_use(void)
-{
- switch (tegra_get_chip_id()) {
- case TEGRA20:
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
- tegra20_cpuidle_pcie_irqs_in_use();
- break;
- }
-}
diff --git a/arch/arm/mach-tegra/cpuidle.h b/arch/arm/mach-tegra/cpuidle.h
deleted file mode 100644
index 4e1f459f5bd8..000000000000
--- a/arch/arm/mach-tegra/cpuidle.h
+++ /dev/null
@@ -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
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index ace7a390b5fe..22fca820f5c0 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -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)
{
diff --git a/arch/arm/mach-tegra/irq.h b/arch/arm/mach-tegra/irq.h
deleted file mode 100644
index 7a94cf121448..000000000000
--- a/arch/arm/mach-tegra/irq.h
+++ /dev/null
@@ -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
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 3cab81b82866..6aaacb5757e1 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -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)
{
/*
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index 569151b3edc0..1e51a9b636eb 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -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);
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 67b763fea005..df44828a34d3 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -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
diff --git a/arch/arm/mach-tegra/reset.h b/arch/arm/mach-tegra/reset.h
index a4cfc08159f6..51265592cb1a 100644
--- a/arch/arm/mach-tegra/reset.h
+++ b/arch/arm/mach-tegra/reset.h
@@ -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 \
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index 9a89f30d53ca..6fb14f76235f 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -43,9 +43,6 @@
#define APB_MISC_XM2CFGCPADCTRL2 0x8e4
#define APB_MISC_XM2CFGDPADCTRL2 0x8e8
-#define __tegra20_cpu1_resettable_status_offset \
- (__tegra_cpu_reset_handler_data_offset + RESET_DATA(RESETTABLE_STATUS))
-
.macro pll_enable, rd, r_car_base, pll_base
ldr \rd, [\r_car_base, #\pll_base]
tst \rd, #(1 << 30)
@@ -64,21 +61,6 @@
/*
* tegra20_hotplug_shutdown(void)
*
- * puts the current cpu in reset
- * should never return
- */
-ENTRY(tegra20_hotplug_shutdown)
- /* Put this CPU down */
- cpu_id r0
- bl tegra20_cpu_shutdown
- ret lr @ should never get here
-ENDPROC(tegra20_hotplug_shutdown)
-
-/*
- * tegra20_cpu_shutdown(int cpu)
- *
- * r0 is cpu to reset
- *
* puts the specified CPU in wait-for-event mode on the flow controller
* and puts the CPU in reset
* can be called on the current cpu or another cpu
@@ -87,13 +69,10 @@ ENDPROC(tegra20_hotplug_shutdown)
*
* corrupts r0-r3, r12
*/
-ENTRY(tegra20_cpu_shutdown)
+ENTRY(tegra20_hotplug_shutdown)
+ cpu_id r0
cmp r0, #0
reteq lr @ must not be called for CPU 0
- mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r2, =__tegra20_cpu1_resettable_status_offset
- mov r12, #CPU_RESETTABLE
- strb r12, [r1, r2]
cpu_to_halt_reg r1, r0
ldr r3, =TEGRA_FLOW_CTRL_VIRT
@@ -112,111 +91,10 @@ ENTRY(tegra20_cpu_shutdown)
cmp r3, r0
beq .
ret lr
-ENDPROC(tegra20_cpu_shutdown)
+ENDPROC(tegra20_hotplug_shutdown)
#endif
#ifdef CONFIG_PM_SLEEP
-/*
- * tegra_pen_lock
- *
- * spinlock implementation with no atomic test-and-set and no coherence
- * using Peterson's algorithm on strongly-ordered registers
- * used to synchronize a cpu waking up from wfi with entering lp2 on idle
- *
- * The reference link of Peterson's algorithm:
- * http://en.wikipedia.org/wiki/Peterson's_algorithm
- *
- * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm)
- * on cpu 0:
- * r2 = flag[0] (in SCRATCH38)
- * r3 = flag[1] (in SCRATCH39)
- * on cpu1:
- * r2 = flag[1] (in SCRATCH39)
- * r3 = flag[0] (in SCRATCH38)
- *
- * must be called with MMU on
- * corrupts r0-r3, r12
- */
-ENTRY(tegra_pen_lock)
- mov32 r3, TEGRA_PMC_VIRT
- cpu_id r0
- add r1, r3, #PMC_SCRATCH37
- cmp r0, #0
- addeq r2, r3, #PMC_SCRATCH38
- addeq r3, r3, #PMC_SCRATCH39
- addne r2, r3, #PMC_SCRATCH39
- addne r3, r3, #PMC_SCRATCH38
-
- mov r12, #1
- str r12, [r2] @ flag[cpu] = 1
- dsb
- str r12, [r1] @ !turn = cpu
-1: dsb
- ldr r12, [r3]
- cmp r12, #1 @ flag[!cpu] == 1?
- ldreq r12, [r1]
- cmpeq r12, r0 @ !turn == cpu?
- beq 1b @ while !turn == cpu && flag[!cpu] == 1
-
- ret lr @ locked
-ENDPROC(tegra_pen_lock)
-
-ENTRY(tegra_pen_unlock)
- dsb
- mov32 r3, TEGRA_PMC_VIRT
- cpu_id r0
- cmp r0, #0
- addeq r2, r3, #PMC_SCRATCH38
- addne r2, r3, #PMC_SCRATCH39
- mov r12, #0
- str r12, [r2]
- ret lr
-ENDPROC(tegra_pen_unlock)
-
-/*
- * tegra20_cpu_clear_resettable(void)
- *
- * Called to clear the "resettable soon" flag in IRAM variable when
- * it is expected that the secondary CPU will be idle soon.
- */
-ENTRY(tegra20_cpu_clear_resettable)
- mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r2, =__tegra20_cpu1_resettable_status_offset
- mov r12, #CPU_NOT_RESETTABLE
- strb r12, [r1, r2]
- ret lr
-ENDPROC(tegra20_cpu_clear_resettable)
-
-/*
- * tegra20_cpu_set_resettable_soon(void)
- *
- * Called to set the "resettable soon" flag in IRAM variable when
- * it is expected that the secondary CPU will be idle soon.
- */
-ENTRY(tegra20_cpu_set_resettable_soon)
- mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r2, =__tegra20_cpu1_resettable_status_offset
- mov r12, #CPU_RESETTABLE_SOON
- strb r12, [r1, r2]
- ret lr
-ENDPROC(tegra20_cpu_set_resettable_soon)
-
-/*
- * tegra20_cpu_is_resettable_soon(void)
- *
- * Returns true if the "resettable soon" flag in IRAM variable has been
- * set because it is expected that the secondary CPU will be idle soon.
- */
-ENTRY(tegra20_cpu_is_resettable_soon)
- mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r2, =__tegra20_cpu1_resettable_status_offset
- ldrb r12, [r1, r2]
- cmp r12, #CPU_RESETTABLE_SOON
- moveq r0, #1
- movne r0, #0
- ret lr
-ENDPROC(tegra20_cpu_is_resettable_soon)
-
/*
* tegra20_sleep_core_finish(unsigned long v2p)
*
@@ -242,68 +120,6 @@ ENTRY(tegra20_sleep_core_finish)
ret r3
ENDPROC(tegra20_sleep_core_finish)
-/*
- * tegra20_sleep_cpu_secondary_finish(unsigned long v2p)
- *
- * Enters WFI on secondary CPU by exiting coherency.
- */
-ENTRY(tegra20_sleep_cpu_secondary_finish)
- stmfd sp!, {r4-r11, lr}
-
- mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency
-
- /* Flush and disable the L1 data cache */
- mov r0, #TEGRA_FLUSH_CACHE_LOUIS
- bl tegra_disable_clean_inv_dcache
-
- mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r4, =__tegra20_cpu1_resettable_status_offset
- mov r3, #CPU_RESETTABLE
- strb r3, [r0, r4]
-
- bl tegra_cpu_do_idle
-
- /*
- * cpu may be reset while in wfi, which will return through
- * tegra_resume to cpu_resume
- * or interrupt may wake wfi, which will return here
- * cpu state is unchanged - MMU is on, cache is on, coherency
- * is off, and the data cache is off
- *
- * r11 contains the original actlr
- */
-
- bl tegra_pen_lock
-
- mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
- ldr r4, =__tegra20_cpu1_resettable_status_offset
- mov r3, #CPU_NOT_RESETTABLE
- strb r3, [r0, r4]
-
- bl tegra_pen_unlock
-
- /* Re-enable the data cache */
- mrc p15, 0, r10, c1, c0, 0
- orr r10, r10, #CR_C
- mcr p15, 0, r10, c1, c0, 0
- isb
-
- mcr p15, 0, r11, c1, c0, 1 @ reenable coherency
-
- /* Invalidate the TLBs & BTAC */
- mov r1, #0
- mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs
- mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC
- dsb
- isb
-
- /* the cpu was running with coherency disabled,
- * caches may be out of date */
- bl v7_flush_kern_cache_louis
-
- ldmfd sp!, {r4 - r11, pc}
-ENDPROC(tegra20_sleep_cpu_secondary_finish)
-
/*
* tegra20_tear_down_cpu
*
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 78ef32a907c8..d219872b7546 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -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);
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index e512e606eabd..d9237769a37c 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -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"))
diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig
index c8ef05d6b8c7..d98c69efb7e0 100644
--- a/drivers/soc/tegra/Kconfig
+++ b/drivers/soc/tegra/Kconfig
@@ -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
diff --git a/include/soc/tegra/cpuidle.h b/include/soc/tegra/cpuidle.h
index 029ba1f4b2cc..f758808342b6 100644
--- a/include/soc/tegra/cpuidle.h
+++ b/include/soc/tegra/cpuidle.h
@@ -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__ */
--
2.22.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 2/6] ARM: tegra: Expose functions required for cpuidle driver
2019-07-07 23:38 [PATCH v1 0/6] Consolidate and improve NVIDIA Tegra CPUIDLE driver(s) Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 1/6] ARM: tegra: Remove cpuidle drivers Dmitry Osipenko
@ 2019-07-07 23:38 ` Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 3/6] cpuidle: Add unified driver for NVIDIA Tegra SoCs Dmitry Osipenko
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Dmitry Osipenko @ 2019-07-07 23:38 UTC (permalink / raw)
To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
Rafael J. Wysocki, Daniel Lezcano
Cc: linux-pm, linux-tegra, linux-kernel
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 <digetx@gmail.com>
---
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(-)
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 5d93a0b36866..27bd5d9865e3 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -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
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index e6911a14c096..c8a63719a143 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -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
};
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 6aaacb5757e1..f9c9bce9e15d 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -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(
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index 1e51a9b636eb..81525f5f4a44 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -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
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index d219872b7546..0d9956e9a8ea 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -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
diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h
index b8aef62cc3f5..cf0f2cb5e109 100644
--- a/include/linux/clk/tegra.h
+++ b/include/linux/clk/tegra.h
@@ -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);
diff --git a/include/soc/tegra/pm.h b/include/soc/tegra/pm.h
index 951fcd738d55..fa18c2df5028 100644
--- a/include/soc/tegra/pm.h
+++ b/include/soc/tegra/pm.h
@@ -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__ */
--
2.22.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 3/6] cpuidle: Add unified driver for NVIDIA Tegra SoCs
2019-07-07 23:38 [PATCH v1 0/6] Consolidate and improve NVIDIA Tegra CPUIDLE driver(s) Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 1/6] ARM: tegra: Remove cpuidle drivers Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 2/6] ARM: tegra: Expose functions required for cpuidle driver Dmitry Osipenko
@ 2019-07-07 23:38 ` Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 4/6] cpuidle: tegra: Support CPU cluster power-down on Tegra30 Dmitry Osipenko
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Dmitry Osipenko @ 2019-07-07 23:38 UTC (permalink / raw)
To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
Rafael J. Wysocki, Daniel Lezcano
Cc: linux-pm, linux-tegra, linux-kernel
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 <digetx@gmail.com>
---
arch/arm/mach-tegra/tegra.c | 4 +
drivers/cpuidle/Kconfig.arm | 8 ++
drivers/cpuidle/Makefile | 1 +
drivers/cpuidle/cpuidle-tegra.c | 237 ++++++++++++++++++++++++++++++++
include/soc/tegra/cpuidle.h | 4 +
5 files changed, 254 insertions(+)
create mode 100644 drivers/cpuidle/cpuidle-tegra.c
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index d9237769a37c..f1ce2857a251 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -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[] = {
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index 48cb3d4bb7d1..d90861361f1d 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -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.
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 9d7176cee3d3..470d17fa8746 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -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
diff --git a/drivers/cpuidle/cpuidle-tegra.c b/drivers/cpuidle/cpuidle-tegra.c
new file mode 100644
index 000000000000..3fad4a0cbc78
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-tegra.c
@@ -0,0 +1,237 @@
+// 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 <ccross@android.com>
+ * Gary King <gking@nvidia.com>
+ *
+ * Rework for 3.3 by Peter De Schrijver <pdeschrijver@nvidia.com>
+ *
+ * Tegra20-124 driver unification by Dmitry Osipenko <digetx@gmail.com>
+ */
+
+#include <linux/cpuidle.h>
+#include <linux/cpumask.h>
+#include <linux/cpu_pm.h>
+#include <linux/errno.h>
+#include <linux/platform_device.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>
+
+static atomic_t tegra_idle_barrier;
+
+static int tegra_shutdown_secondary_cpu(unsigned long cpu)
+{
+ tegra_cpu_die(cpu);
+
+ return -EINVAL;
+}
+
+static void tegra_await_secondary_cpus(void)
+{
+ /*
+ * The boot CPU shall await for the secondaries shutdown in order
+ * to power-off CPU's cluster safely.
+ */
+ while (!tegra_cpu_rail_off_ready())
+ cpu_relax();
+}
+
+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_cpu_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ unsigned int cpu = cpu_logical_map(dev->cpu);
+ int err;
+
+ /*
+ * On Tegra30 CPU0 can't be power-gated while secondary CPUs
+ * are active because it gates the whole CPU cluster.
+ */
+ if (index == 1 && cpu == 0)
+ return arm_cpuidle_simple_enter(dev, drv, 0);
+
+ local_fiq_disable();
+ tegra_set_cpu_in_lp2();
+ cpu_pm_enter();
+
+ switch (index) {
+ case 1:
+ err = cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
+ break;
+ case 2:
+ cpuidle_coupled_parallel_barrier(dev, &tegra_idle_barrier);
+
+ if (cpu == 0) {
+ tegra_await_secondary_cpus();
+ err = tegra_idle_lp2_last();
+ tegra_wake_up_secondary_cpus();
+ } else {
+ err = cpu_suspend(cpu, tegra_shutdown_secondary_cpu);
+ }
+ break;
+ case 3:
+ err = call_firmware_op(prepare_idle, TF_PM_MODE_LP2_NOFLUSH_L2);
+ if (err && err != -ENOSYS)
+ break;
+
+ err = call_firmware_op(do_idle, 0);
+ if (err && err != -ENOSYS)
+ break;
+
+ /*
+ * Do suspend by ourselves if the firmware does not
+ * implement it.
+ */
+ err = cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ cpu_pm_exit();
+ tegra_clear_cpu_in_lp2();
+ local_fiq_enable();
+
+ smp_rmb();
+
+ return WARN_ON_ONCE(err) ? -1 : index;
+}
+
+static void tegra114_idle_enter_s2idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ tegra_cpu_idle(dev, drv, index);
+}
+
+static struct cpuidle_driver tegra_idle_driver = {
+ .name = "tegra_idle",
+ .states = {
+ [0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
+ [1] = {
+ .enter = tegra_cpu_idle,
+ .exit_latency = 2000,
+ .target_residency = 2200,
+ .power_usage = 0,
+ .flags = CPUIDLE_FLAG_TIMER_STOP,
+ .name = "powered-down",
+ .desc = "CPU core powered-off",
+ },
+ [2] = {
+ .enter = tegra_cpu_idle,
+ .exit_latency = 5000,
+ .target_residency = 10000,
+ .power_usage = 0,
+ .flags = CPUIDLE_FLAG_COUPLED |
+ CPUIDLE_FLAG_TIMER_STOP,
+ .name = "powered-down",
+ .desc = "CPU cluster powered-off",
+ },
+ [3] = {
+ .enter = tegra_cpu_idle,
+ .enter_s2idle = tegra114_idle_enter_s2idle,
+ .exit_latency = 500,
+ .target_residency = 1000,
+ .power_usage = 0,
+ .flags = CPUIDLE_FLAG_TIMER_STOP,
+ .name = "powered-down",
+ .desc = "CPU core power-gated",
+ },
+ },
+ .state_count = 4,
+ .safe_state_index = 0,
+};
+
+/*
+ * Tegra20 HW appears to have a bug such that PCIe device interrupts, whether
+ * they are legacy IRQs or MSI, are lost when LP2 is enabled. To work around
+ * this, simply disable LP2 if the PCI driver and DT node are both enabled.
+ */
+void tegra_cpuidle_pcie_irqs_in_use(void)
+{
+ if (tegra_get_chip_id() != TEGRA20 ||
+ tegra_idle_driver.states[2].disabled)
+ return;
+
+ pr_info("Disabling cpuidle LP2 state, since PCIe IRQs are in use\n");
+ tegra_idle_driver.states[2].disabled = true;
+}
+
+static int tegra_cpuidle_probe(struct platform_device *pdev)
+{
+ const struct cpumask *coupled_cpus = cpu_possible_mask;
+
+ /*
+ * Generic WFI state is common for all NVIDIA Tegra SoCs.
+ *
+ * Secondary CPU core can't be power-gated separately from CPU0
+ * on Tegra20.
+ *
+ * On Tegra114/124 all CPU cores could be power-gated separately.
+ */
+ switch (tegra_get_chip_id()) {
+ case TEGRA20:
+ tegra_idle_driver.states[1].disabled = true;
+ tegra_idle_driver.states[3].disabled = true;
+ break;
+ case TEGRA30:
+ tegra_idle_driver.states[2].disabled = true;
+ tegra_idle_driver.states[3].disabled = true;
+ break;
+ case TEGRA114:
+ case TEGRA124:
+ tegra_idle_driver.states[1].disabled = true;
+ tegra_idle_driver.states[2].disabled = true;
+
+ coupled_cpus = NULL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!IS_ENABLED(CONFIG_PM_SLEEP)) {
+ tegra_idle_driver.states[1].disabled = true;
+ tegra_idle_driver.states[2].disabled = true;
+ }
+
+ return cpuidle_register(&tegra_idle_driver, coupled_cpus);
+}
+
+static struct platform_driver tegra_cpuidle_driver = {
+ .probe = tegra_cpuidle_probe,
+ .driver = {
+ .name = "tegra-cpuidle",
+ .suppress_bind_attrs = true,
+ },
+};
+builtin_platform_driver(tegra_cpuidle_driver);
diff --git a/include/soc/tegra/cpuidle.h b/include/soc/tegra/cpuidle.h
index f758808342b6..5665975015d8 100644
--- a/include/soc/tegra/cpuidle.h
+++ b/include/soc/tegra/cpuidle.h
@@ -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__ */
--
2.22.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 4/6] cpuidle: tegra: Support CPU cluster power-down on Tegra30
2019-07-07 23:38 [PATCH v1 0/6] Consolidate and improve NVIDIA Tegra CPUIDLE driver(s) Dmitry Osipenko
` (2 preceding siblings ...)
2019-07-07 23:38 ` [PATCH v1 3/6] cpuidle: Add unified driver for NVIDIA Tegra SoCs Dmitry Osipenko
@ 2019-07-07 23:38 ` Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 5/6] cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from Tegra114/124 idle-state Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 6/6] cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from all states Dmitry Osipenko
5 siblings, 0 replies; 8+ messages in thread
From: Dmitry Osipenko @ 2019-07-07 23:38 UTC (permalink / raw)
To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
Rafael J. Wysocki, Daniel Lezcano
Cc: linux-pm, linux-tegra, linux-kernel
The 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.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
Please note that outer_disable() has a WARN_ON(num_online_cpus > 1)
and it doesn't know that we turned off those secondary CPUs, hence the
outer_cache.disable() is now invoked directly.
arch/arm/mach-tegra/pm.c | 4 ++--
drivers/cpuidle/cpuidle-tegra.c | 4 +---
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index f9c9bce9e15d..cc941b0c97e8 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -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
diff --git a/drivers/cpuidle/cpuidle-tegra.c b/drivers/cpuidle/cpuidle-tegra.c
index 3fad4a0cbc78..31eeef22c0ff 100644
--- a/drivers/cpuidle/cpuidle-tegra.c
+++ b/drivers/cpuidle/cpuidle-tegra.c
@@ -202,10 +202,8 @@ static int tegra_cpuidle_probe(struct platform_device *pdev)
switch (tegra_get_chip_id()) {
case TEGRA20:
tegra_idle_driver.states[1].disabled = true;
- tegra_idle_driver.states[3].disabled = true;
- break;
+ /* fall through */
case TEGRA30:
- tegra_idle_driver.states[2].disabled = true;
tegra_idle_driver.states[3].disabled = true;
break;
case TEGRA114:
--
2.22.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 5/6] cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from Tegra114/124 idle-state
2019-07-07 23:38 [PATCH v1 0/6] Consolidate and improve NVIDIA Tegra CPUIDLE driver(s) Dmitry Osipenko
` (3 preceding siblings ...)
2019-07-07 23:38 ` [PATCH v1 4/6] cpuidle: tegra: Support CPU cluster power-down on Tegra30 Dmitry Osipenko
@ 2019-07-07 23:38 ` Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 6/6] cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from all states Dmitry Osipenko
5 siblings, 0 replies; 8+ messages in thread
From: Dmitry Osipenko @ 2019-07-07 23:38 UTC (permalink / raw)
To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
Rafael J. Wysocki, Daniel Lezcano
Cc: linux-pm, linux-tegra, linux-kernel
Local CPU timers are always-ON on the Tegra114/124 SoCs regardless of the
CPU's idle state.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/cpuidle/cpuidle-tegra.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/cpuidle/cpuidle-tegra.c b/drivers/cpuidle/cpuidle-tegra.c
index 31eeef22c0ff..464b2376905a 100644
--- a/drivers/cpuidle/cpuidle-tegra.c
+++ b/drivers/cpuidle/cpuidle-tegra.c
@@ -163,7 +163,6 @@ static struct cpuidle_driver tegra_idle_driver = {
.exit_latency = 500,
.target_residency = 1000,
.power_usage = 0,
- .flags = CPUIDLE_FLAG_TIMER_STOP,
.name = "powered-down",
.desc = "CPU core power-gated",
},
--
2.22.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 6/6] cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from all states
2019-07-07 23:38 [PATCH v1 0/6] Consolidate and improve NVIDIA Tegra CPUIDLE driver(s) Dmitry Osipenko
` (4 preceding siblings ...)
2019-07-07 23:38 ` [PATCH v1 5/6] cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from Tegra114/124 idle-state Dmitry Osipenko
@ 2019-07-07 23:38 ` Dmitry Osipenko
2019-07-09 5:49 ` Dmitry Osipenko
5 siblings, 1 reply; 8+ messages in thread
From: Dmitry Osipenko @ 2019-07-07 23:38 UTC (permalink / raw)
To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
Rafael J. Wysocki, Daniel Lezcano
Cc: linux-pm, linux-tegra, linux-kernel
The Tegra's clocksource driver got some rework recently and now the
internal/local CPU timers usage is discouraged on Tegra20/30 SoCs in
a favor of the platform-specific timers that are assigned as per-CPU
clocksources because they do not suffer from the CPU-freq changes and
are always-ON during of CPU-idling. That happened in the commit
f6d50ec5f85c ("clocksource/drivers/tegra: Support per-CPU timers on all
Tegra's"). The Tegra's clocksource driver is the essential arch-driver
that is guaranteed to always present on all Tegra SoCs up to Tegra124.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/cpuidle/cpuidle-tegra.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/cpuidle/cpuidle-tegra.c b/drivers/cpuidle/cpuidle-tegra.c
index 464b2376905a..e2aa46231c05 100644
--- a/drivers/cpuidle/cpuidle-tegra.c
+++ b/drivers/cpuidle/cpuidle-tegra.c
@@ -143,7 +143,6 @@ static struct cpuidle_driver tegra_idle_driver = {
.exit_latency = 2000,
.target_residency = 2200,
.power_usage = 0,
- .flags = CPUIDLE_FLAG_TIMER_STOP,
.name = "powered-down",
.desc = "CPU core powered-off",
},
@@ -152,8 +151,7 @@ static struct cpuidle_driver tegra_idle_driver = {
.exit_latency = 5000,
.target_residency = 10000,
.power_usage = 0,
- .flags = CPUIDLE_FLAG_COUPLED |
- CPUIDLE_FLAG_TIMER_STOP,
+ .flags = CPUIDLE_FLAG_COUPLED,
.name = "powered-down",
.desc = "CPU cluster powered-off",
},
--
2.22.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v1 6/6] cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from all states
2019-07-07 23:38 ` [PATCH v1 6/6] cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from all states Dmitry Osipenko
@ 2019-07-09 5:49 ` Dmitry Osipenko
0 siblings, 0 replies; 8+ messages in thread
From: Dmitry Osipenko @ 2019-07-09 5:49 UTC (permalink / raw)
To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
Rafael J. Wysocki, Daniel Lezcano
Cc: linux-pm, linux-tegra, linux-kernel
08.07.2019 2:38, Dmitry Osipenko пишет:
> The Tegra's clocksource driver got some rework recently and now the
> internal/local CPU timers usage is discouraged on Tegra20/30 SoCs in
> a favor of the platform-specific timers that are assigned as per-CPU
> clocksources because they do not suffer from the CPU-freq changes and
> are always-ON during of CPU-idling. That happened in the commit
> f6d50ec5f85c ("clocksource/drivers/tegra: Support per-CPU timers on all
> Tegra's"). The Tegra's clocksource driver is the essential arch-driver
> that is guaranteed to always present on all Tegra SoCs up to Tegra124.
>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
> drivers/cpuidle/cpuidle-tegra.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/cpuidle/cpuidle-tegra.c b/drivers/cpuidle/cpuidle-tegra.c
> index 464b2376905a..e2aa46231c05 100644
> --- a/drivers/cpuidle/cpuidle-tegra.c
> +++ b/drivers/cpuidle/cpuidle-tegra.c
> @@ -143,7 +143,6 @@ static struct cpuidle_driver tegra_idle_driver = {
> .exit_latency = 2000,
> .target_residency = 2200,
> .power_usage = 0,
> - .flags = CPUIDLE_FLAG_TIMER_STOP,
> .name = "powered-down",
> .desc = "CPU core powered-off",
> },
> @@ -152,8 +151,7 @@ static struct cpuidle_driver tegra_idle_driver = {
> .exit_latency = 5000,
> .target_residency = 10000,
> .power_usage = 0,
> - .flags = CPUIDLE_FLAG_COUPLED |
> - CPUIDLE_FLAG_TIMER_STOP,
> + .flags = CPUIDLE_FLAG_COUPLED,
> .name = "powered-down",
> .desc = "CPU cluster powered-off",
> },
>
Actually, it should be fine to keep this flag because I found that
tick_broadcast_oneshot_control() checks for the C3STOP flag and thus
CPUIDLE_FLAG_TIMER_STOP has no effect in that case. Will drop this patch in the next revision.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2019-07-09 5:49 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-07 23:38 [PATCH v1 0/6] Consolidate and improve NVIDIA Tegra CPUIDLE driver(s) Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 1/6] ARM: tegra: Remove cpuidle drivers Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 2/6] ARM: tegra: Expose functions required for cpuidle driver Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 3/6] cpuidle: Add unified driver for NVIDIA Tegra SoCs Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 4/6] cpuidle: tegra: Support CPU cluster power-down on Tegra30 Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 5/6] cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from Tegra114/124 idle-state Dmitry Osipenko
2019-07-07 23:38 ` [PATCH v1 6/6] cpuidle: tegra: Remove CPUIDLE_FLAG_TIMER_STOP from all states Dmitry Osipenko
2019-07-09 5:49 ` Dmitry Osipenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).