soc/tegra: pmc: Prevent racing with cpuilde driver
authorDmitry Osipenko <digetx@gmail.com>
Sun, 18 Jul 2021 21:27:05 +0000 (00:27 +0300)
committerThierry Reding <treding@nvidia.com>
Wed, 11 Aug 2021 09:51:39 +0000 (11:51 +0200)
Both PMC and cpuidle drivers are probed at the same init level and
cpuidle depends on the PMC suspend mode. Add new default suspend mode
that indicates whether PMC driver has been probed and reset the mode in
a case of deferred probe of the PMC driver.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/pm.h
arch/arm/mach-tegra/tegra.c
drivers/soc/tegra/pmc.c
include/soc/tegra/pm.h

index 6452ebf68d40efc20ac42952aade79a4805404c0..b21f51b8e19e19852f5eddd1c6c3cef8151afb3b 100644 (file)
@@ -403,7 +403,7 @@ static const struct platform_suspend_ops tegra_suspend_ops = {
        .enter          = tegra_suspend_enter,
 };
 
-void __init tegra_init_suspend(void)
+void tegra_pm_init_suspend(void)
 {
        enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();
 
index 81525f5f4a441a9c2005ed1d813b0227d0a0c73e..e63f96de28256eaf3aac073e542278f145275163 100644 (file)
@@ -25,10 +25,4 @@ void tegra30_sleep_core_init(void);
 
 extern void (*tegra_tear_down_cpu)(void);
 
-#ifdef CONFIG_PM_SLEEP
-void tegra_init_suspend(void);
-#else
-static inline void tegra_init_suspend(void) {}
-#endif
-
 #endif /* _MACH_TEGRA_PM_H_ */
index c011359bcdb443f5f687dc747315ab1baee3afb2..ab5008f35803cb2ac3c544604e194c8b03ac7992 100644 (file)
@@ -84,8 +84,6 @@ static void __init tegra_dt_init(void)
 
 static void __init tegra_dt_init_late(void)
 {
-       tegra_init_suspend();
-
        if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
            of_machine_is_compatible("compal,paz00"))
                tegra_paz00_wifikill_init();
index ea62f84d1c8bd91907cf64e6010c23fe46cf920e..50091c4ec94812f9961f4885c9b45ca2151b58dc 100644 (file)
@@ -436,7 +436,7 @@ struct tegra_pmc {
 
 static struct tegra_pmc *pmc = &(struct tegra_pmc) {
        .base = NULL,
-       .suspend_mode = TEGRA_SUSPEND_NONE,
+       .suspend_mode = TEGRA_SUSPEND_NOT_READY,
 };
 
 static inline struct tegra_powergate *
@@ -1812,6 +1812,7 @@ static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np)
        u32 value, values[2];
 
        if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) {
+               pmc->suspend_mode = TEGRA_SUSPEND_NONE;
        } else {
                switch (value) {
                case 0:
@@ -2785,6 +2786,11 @@ static int tegra_pmc_regmap_init(struct tegra_pmc *pmc)
        return 0;
 }
 
+static void tegra_pmc_reset_suspend_mode(void *data)
+{
+       pmc->suspend_mode = TEGRA_SUSPEND_NOT_READY;
+}
+
 static int tegra_pmc_probe(struct platform_device *pdev)
 {
        void __iomem *base;
@@ -2803,6 +2809,11 @@ static int tegra_pmc_probe(struct platform_device *pdev)
        if (err < 0)
                return err;
 
+       err = devm_add_action_or_reset(&pdev->dev, tegra_pmc_reset_suspend_mode,
+                                      NULL);
+       if (err)
+               return err;
+
        /* take over the memory region from the early initialization */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        base = devm_ioremap_resource(&pdev->dev, res);
@@ -2909,6 +2920,7 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 
        tegra_pmc_clock_register(pmc, pdev->dev.of_node);
        platform_set_drvdata(pdev, pmc);
+       tegra_pm_init_suspend();
 
        return 0;
 
index 08477d7bfab93fde69840ef7e945fb2a22bc983e..433878927026335d63c43497d39b7b85bb94de49 100644 (file)
@@ -14,6 +14,7 @@ enum tegra_suspend_mode {
        TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
        TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
        TEGRA_MAX_SUSPEND_MODE,
+       TEGRA_SUSPEND_NOT_READY,
 };
 
 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
@@ -28,6 +29,7 @@ void tegra_pm_clear_cpu_in_lp2(void);
 void tegra_pm_set_cpu_in_lp2(void);
 int tegra_pm_enter_lp2(void);
 int tegra_pm_park_secondary_cpu(unsigned long cpu);
+void tegra_pm_init_suspend(void);
 #else
 static inline enum tegra_suspend_mode
 tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
@@ -61,6 +63,10 @@ static inline int tegra_pm_park_secondary_cpu(unsigned long cpu)
 {
        return -ENOTSUPP;
 }
+
+static inline void tegra_pm_init_suspend(void)
+{
+}
 #endif /* CONFIG_PM_SLEEP */
 
 #endif /* __SOC_TEGRA_PM_H__ */