summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2021-07-08 16:37:36 +0200
committerThierry Reding <treding@nvidia.com>2021-12-16 14:07:07 +0100
commit271fca025a6d43f1c18a48543c5aaf31a31e4694 (patch)
tree0a6c900d75eefbf41ff57d181e9dbf311ef6a995
parent6c7a388b62366f0de9936db3c1921d7f4e0011bc (diff)
downloadlinux-271fca025a6d43f1c18a48543c5aaf31a31e4694.tar.bz2
drm/tegra: gr2d: Explicitly control module reset
As of commit 4782c0a5dd88 ("clk: tegra: Don't deassert reset on enabling clocks"), module resets are no longer automatically deasserted when the module clock is enabled. To make sure that the gr2d module continues to work, we need to explicitly control the module reset. Fixes: 4782c0a5dd88 ("clk: tegra: Don't deassert reset on enabling clocks") Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/gpu/drm/tegra/gr2d.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index de288cba3905..ba3722f1b865 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -4,9 +4,11 @@
*/
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/reset.h>
#include "drm.h"
#include "gem.h"
@@ -19,6 +21,7 @@ struct gr2d_soc {
struct gr2d {
struct tegra_drm_client client;
struct host1x_channel *channel;
+ struct reset_control *rst;
struct clk *clk;
const struct gr2d_soc *soc;
@@ -208,6 +211,12 @@ static int gr2d_probe(struct platform_device *pdev)
if (!syncpts)
return -ENOMEM;
+ gr2d->rst = devm_reset_control_get(dev, NULL);
+ if (IS_ERR(gr2d->rst)) {
+ dev_err(dev, "cannot get reset\n");
+ return PTR_ERR(gr2d->rst);
+ }
+
gr2d->clk = devm_clk_get(dev, NULL);
if (IS_ERR(gr2d->clk)) {
dev_err(dev, "cannot get clock\n");
@@ -220,6 +229,14 @@ static int gr2d_probe(struct platform_device *pdev)
return err;
}
+ usleep_range(2000, 4000);
+
+ err = reset_control_deassert(gr2d->rst);
+ if (err < 0) {
+ dev_err(dev, "failed to deassert reset: %d\n", err);
+ goto disable_clk;
+ }
+
INIT_LIST_HEAD(&gr2d->client.base.list);
gr2d->client.base.ops = &gr2d_client_ops;
gr2d->client.base.dev = dev;
@@ -234,8 +251,7 @@ static int gr2d_probe(struct platform_device *pdev)
err = host1x_client_register(&gr2d->client.base);
if (err < 0) {
dev_err(dev, "failed to register host1x client: %d\n", err);
- clk_disable_unprepare(gr2d->clk);
- return err;
+ goto assert_rst;
}
/* initialize address register map */
@@ -245,6 +261,13 @@ static int gr2d_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, gr2d);
return 0;
+
+assert_rst:
+ (void)reset_control_assert(gr2d->rst);
+disable_clk:
+ clk_disable_unprepare(gr2d->clk);
+
+ return err;
}
static int gr2d_remove(struct platform_device *pdev)
@@ -259,6 +282,12 @@ static int gr2d_remove(struct platform_device *pdev)
return err;
}
+ err = reset_control_assert(gr2d->rst);
+ if (err < 0)
+ dev_err(&pdev->dev, "failed to assert reset: %d\n", err);
+
+ usleep_range(2000, 4000);
+
clk_disable_unprepare(gr2d->clk);
return 0;