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: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
parent
aeecc50ace
commit
88724b78a8
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user