Commit d2d0a9d2 authored by Thierry Reding's avatar Thierry Reding

drm/tegra: dsi: Properly cleanup on probe failure

The driver wasn't even attempting to do any cleanup when probing failed.
Fix this by releasing any resources acquired up to the point of failure
and putting the device back into the original state (reset, clocks off).
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent ba3df979
...@@ -861,64 +861,72 @@ static int tegra_dsi_probe(struct platform_device *pdev) ...@@ -861,64 +861,72 @@ static int tegra_dsi_probe(struct platform_device *pdev)
dsi->clk = devm_clk_get(&pdev->dev, NULL); dsi->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dsi->clk)) { if (IS_ERR(dsi->clk)) {
dev_err(&pdev->dev, "cannot get DSI clock\n"); dev_err(&pdev->dev, "cannot get DSI clock\n");
return PTR_ERR(dsi->clk); err = PTR_ERR(dsi->clk);
goto reset;
} }
err = clk_prepare_enable(dsi->clk); err = clk_prepare_enable(dsi->clk);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "cannot enable DSI clock\n"); dev_err(&pdev->dev, "cannot enable DSI clock\n");
return err; goto reset;
} }
dsi->clk_lp = devm_clk_get(&pdev->dev, "lp"); dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
if (IS_ERR(dsi->clk_lp)) { if (IS_ERR(dsi->clk_lp)) {
dev_err(&pdev->dev, "cannot get low-power clock\n"); dev_err(&pdev->dev, "cannot get low-power clock\n");
return PTR_ERR(dsi->clk_lp); err = PTR_ERR(dsi->clk_lp);
goto disable_clk;
} }
err = clk_prepare_enable(dsi->clk_lp); err = clk_prepare_enable(dsi->clk_lp);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "cannot enable low-power clock\n"); dev_err(&pdev->dev, "cannot enable low-power clock\n");
return err; goto disable_clk;
} }
dsi->clk_parent = devm_clk_get(&pdev->dev, "parent"); dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
if (IS_ERR(dsi->clk_parent)) { if (IS_ERR(dsi->clk_parent)) {
dev_err(&pdev->dev, "cannot get parent clock\n"); dev_err(&pdev->dev, "cannot get parent clock\n");
return PTR_ERR(dsi->clk_parent); err = PTR_ERR(dsi->clk_parent);
goto disable_clk_lp;
} }
dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi"); dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
if (IS_ERR(dsi->vdd)) { if (IS_ERR(dsi->vdd)) {
dev_err(&pdev->dev, "cannot get VDD supply\n"); dev_err(&pdev->dev, "cannot get VDD supply\n");
return PTR_ERR(dsi->vdd); err = PTR_ERR(dsi->vdd);
goto disable_clk_lp;
} }
err = regulator_enable(dsi->vdd); err = regulator_enable(dsi->vdd);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "cannot enable VDD supply\n"); dev_err(&pdev->dev, "cannot enable VDD supply\n");
return err; goto disable_clk_lp;
} }
err = tegra_dsi_setup_clocks(dsi); err = tegra_dsi_setup_clocks(dsi);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "cannot setup clocks\n"); dev_err(&pdev->dev, "cannot setup clocks\n");
return err; goto disable_vdd;
} }
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dsi->regs = devm_ioremap_resource(&pdev->dev, regs); dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
if (IS_ERR(dsi->regs)) if (IS_ERR(dsi->regs)) {
return PTR_ERR(dsi->regs); err = PTR_ERR(dsi->regs);
goto disable_vdd;
}
dsi->mipi = tegra_mipi_request(&pdev->dev); dsi->mipi = tegra_mipi_request(&pdev->dev);
if (IS_ERR(dsi->mipi)) if (IS_ERR(dsi->mipi)) {
return PTR_ERR(dsi->mipi); err = PTR_ERR(dsi->mipi);
goto disable_vdd;
}
err = tegra_dsi_pad_calibrate(dsi); err = tegra_dsi_pad_calibrate(dsi);
if (err < 0) { if (err < 0) {
dev_err(dsi->dev, "MIPI calibration failed: %d\n", err); dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
return err; goto mipi_free;
} }
dsi->host.ops = &tegra_dsi_host_ops; dsi->host.ops = &tegra_dsi_host_ops;
...@@ -927,7 +935,7 @@ static int tegra_dsi_probe(struct platform_device *pdev) ...@@ -927,7 +935,7 @@ static int tegra_dsi_probe(struct platform_device *pdev)
err = mipi_dsi_host_register(&dsi->host); err = mipi_dsi_host_register(&dsi->host);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "failed to register DSI host: %d\n", err); dev_err(&pdev->dev, "failed to register DSI host: %d\n", err);
return err; goto mipi_free;
} }
INIT_LIST_HEAD(&dsi->client.list); INIT_LIST_HEAD(&dsi->client.list);
...@@ -938,12 +946,26 @@ static int tegra_dsi_probe(struct platform_device *pdev) ...@@ -938,12 +946,26 @@ static int tegra_dsi_probe(struct platform_device *pdev)
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "failed to register host1x client: %d\n", dev_err(&pdev->dev, "failed to register host1x client: %d\n",
err); err);
return err; goto unregister;
} }
platform_set_drvdata(pdev, dsi); platform_set_drvdata(pdev, dsi);
return 0; return 0;
unregister:
mipi_dsi_host_unregister(&dsi->host);
mipi_free:
tegra_mipi_free(dsi->mipi);
disable_vdd:
regulator_disable(dsi->vdd);
disable_clk_lp:
clk_disable_unprepare(dsi->clk_lp);
disable_clk:
clk_disable_unprepare(dsi->clk);
reset:
reset_control_assert(dsi->rst);
return err;
} }
static int tegra_dsi_remove(struct platform_device *pdev) static int tegra_dsi_remove(struct platform_device *pdev)
......
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