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

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

Merge tag 'tegra-for-5.17-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into arm/drivers

soc/tegra: Changes for v5.17-rc1

This set of changes contains some preparatory work that is shared by
several branches and trees to support DVFS via power domains.

There's also a bit of cleanup and improvements to reboot on chips that
use PSCI.

* tag 'tegra-for-5.17-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  soc/tegra: pmc: Rename core power domain
  soc/tegra: pmc: Rename 3d power domains
  soc/tegra: regulators: Prepare for suspend
  soc/tegra: fuse: Use resource-managed helpers
  soc/tegra: fuse: Reset hardware
  soc/tegra: pmc: Add reboot notifier
  soc/tegra: Don't print error message when OPPs not available

Link: https://lore.kernel.org/r/20211217162253.1801077-1-thierry.reding@gmail.com


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents a1539b2e 81c4c86c
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -136,9 +136,7 @@ int devm_tegra_core_dev_init_opp_table(struct device *dev,
	 */
	err = devm_pm_opp_of_add_table(dev);
	if (err) {
		if (err == -ENODEV)
			dev_err_once(dev, "OPP table not found, please update device-tree\n");
		else
		if (err != -ENODEV)
			dev_err(dev, "failed to add OPP table: %d\n", err);

		return err;
+40 −11
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>

@@ -181,6 +182,12 @@ static const struct nvmem_cell_info tegra_fuse_cells[] = {
	},
};

static void tegra_fuse_restore(void *base)
{
	fuse->clk = NULL;
	fuse->base = base;
}

static int tegra_fuse_probe(struct platform_device *pdev)
{
	void __iomem *base = fuse->base;
@@ -188,13 +195,16 @@ static int tegra_fuse_probe(struct platform_device *pdev)
	struct resource *res;
	int err;

	err = devm_add_action(&pdev->dev, tegra_fuse_restore, base);
	if (err)
		return err;

	/* take over the memory region from the early initialization */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	fuse->phys = res->start;
	fuse->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(fuse->base)) {
		err = PTR_ERR(fuse->base);
		fuse->base = base;
		return err;
	}

@@ -204,19 +214,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
			dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
				PTR_ERR(fuse->clk));

		fuse->base = base;
		return PTR_ERR(fuse->clk);
	}

	platform_set_drvdata(pdev, fuse);
	fuse->dev = &pdev->dev;

	pm_runtime_enable(&pdev->dev);
	err = devm_pm_runtime_enable(&pdev->dev);
	if (err)
		return err;

	if (fuse->soc->probe) {
		err = fuse->soc->probe(fuse);
		if (err < 0)
			goto restore;
			return err;
	}

	memset(&nvmem, 0, sizeof(nvmem));
@@ -240,19 +251,37 @@ static int tegra_fuse_probe(struct platform_device *pdev)
		err = PTR_ERR(fuse->nvmem);
		dev_err(&pdev->dev, "failed to register NVMEM device: %d\n",
			err);
		goto restore;
		return err;
	}

	fuse->rst = devm_reset_control_get_optional(&pdev->dev, "fuse");
	if (IS_ERR(fuse->rst)) {
		err = PTR_ERR(fuse->rst);
		dev_err(&pdev->dev, "failed to get FUSE reset: %pe\n",
			fuse->rst);
		return err;
	}

	/*
	 * FUSE clock is enabled at a boot time, hence this resume/suspend
	 * disables the clock besides the h/w resetting.
	 */
	err = pm_runtime_resume_and_get(&pdev->dev);
	if (err)
		return err;

	err = reset_control_reset(fuse->rst);
	pm_runtime_put(&pdev->dev);

	if (err < 0) {
		dev_err(&pdev->dev, "failed to reset FUSE: %d\n", err);
		return err;
	}

	/* release the early I/O memory mapping */
	iounmap(base);

	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)
+30 −3
Original line number Diff line number Diff line
@@ -94,9 +94,28 @@ static bool dma_filter(struct dma_chan *chan, void *filter_param)
	return of_device_is_compatible(np, "nvidia,tegra20-apbdma");
}

static void tegra20_fuse_release_channel(void *data)
{
	struct tegra_fuse *fuse = data;

	dma_release_channel(fuse->apbdma.chan);
	fuse->apbdma.chan = NULL;
}

static void tegra20_fuse_free_coherent(void *data)
{
	struct tegra_fuse *fuse = data;

	dma_free_coherent(fuse->dev, sizeof(u32), fuse->apbdma.virt,
			  fuse->apbdma.phys);
	fuse->apbdma.virt = NULL;
	fuse->apbdma.phys = 0x0;
}

static int tegra20_fuse_probe(struct tegra_fuse *fuse)
{
	dma_cap_mask_t mask;
	int err;

	dma_cap_zero(mask);
	dma_cap_set(DMA_SLAVE, mask);
@@ -105,13 +124,21 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse)
	if (!fuse->apbdma.chan)
		return -EPROBE_DEFER;

	err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_release_channel,
				       fuse);
	if (err)
		return err;

	fuse->apbdma.virt = dma_alloc_coherent(fuse->dev, sizeof(u32),
					       &fuse->apbdma.phys,
					       GFP_KERNEL);
	if (!fuse->apbdma.virt) {
		dma_release_channel(fuse->apbdma.chan);
	if (!fuse->apbdma.virt)
		return -ENOMEM;
	}

	err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_free_coherent,
				       fuse);
	if (err)
		return err;

	fuse->apbdma.config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
	fuse->apbdma.config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ struct tegra_fuse {
	void __iomem *base;
	phys_addr_t phys;
	struct clk *clk;
	struct reset_control *rst;

	u32 (*read_early)(struct tegra_fuse *fuse, unsigned int offset);
	u32 (*read)(struct tegra_fuse *fuse, unsigned int offset);
+33 −8
Original line number Diff line number Diff line
@@ -1064,10 +1064,8 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid)
	return tegra_powergate_remove_clamping(id);
}

static int tegra_pmc_restart_notify(struct notifier_block *this,
				    unsigned long action, void *data)
static void tegra_pmc_program_reboot_reason(const char *cmd)
{
	const char *cmd = data;
	u32 value;

	value = tegra_pmc_scratch_readl(pmc, pmc->soc->regs->scratch0);
@@ -1085,6 +1083,25 @@ static int tegra_pmc_restart_notify(struct notifier_block *this,
	}

	tegra_pmc_scratch_writel(pmc, value, pmc->soc->regs->scratch0);
}

static int tegra_pmc_reboot_notify(struct notifier_block *this,
				   unsigned long action, void *data)
{
	if (action == SYS_RESTART)
		tegra_pmc_program_reboot_reason(data);

	return NOTIFY_DONE;
}

static struct notifier_block tegra_pmc_reboot_notifier = {
	.notifier_call = tegra_pmc_reboot_notify,
};

static int tegra_pmc_restart_notify(struct notifier_block *this,
				    unsigned long action, void *data)
{
	u32 value;

	/* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */
	value = tegra_pmc_readl(pmc, PMC_CNTRL);
@@ -1353,7 +1370,7 @@ static int tegra_pmc_core_pd_add(struct tegra_pmc *pmc, struct device_node *np)
	if (!genpd)
		return -ENOMEM;

	genpd->name = np->name;
	genpd->name = "core";
	genpd->set_performance_state = tegra_pmc_core_pd_set_performance_state;
	genpd->opp_to_performance_state = tegra_pmc_core_pd_opp_to_performance_state;

@@ -2890,6 +2907,14 @@ static int tegra_pmc_probe(struct platform_device *pdev)
			goto cleanup_sysfs;
	}

	err = devm_register_reboot_notifier(&pdev->dev,
					    &tegra_pmc_reboot_notifier);
	if (err) {
		dev_err(&pdev->dev, "unable to register reboot notifier, %d\n",
			err);
		goto cleanup_debugfs;
	}

	err = register_restart_handler(&tegra_pmc_restart_handler);
	if (err) {
		dev_err(&pdev->dev, "unable to register restart handler, %d\n",
@@ -2963,7 +2988,7 @@ static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume);

static const char * const tegra20_powergates[] = {
	[TEGRA_POWERGATE_CPU] = "cpu",
	[TEGRA_POWERGATE_3D] = "3d",
	[TEGRA_POWERGATE_3D] = "td",
	[TEGRA_POWERGATE_VENC] = "venc",
	[TEGRA_POWERGATE_VDEC] = "vdec",
	[TEGRA_POWERGATE_PCIE] = "pcie",
@@ -3071,7 +3096,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {

static const char * const tegra30_powergates[] = {
	[TEGRA_POWERGATE_CPU] = "cpu0",
	[TEGRA_POWERGATE_3D] = "3d0",
	[TEGRA_POWERGATE_3D] = "td",
	[TEGRA_POWERGATE_VENC] = "venc",
	[TEGRA_POWERGATE_VDEC] = "vdec",
	[TEGRA_POWERGATE_PCIE] = "pcie",
@@ -3083,7 +3108,7 @@ static const char * const tegra30_powergates[] = {
	[TEGRA_POWERGATE_CPU2] = "cpu2",
	[TEGRA_POWERGATE_CPU3] = "cpu3",
	[TEGRA_POWERGATE_CELP] = "celp",
	[TEGRA_POWERGATE_3D1] = "3d1",
	[TEGRA_POWERGATE_3D1] = "td2",
};

static const u8 tegra30_cpu_powergates[] = {
@@ -3132,7 +3157,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {

static const char * const tegra114_powergates[] = {
	[TEGRA_POWERGATE_CPU] = "crail",
	[TEGRA_POWERGATE_3D] = "3d",
	[TEGRA_POWERGATE_3D] = "td",
	[TEGRA_POWERGATE_VENC] = "venc",
	[TEGRA_POWERGATE_VDEC] = "vdec",
	[TEGRA_POWERGATE_MPE] = "mpe",
Loading