cpuidle: tegra: Squash Tegra114 driver into the common driver
authorDmitry Osipenko <digetx@gmail.com>
Mon, 24 Feb 2020 22:40:54 +0000 (01:40 +0300)
committerThierry Reding <treding@nvidia.com>
Fri, 13 Mar 2020 10:32:01 +0000 (11:32 +0100)
Tegra20/30/114/124 SoCs have common idling states, thus there is no much
point in having separate drivers for a similar hardware. This patch moves
Tegra114/124 arch/ drivers into the common driver without any functional
changes. The CC6 state is kept disabled on Tegra114/124 because the core
Tegra PM code needs some more work in order to support that state.

Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Thierry Reding <treding@nvidia.com>
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/cpuidle-tegra114.c [deleted file]
arch/arm/mach-tegra/cpuidle.c [deleted file]
arch/arm/mach-tegra/cpuidle.h [deleted file]
arch/arm/mach-tegra/tegra.c
drivers/cpuidle/cpuidle-tegra.c

index 99c5f42..07572b5 100644 (file)
@@ -10,19 +10,12 @@ obj-y                                       += sleep.o
 obj-y                                  += tegra.o
 obj-y                                  += sleep-tegra20.o
 obj-y                                  += sleep-tegra30.o
-obj-$(CONFIG_CPU_IDLE)                 += cpuidle.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += pm-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += pm-tegra30.o
 obj-$(CONFIG_SMP)                      += platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.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)       += 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 (file)
index 858c30c..0000000
+++ /dev/null
@@ -1,90 +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 <soc/tegra/pm.h>
-
-#include <asm/cpuidle.h>
-#include <asm/smp_plat.h>
-#include <asm/suspend.h>
-#include <asm/psci.h>
-
-#include "cpuidle.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_pm_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_pm_secondary_cpu_suspend);
-
-       cpu_pm_exit();
-       tegra_pm_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.c b/arch/arm/mach-tegra/cpuidle.c
deleted file mode 100644 (file)
index fa0dcf3..0000000
+++ /dev/null
@@ -1,37 +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 <linux/platform_device.h>
-
-#include <soc/tegra/fuse.h>
-
-#include "cpuidle.h"
-
-void __init tegra_cpuidle_init(void)
-{
-       switch (tegra_get_chip_id()) {
-       case TEGRA20:
-       case TEGRA30:
-               platform_device_register_simple("tegra-cpuidle", -1, NULL, 0);
-               break;
-       case TEGRA114:
-       case TEGRA124:
-               if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) ||
-                   IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC))
-                       tegra114_cpuidle_init();
-               break;
-       }
-}
diff --git a/arch/arm/mach-tegra/cpuidle.h b/arch/arm/mach-tegra/cpuidle.h
deleted file mode 100644 (file)
index 5423a05..0000000
+++ /dev/null
@@ -1,16 +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 tegra114_cpuidle_init(void);
-void tegra_cpuidle_init(void);
-#else
-static inline void tegra_cpuidle_init(void) {}
-#endif
-
-#endif
index 00aaf49..f1ce285 100644 (file)
 #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"
 #include "common.h"
-#include "cpuidle.h"
 #include "iomap.h"
 #include "pm.h"
 #include "reset.h"
@@ -85,7 +85,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"))
@@ -94,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[] = {
index cd969ec..2ddbd28 100644 (file)
@@ -24,6 +24,7 @@
 #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>
@@ -32,6 +33,7 @@
 #include <soc/tegra/pm.h>
 
 #include <asm/cpuidle.h>
+#include <asm/firmware.h>
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 
@@ -45,6 +47,11 @@ enum tegra_state {
 static atomic_t tegra_idle_barrier;
 static atomic_t tegra_abort_flag;
 
+static inline bool tegra_cpuidle_using_firmware(void)
+{
+       return firmware_ops->prepare_idle && firmware_ops->do_idle;
+}
+
 static void tegra_cpuidle_report_cpus_state(void)
 {
        unsigned long cpu, lcpu, csr;
@@ -125,6 +132,16 @@ static int tegra_cpuidle_cc6_enter(unsigned int cpu)
 
 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_pm_secondary_cpu_suspend);
 }
 
@@ -235,6 +252,13 @@ static int tegra_cpuidle_enter(struct cpuidle_device *dev,
        return err ? -1 : index;
 }
 
+static void tegra114_enter_s2idle(struct cpuidle_device *dev,
+                                 struct cpuidle_driver *drv,
+                                 int index)
+{
+       tegra_cpuidle_enter(dev, drv, index);
+}
+
 /*
  * The previous versions of Tegra CPUIDLE driver used a different "legacy"
  * terminology for naming of the idling states, while this driver uses the
@@ -302,6 +326,15 @@ void tegra_cpuidle_pcie_irqs_in_use(void)
        tegra_cpuidle_disable_state(TEGRA_CC6);
 }
 
+static void tegra_cpuidle_setup_tegra114_c7_state(void)
+{
+       struct cpuidle_state *s = &tegra_idle_driver.states[TEGRA_C7];
+
+       s->enter_s2idle = tegra114_enter_s2idle;
+       s->target_residency = 1000;
+       s->exit_latency = 500;
+}
+
 static int tegra_cpuidle_probe(struct platform_device *pdev)
 {
        /*
@@ -310,7 +343,9 @@ static int tegra_cpuidle_probe(struct platform_device *pdev)
         * is disabled.
         */
        if (!IS_ENABLED(CONFIG_PM_SLEEP)) {
-               tegra_cpuidle_disable_state(TEGRA_C7);
+               if (!tegra_cpuidle_using_firmware())
+                       tegra_cpuidle_disable_state(TEGRA_C7);
+
                tegra_cpuidle_disable_state(TEGRA_CC6);
        }
 
@@ -328,6 +363,14 @@ static int tegra_cpuidle_probe(struct platform_device *pdev)
                tegra_cpuidle_disable_state(TEGRA_CC6);
                break;
 
+       case TEGRA114:
+       case TEGRA124:
+               tegra_cpuidle_setup_tegra114_c7_state();
+
+               /* coupled CC6 (LP2) state isn't implemented yet */
+               tegra_cpuidle_disable_state(TEGRA_CC6);
+               break;
+
        default:
                return -EINVAL;
        }