soc/tegra: Changes for v5.15-rc1
Implements runtime PM support for the FUSE block and prepares the driver to work better in conjunction with the CPUIDLE driver. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAmEWl5ATHHRyZWRpbmdA bnZpZGlhLmNvbQAKCRDdI6zXfz6zoZsWD/9KuRskoHLU9ism/+4ZW3zb7AthqYEd nE0mIjoRjZe8nOjBv4nBO40varyyO5nrA7+Ko5Vu4ArYOz+xFjKVNAYtYe3jqhvv fNlvcsMYoAf++3Sr35XjNi6ILQV0eKtZwT5rgLmzcKiC58JZ1y3DMi8YoD3x2MBh 49O68pG36GjkB6n1fMP/P7KgNmnhfO6AaQCDzxRYxAEKi2whq6jmxcZRIWYaIvPT DNTeU7DTFnBYGOmXAyG6qrl6IJKasO6QeU/YXS3XBCwF2XL4cNaWfXawDXm57v4Q 1G/rz4sUiBLeGoKKqvApuOeogKQpeAfWaZaeYr9wl8OI5yam/kQGcH+qi6kyiLCu W7N81RxVWPD2Ehuwn2hdr30Gqq/KtUcY5Dq3YCdP2SwL25fYxbac08FufH/ARPHZ MMTo32FhNp+6BYoD5aqFQJAKB0lCDjmZvYPYE1ux/yPysIDSLaVKFCenS0Ky+utA UzMUw/IoB2XhTEhgYbrdhcMFcvRTHbldPi6xndSz3RSBcRPLih/5PpKpBmtPPxAc TodJVnuIrQCjyQuNKrmlLEyYgbMD6LaX52x8JwLctCNYA/xH7ZXaxCjNXKNshynp w4wxGzGNpmTeisvSxin+knjJB8uZu/X9L+wRlzzhs3t6BKwagSJVl0CH5Wviy12P WeMvvgV5szk9cw== =migJ -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmEdCdsACgkQmmx57+YA GNnsexAApw0O9VGU7SCEE9w9drayJNljjaGoOR5HmIq9xgd7IpnGrBsOecVfjTqs Z48EB6zELIUrTSaUdfxMM7mF9PSCZyF9ekEl5dA6JeJ+4orvoDHcOOiMmRQxvBrs 0Sz9q7kCz1N+dabIPym2eOpzfW+EZbGorpadNek1SNAUOTCjPklgIIuXeXAkYWFU jak6Fsx3IbG28s8fsaSRDXJSfq40HFOLBlAs0qPykO+iKXYvUHdSrYRn7B8pTHHE c2agaS9Hao1+sTUsTTaHEexQRDSNJn31Xae8FQ1o3/Uny+U8fcPKDt9Uy4tcsNi6 rxS04z4dbm7tVwyasXoqxcwRtKcY4wvhMhniYz80BMAF3DdjsRPYcSmlscDF79aP KoeotPXmD6JLnyjmC0SimapQtbdBJsIivTukeuSCxGN7qgYF0YbOmfdlSTU5YtmP DXzaAcT6cJaefSSR5IgOxwa2v3LsDTO1HLbuhMtfQL32RaXxFNHjByBz250ltsO7 2hXTyMSkbo4NFeEdD4+JjmuIMkwh8L25NJDnUKjC5i0cn3568IfktAkxfKj/5qPs McI7oriaW//ljUroP7CAxsf+Y+FOIy/Bf9vgpmbCHaKns4xaJCCQc8jMIRzrqeE4 Y7yiaG5cktceQtLDHvTWZgMgC8FDO1UfFpBFdSYJkjcFbTOxlUk= =GgIf -----END PGP SIGNATURE----- Merge tag 'tegra-for-5.15-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into arm/drivers soc/tegra: Changes for v5.15-rc1 Implements runtime PM support for the FUSE block and prepares the driver to work better in conjunction with the CPUIDLE driver. * tag 'tegra-for-5.15-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux: soc/tegra: fuse: Enable fuse clock on suspend for Tegra124 soc/tegra: fuse: Add runtime PM support soc/tegra: fuse: Clear fuse->clk on driver probe failure soc/tegra: pmc: Prevent racing with cpuilde driver soc/tegra: bpmp: Remove unused including <linux/version.h> Link: https://lore.kernel.org/r/20210813162157.2820913-3-thierry.reding@gmail.com Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Коммит
c4361dee2e
|
@ -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();
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
|
@ -210,6 +211,8 @@ static int tegra_fuse_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, fuse);
|
||||
fuse->dev = &pdev->dev;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
if (fuse->soc->probe) {
|
||||
err = fuse->soc->probe(fuse);
|
||||
if (err < 0)
|
||||
|
@ -246,14 +249,71 @@ static int tegra_fuse_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
restore:
|
||||
fuse->clk = NULL;
|
||||
fuse->base = base;
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
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 = {
|
||||
.driver = {
|
||||
.name = "tegra-fuse",
|
||||
.of_match_table = tegra_fuse_match,
|
||||
.pm = &tegra_fuse_pm,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = tegra_fuse_probe,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/kobject.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <soc/tegra/fuse.h>
|
||||
|
@ -46,6 +47,10 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
|
|||
u32 value = 0;
|
||||
int err;
|
||||
|
||||
err = pm_runtime_resume_and_get(fuse->dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mutex_lock(&fuse->apbdma.lock);
|
||||
|
||||
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)
|
|||
|
||||
reinit_completion(&fuse->apbdma.wait);
|
||||
|
||||
clk_prepare_enable(fuse->clk);
|
||||
|
||||
dmaengine_submit(dma_desc);
|
||||
dma_async_issue_pending(fuse->apbdma.chan);
|
||||
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)
|
|||
else
|
||||
value = *fuse->apbdma.virt;
|
||||
|
||||
clk_disable_unprepare(fuse->clk);
|
||||
|
||||
out:
|
||||
mutex_unlock(&fuse->apbdma.lock);
|
||||
pm_runtime_put(fuse->dev);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -165,4 +167,5 @@ const struct tegra_fuse_soc tegra20_fuse_soc = {
|
|||
.probe = tegra20_fuse_probe,
|
||||
.info = &tegra20_fuse_info,
|
||||
.soc_attr_group = &tegra_soc_attr_group,
|
||||
.clk_suspend_on = false,
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/of_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <soc/tegra/fuse.h>
|
||||
|
@ -52,15 +53,13 @@ static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
|
|||
u32 value;
|
||||
int err;
|
||||
|
||||
err = clk_prepare_enable(fuse->clk);
|
||||
if (err < 0) {
|
||||
dev_err(fuse->dev, "failed to enable FUSE clock: %d\n", err);
|
||||
err = pm_runtime_resume_and_get(fuse->dev);
|
||||
if (err)
|
||||
return 0;
|
||||
}
|
||||
|
||||
value = readl_relaxed(fuse->base + FUSE_BEGIN + offset);
|
||||
|
||||
clk_disable_unprepare(fuse->clk);
|
||||
pm_runtime_put(fuse->dev);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -113,6 +112,7 @@ const struct tegra_fuse_soc tegra30_fuse_soc = {
|
|||
.speedo_init = tegra30_init_speedo_data,
|
||||
.info = &tegra30_fuse_info,
|
||||
.soc_attr_group = &tegra_soc_attr_group,
|
||||
.clk_suspend_on = false,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -128,6 +128,7 @@ const struct tegra_fuse_soc tegra114_fuse_soc = {
|
|||
.speedo_init = tegra114_init_speedo_data,
|
||||
.info = &tegra114_fuse_info,
|
||||
.soc_attr_group = &tegra_soc_attr_group,
|
||||
.clk_suspend_on = false,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -209,6 +210,7 @@ const struct tegra_fuse_soc tegra124_fuse_soc = {
|
|||
.lookups = tegra124_fuse_lookups,
|
||||
.num_lookups = ARRAY_SIZE(tegra124_fuse_lookups),
|
||||
.soc_attr_group = &tegra_soc_attr_group,
|
||||
.clk_suspend_on = true,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -295,6 +297,7 @@ const struct tegra_fuse_soc tegra210_fuse_soc = {
|
|||
.lookups = tegra210_fuse_lookups,
|
||||
.num_lookups = ARRAY_SIZE(tegra210_fuse_lookups),
|
||||
.soc_attr_group = &tegra_soc_attr_group,
|
||||
.clk_suspend_on = false,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -325,6 +328,7 @@ const struct tegra_fuse_soc tegra186_fuse_soc = {
|
|||
.lookups = tegra186_fuse_lookups,
|
||||
.num_lookups = ARRAY_SIZE(tegra186_fuse_lookups),
|
||||
.soc_attr_group = &tegra_soc_attr_group,
|
||||
.clk_suspend_on = false,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -355,6 +359,7 @@ const struct tegra_fuse_soc tegra194_fuse_soc = {
|
|||
.lookups = tegra194_fuse_lookups,
|
||||
.num_lookups = ARRAY_SIZE(tegra194_fuse_lookups),
|
||||
.soc_attr_group = &tegra194_soc_attr_group,
|
||||
.clk_suspend_on = false,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -385,5 +390,6 @@ const struct tegra_fuse_soc tegra234_fuse_soc = {
|
|||
.lookups = tegra234_fuse_lookups,
|
||||
.num_lookups = ARRAY_SIZE(tegra234_fuse_lookups),
|
||||
.soc_attr_group = &tegra194_soc_attr_group,
|
||||
.clk_suspend_on = false,
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,8 @@ struct tegra_fuse_soc {
|
|||
unsigned int num_lookups;
|
||||
|
||||
const struct attribute_group *soc_attr_group;
|
||||
|
||||
bool clk_suspend_on;
|
||||
};
|
||||
|
||||
struct tegra_fuse {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <soc/tegra/bpmp.h>
|
||||
#include <soc/tegra/bpmp-abi.h>
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче