Commit e278718f authored by Thierry Reding's avatar Thierry Reding

Merge branch 'for-5.15/soc' into for-5.15/clk

parents e73f0f0e 59c6fceb
...@@ -403,7 +403,7 @@ static const struct platform_suspend_ops tegra_suspend_ops = { ...@@ -403,7 +403,7 @@ static const struct platform_suspend_ops tegra_suspend_ops = {
.enter = tegra_suspend_enter, .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(); enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();
......
...@@ -25,10 +25,4 @@ void tegra30_sleep_core_init(void); ...@@ -25,10 +25,4 @@ void tegra30_sleep_core_init(void);
extern void (*tegra_tear_down_cpu)(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_ */ #endif /* _MACH_TEGRA_PM_H_ */
...@@ -84,8 +84,6 @@ static void __init tegra_dt_init(void) ...@@ -84,8 +84,6 @@ static void __init tegra_dt_init(void)
static void __init tegra_dt_init_late(void) static void __init tegra_dt_init_late(void)
{ {
tegra_init_suspend();
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
of_machine_is_compatible("compal,paz00")) of_machine_is_compatible("compal,paz00"))
tegra_paz00_wifikill_init(); tegra_paz00_wifikill_init();
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sys_soc.h> #include <linux/sys_soc.h>
...@@ -210,6 +211,8 @@ static int tegra_fuse_probe(struct platform_device *pdev) ...@@ -210,6 +211,8 @@ static int tegra_fuse_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, fuse); platform_set_drvdata(pdev, fuse);
fuse->dev = &pdev->dev; fuse->dev = &pdev->dev;
pm_runtime_enable(&pdev->dev);
if (fuse->soc->probe) { if (fuse->soc->probe) {
err = fuse->soc->probe(fuse); err = fuse->soc->probe(fuse);
if (err < 0) if (err < 0)
...@@ -246,14 +249,71 @@ static int tegra_fuse_probe(struct platform_device *pdev) ...@@ -246,14 +249,71 @@ static int tegra_fuse_probe(struct platform_device *pdev)
return 0; return 0;
restore: restore:
fuse->clk = NULL;
fuse->base = base; fuse->base = base;
pm_runtime_disable(&pdev->dev);
return err; return err;
} }
static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev)
{
int err;
err = clk_prepare_enable(fuse->clk);
if (err < 0) {
dev_err(dev, "failed to enable FUSE clock: %d\n", err);
return err;
}
return 0;
}
static int __maybe_unused tegra_fuse_runtime_suspend(struct device *dev)
{
clk_disable_unprepare(fuse->clk);
return 0;
}
static int __maybe_unused tegra_fuse_suspend(struct device *dev)
{
int ret;
/*
* Critical for RAM re-repair operation, which must occur on resume
* from LP1 system suspend and as part of CCPLEX cluster switching.
*/
if (fuse->soc->clk_suspend_on)
ret = pm_runtime_resume_and_get(dev);
else
ret = pm_runtime_force_suspend(dev);
return ret;
}
static int __maybe_unused tegra_fuse_resume(struct device *dev)
{
int ret = 0;
if (fuse->soc->clk_suspend_on)
pm_runtime_put(dev);
else
ret = pm_runtime_force_resume(dev);
return ret;
}
static const struct dev_pm_ops tegra_fuse_pm = {
SET_RUNTIME_PM_OPS(tegra_fuse_runtime_suspend, tegra_fuse_runtime_resume,
NULL)
SET_SYSTEM_SLEEP_PM_OPS(tegra_fuse_suspend, tegra_fuse_resume)
};
static struct platform_driver tegra_fuse_driver = { static struct platform_driver tegra_fuse_driver = {
.driver = { .driver = {
.name = "tegra-fuse", .name = "tegra-fuse",
.of_match_table = tegra_fuse_match, .of_match_table = tegra_fuse_match,
.pm = &tegra_fuse_pm,
.suppress_bind_attrs = true, .suppress_bind_attrs = true,
}, },
.probe = tegra_fuse_probe, .probe = tegra_fuse_probe,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/random.h> #include <linux/random.h>
#include <soc/tegra/fuse.h> #include <soc/tegra/fuse.h>
...@@ -46,6 +47,10 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) ...@@ -46,6 +47,10 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
u32 value = 0; u32 value = 0;
int err; int err;
err = pm_runtime_resume_and_get(fuse->dev);
if (err)
return err;
mutex_lock(&fuse->apbdma.lock); mutex_lock(&fuse->apbdma.lock);
fuse->apbdma.config.src_addr = fuse->phys + FUSE_BEGIN + offset; fuse->apbdma.config.src_addr = fuse->phys + FUSE_BEGIN + offset;
...@@ -66,8 +71,6 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) ...@@ -66,8 +71,6 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
reinit_completion(&fuse->apbdma.wait); reinit_completion(&fuse->apbdma.wait);
clk_prepare_enable(fuse->clk);
dmaengine_submit(dma_desc); dmaengine_submit(dma_desc);
dma_async_issue_pending(fuse->apbdma.chan); dma_async_issue_pending(fuse->apbdma.chan);
time_left = wait_for_completion_timeout(&fuse->apbdma.wait, time_left = wait_for_completion_timeout(&fuse->apbdma.wait,
...@@ -78,10 +81,9 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) ...@@ -78,10 +81,9 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
else else
value = *fuse->apbdma.virt; value = *fuse->apbdma.virt;
clk_disable_unprepare(fuse->clk);
out: out:
mutex_unlock(&fuse->apbdma.lock); mutex_unlock(&fuse->apbdma.lock);
pm_runtime_put(fuse->dev);
return value; return value;
} }
...@@ -165,4 +167,5 @@ const struct tegra_fuse_soc tegra20_fuse_soc = { ...@@ -165,4 +167,5 @@ const struct tegra_fuse_soc tegra20_fuse_soc = {
.probe = tegra20_fuse_probe, .probe = tegra20_fuse_probe,
.info = &tegra20_fuse_info, .info = &tegra20_fuse_info,
.soc_attr_group = &tegra_soc_attr_group, .soc_attr_group = &tegra_soc_attr_group,
.clk_suspend_on = false,
}; };
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/random.h> #include <linux/random.h>
#include <soc/tegra/fuse.h> #include <soc/tegra/fuse.h>
...@@ -52,15 +53,13 @@ static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset) ...@@ -52,15 +53,13 @@ static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
u32 value; u32 value;
int err; int err;
err = clk_prepare_enable(fuse->clk); err = pm_runtime_resume_and_get(fuse->dev);
if (err < 0) { if (err)
dev_err(fuse->dev, "failed to enable FUSE clock: %d\n", err);
return 0; return 0;
}
value = readl_relaxed(fuse->base + FUSE_BEGIN + offset); value = readl_relaxed(fuse->base + FUSE_BEGIN + offset);
clk_disable_unprepare(fuse->clk); pm_runtime_put(fuse->dev);
return value; return value;
} }
...@@ -113,6 +112,7 @@ const struct tegra_fuse_soc tegra30_fuse_soc = { ...@@ -113,6 +112,7 @@ const struct tegra_fuse_soc tegra30_fuse_soc = {
.speedo_init = tegra30_init_speedo_data, .speedo_init = tegra30_init_speedo_data,
.info = &tegra30_fuse_info, .info = &tegra30_fuse_info,
.soc_attr_group = &tegra_soc_attr_group, .soc_attr_group = &tegra_soc_attr_group,
.clk_suspend_on = false,
}; };
#endif #endif
...@@ -128,6 +128,7 @@ const struct tegra_fuse_soc tegra114_fuse_soc = { ...@@ -128,6 +128,7 @@ const struct tegra_fuse_soc tegra114_fuse_soc = {
.speedo_init = tegra114_init_speedo_data, .speedo_init = tegra114_init_speedo_data,
.info = &tegra114_fuse_info, .info = &tegra114_fuse_info,
.soc_attr_group = &tegra_soc_attr_group, .soc_attr_group = &tegra_soc_attr_group,
.clk_suspend_on = false,
}; };
#endif #endif
...@@ -209,6 +210,7 @@ const struct tegra_fuse_soc tegra124_fuse_soc = { ...@@ -209,6 +210,7 @@ const struct tegra_fuse_soc tegra124_fuse_soc = {
.lookups = tegra124_fuse_lookups, .lookups = tegra124_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra124_fuse_lookups), .num_lookups = ARRAY_SIZE(tegra124_fuse_lookups),
.soc_attr_group = &tegra_soc_attr_group, .soc_attr_group = &tegra_soc_attr_group,
.clk_suspend_on = true,
}; };
#endif #endif
...@@ -295,6 +297,7 @@ const struct tegra_fuse_soc tegra210_fuse_soc = { ...@@ -295,6 +297,7 @@ const struct tegra_fuse_soc tegra210_fuse_soc = {
.lookups = tegra210_fuse_lookups, .lookups = tegra210_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra210_fuse_lookups), .num_lookups = ARRAY_SIZE(tegra210_fuse_lookups),
.soc_attr_group = &tegra_soc_attr_group, .soc_attr_group = &tegra_soc_attr_group,
.clk_suspend_on = false,
}; };
#endif #endif
...@@ -325,6 +328,7 @@ const struct tegra_fuse_soc tegra186_fuse_soc = { ...@@ -325,6 +328,7 @@ const struct tegra_fuse_soc tegra186_fuse_soc = {
.lookups = tegra186_fuse_lookups, .lookups = tegra186_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra186_fuse_lookups), .num_lookups = ARRAY_SIZE(tegra186_fuse_lookups),
.soc_attr_group = &tegra_soc_attr_group, .soc_attr_group = &tegra_soc_attr_group,
.clk_suspend_on = false,
}; };
#endif #endif
...@@ -355,6 +359,7 @@ const struct tegra_fuse_soc tegra194_fuse_soc = { ...@@ -355,6 +359,7 @@ const struct tegra_fuse_soc tegra194_fuse_soc = {
.lookups = tegra194_fuse_lookups, .lookups = tegra194_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra194_fuse_lookups), .num_lookups = ARRAY_SIZE(tegra194_fuse_lookups),
.soc_attr_group = &tegra194_soc_attr_group, .soc_attr_group = &tegra194_soc_attr_group,
.clk_suspend_on = false,
}; };
#endif #endif
...@@ -385,5 +390,6 @@ const struct tegra_fuse_soc tegra234_fuse_soc = { ...@@ -385,5 +390,6 @@ const struct tegra_fuse_soc tegra234_fuse_soc = {
.lookups = tegra234_fuse_lookups, .lookups = tegra234_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra234_fuse_lookups), .num_lookups = ARRAY_SIZE(tegra234_fuse_lookups),
.soc_attr_group = &tegra194_soc_attr_group, .soc_attr_group = &tegra194_soc_attr_group,
.clk_suspend_on = false,
}; };
#endif #endif
...@@ -34,6 +34,8 @@ struct tegra_fuse_soc { ...@@ -34,6 +34,8 @@ struct tegra_fuse_soc {
unsigned int num_lookups; unsigned int num_lookups;
const struct attribute_group *soc_attr_group; const struct attribute_group *soc_attr_group;
bool clk_suspend_on;
}; };
struct tegra_fuse { struct tegra_fuse {
......
...@@ -436,7 +436,7 @@ struct tegra_pmc { ...@@ -436,7 +436,7 @@ struct tegra_pmc {
static struct tegra_pmc *pmc = &(struct tegra_pmc) { static struct tegra_pmc *pmc = &(struct tegra_pmc) {
.base = NULL, .base = NULL,
.suspend_mode = TEGRA_SUSPEND_NONE, .suspend_mode = TEGRA_SUSPEND_NOT_READY,
}; };
static inline struct tegra_powergate * static inline struct tegra_powergate *
...@@ -1812,6 +1812,7 @@ static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np) ...@@ -1812,6 +1812,7 @@ static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np)
u32 value, values[2]; u32 value, values[2];
if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) { if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) {
pmc->suspend_mode = TEGRA_SUSPEND_NONE;
} else { } else {
switch (value) { switch (value) {
case 0: case 0:
...@@ -2785,6 +2786,11 @@ static int tegra_pmc_regmap_init(struct tegra_pmc *pmc) ...@@ -2785,6 +2786,11 @@ static int tegra_pmc_regmap_init(struct tegra_pmc *pmc)
return 0; 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) static int tegra_pmc_probe(struct platform_device *pdev)
{ {
void __iomem *base; void __iomem *base;
...@@ -2803,6 +2809,11 @@ static int tegra_pmc_probe(struct platform_device *pdev) ...@@ -2803,6 +2809,11 @@ static int tegra_pmc_probe(struct platform_device *pdev)
if (err < 0) if (err < 0)
return err; 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 */ /* take over the memory region from the early initialization */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res); base = devm_ioremap_resource(&pdev->dev, res);
...@@ -2909,6 +2920,7 @@ static int tegra_pmc_probe(struct platform_device *pdev) ...@@ -2909,6 +2920,7 @@ static int tegra_pmc_probe(struct platform_device *pdev)
tegra_pmc_clock_register(pmc, pdev->dev.of_node); tegra_pmc_clock_register(pmc, pdev->dev.of_node);
platform_set_drvdata(pdev, pmc); platform_set_drvdata(pdev, pmc);
tegra_pm_init_suspend();
return 0; return 0;
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_domain.h> #include <linux/pm_domain.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/version.h>
#include <soc/tegra/bpmp.h> #include <soc/tegra/bpmp.h>
#include <soc/tegra/bpmp-abi.h> #include <soc/tegra/bpmp-abi.h>
......
...@@ -14,6 +14,7 @@ enum tegra_suspend_mode { ...@@ -14,6 +14,7 @@ enum tegra_suspend_mode {
TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */ TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */ TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
TEGRA_MAX_SUSPEND_MODE, TEGRA_MAX_SUSPEND_MODE,
TEGRA_SUSPEND_NOT_READY,
}; };
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
...@@ -28,6 +29,7 @@ void tegra_pm_clear_cpu_in_lp2(void); ...@@ -28,6 +29,7 @@ void tegra_pm_clear_cpu_in_lp2(void);
void tegra_pm_set_cpu_in_lp2(void); void tegra_pm_set_cpu_in_lp2(void);
int tegra_pm_enter_lp2(void); int tegra_pm_enter_lp2(void);
int tegra_pm_park_secondary_cpu(unsigned long cpu); int tegra_pm_park_secondary_cpu(unsigned long cpu);
void tegra_pm_init_suspend(void);
#else #else
static inline enum tegra_suspend_mode static inline enum tegra_suspend_mode
tegra_pm_validate_suspend_mode(enum tegra_suspend_mode 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) ...@@ -61,6 +63,10 @@ static inline int tegra_pm_park_secondary_cpu(unsigned long cpu)
{ {
return -ENOTSUPP; return -ENOTSUPP;
} }
static inline void tegra_pm_init_suspend(void)
{
}
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
#endif /* __SOC_TEGRA_PM_H__ */ #endif /* __SOC_TEGRA_PM_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment