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 6452ebf..b21f51b 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 81525f5..e63f96d 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 c011359..ab5008f 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 ea62f84..50091c4 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 08477d7..4338789 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__ */