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

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
...@@ -182,6 +182,12 @@ static const struct nvmem_cell_info tegra_fuse_cells[] = { ...@@ -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) static int tegra_fuse_probe(struct platform_device *pdev)
{ {
void __iomem *base = fuse->base; void __iomem *base = fuse->base;
...@@ -189,13 +195,16 @@ static int tegra_fuse_probe(struct platform_device *pdev) ...@@ -189,13 +195,16 @@ static int tegra_fuse_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
int err; 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 */ /* 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);
fuse->phys = res->start; fuse->phys = res->start;
fuse->base = devm_ioremap_resource(&pdev->dev, res); fuse->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(fuse->base)) { if (IS_ERR(fuse->base)) {
err = PTR_ERR(fuse->base); err = PTR_ERR(fuse->base);
fuse->base = base;
return err; return err;
} }
...@@ -205,19 +214,20 @@ static int tegra_fuse_probe(struct platform_device *pdev) ...@@ -205,19 +214,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to get FUSE clock: %ld", dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
PTR_ERR(fuse->clk)); PTR_ERR(fuse->clk));
fuse->base = base;
return PTR_ERR(fuse->clk); return PTR_ERR(fuse->clk);
} }
platform_set_drvdata(pdev, fuse); platform_set_drvdata(pdev, fuse);
fuse->dev = &pdev->dev; fuse->dev = &pdev->dev;
pm_runtime_enable(&pdev->dev); err = devm_pm_runtime_enable(&pdev->dev);
if (err)
return err;
if (fuse->soc->probe) { if (fuse->soc->probe) {
err = fuse->soc->probe(fuse); err = fuse->soc->probe(fuse);
if (err < 0) if (err < 0)
goto restore; return err;
} }
memset(&nvmem, 0, sizeof(nvmem)); memset(&nvmem, 0, sizeof(nvmem));
...@@ -241,7 +251,7 @@ static int tegra_fuse_probe(struct platform_device *pdev) ...@@ -241,7 +251,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
err = PTR_ERR(fuse->nvmem); err = PTR_ERR(fuse->nvmem);
dev_err(&pdev->dev, "failed to register NVMEM device: %d\n", dev_err(&pdev->dev, "failed to register NVMEM device: %d\n",
err); err);
goto restore; return err;
} }
fuse->rst = devm_reset_control_get_optional(&pdev->dev, "fuse"); fuse->rst = devm_reset_control_get_optional(&pdev->dev, "fuse");
...@@ -249,7 +259,7 @@ static int tegra_fuse_probe(struct platform_device *pdev) ...@@ -249,7 +259,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
err = PTR_ERR(fuse->rst); err = PTR_ERR(fuse->rst);
dev_err(&pdev->dev, "failed to get FUSE reset: %pe\n", dev_err(&pdev->dev, "failed to get FUSE reset: %pe\n",
fuse->rst); fuse->rst);
goto restore; return err;
} }
/* /*
...@@ -258,26 +268,20 @@ static int tegra_fuse_probe(struct platform_device *pdev) ...@@ -258,26 +268,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
*/ */
err = pm_runtime_resume_and_get(&pdev->dev); err = pm_runtime_resume_and_get(&pdev->dev);
if (err) if (err)
goto restore; return err;
err = reset_control_reset(fuse->rst); err = reset_control_reset(fuse->rst);
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "failed to reset FUSE: %d\n", err); dev_err(&pdev->dev, "failed to reset FUSE: %d\n", err);
goto restore; return err;
} }
/* release the early I/O memory mapping */ /* release the early I/O memory mapping */
iounmap(base); iounmap(base);
return 0; 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) static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev)
......
...@@ -94,9 +94,28 @@ static bool dma_filter(struct dma_chan *chan, void *filter_param) ...@@ -94,9 +94,28 @@ static bool dma_filter(struct dma_chan *chan, void *filter_param)
return of_device_is_compatible(np, "nvidia,tegra20-apbdma"); 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) static int tegra20_fuse_probe(struct tegra_fuse *fuse)
{ {
dma_cap_mask_t mask; dma_cap_mask_t mask;
int err;
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
...@@ -105,13 +124,21 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse) ...@@ -105,13 +124,21 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse)
if (!fuse->apbdma.chan) if (!fuse->apbdma.chan)
return -EPROBE_DEFER; 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.virt = dma_alloc_coherent(fuse->dev, sizeof(u32),
&fuse->apbdma.phys, &fuse->apbdma.phys,
GFP_KERNEL); GFP_KERNEL);
if (!fuse->apbdma.virt) { if (!fuse->apbdma.virt)
dma_release_channel(fuse->apbdma.chan);
return -ENOMEM; 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.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
fuse->apbdma.config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; fuse->apbdma.config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
......
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