Unverified Commit c4361dee authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'tegra-for-5.15-soc' of...

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: default avatarArnd Bergmann <arnd@arndb.de>
parents 8745d0e9 59c6fceb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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();

+0 −6
Original line number Diff line number Diff line
@@ -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_ */
+0 −2
Original line number Diff line number Diff line
@@ -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();
+60 −0
Original line number Diff line number Diff line
@@ -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,
+7 −4
Original line number Diff line number Diff line
@@ -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,
};
Loading