Commit 88724b78 authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Thierry Reding
Browse files

soc/tegra: fuse: Use resource-managed helpers



Use resource-managed helpers to make code cleaner and more correct,
properly releasing all resources in case of driver probe error.

Signed-off-by: default avatarDmitry Osipenko <digetx@gmail.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent aeecc50a
Loading
Loading
Loading
Loading
+18 −14
Original line number Diff line number Diff line
@@ -182,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;
@@ -189,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;
	}

@@ -205,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));
@@ -241,7 +251,7 @@ 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");
@@ -249,7 +259,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
		err = PTR_ERR(fuse->rst);
		dev_err(&pdev->dev, "failed to get FUSE reset: %pe\n",
			fuse->rst);
		goto restore;
		return err;
	}

	/*
@@ -258,26 +268,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
	 */
	err = pm_runtime_resume_and_get(&pdev->dev);
	if (err)
		goto restore;
		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);
		goto restore;
		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;