drm/tegra: vic: Implement explicit reset support
Tegra supports generic PM domains on 64-bit ARM, and if that is enabled, the power domain code will make sure that resets are asserted and deasserted at appropriate points in time. If generic PM domains are not implemented, such as on 32-bit Tegra, the resets need to be asserted and deasserted explicitly by the driver. Reviewed-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
@@ -38,6 +38,7 @@ struct vic {
|
|||||||
struct iommu_domain *domain;
|
struct iommu_domain *domain;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
struct reset_control *rst;
|
||||||
|
|
||||||
/* Platform configuration */
|
/* Platform configuration */
|
||||||
const struct vic_config *config;
|
const struct vic_config *config;
|
||||||
@@ -56,13 +57,37 @@ static void vic_writel(struct vic *vic, u32 value, unsigned int offset)
|
|||||||
static int vic_runtime_resume(struct device *dev)
|
static int vic_runtime_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct vic *vic = dev_get_drvdata(dev);
|
struct vic *vic = dev_get_drvdata(dev);
|
||||||
|
int err;
|
||||||
|
|
||||||
return clk_prepare_enable(vic->clk);
|
err = clk_prepare_enable(vic->clk);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
usleep_range(10, 20);
|
||||||
|
|
||||||
|
err = reset_control_deassert(vic->rst);
|
||||||
|
if (err < 0)
|
||||||
|
goto disable;
|
||||||
|
|
||||||
|
usleep_range(10, 20);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
disable:
|
||||||
|
clk_disable_unprepare(vic->clk);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vic_runtime_suspend(struct device *dev)
|
static int vic_runtime_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct vic *vic = dev_get_drvdata(dev);
|
struct vic *vic = dev_get_drvdata(dev);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = reset_control_assert(vic->rst);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
usleep_range(2000, 4000);
|
||||||
|
|
||||||
clk_disable_unprepare(vic->clk);
|
clk_disable_unprepare(vic->clk);
|
||||||
|
|
||||||
@@ -323,6 +348,14 @@ static int vic_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(vic->clk);
|
return PTR_ERR(vic->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!dev->pm_domain) {
|
||||||
|
vic->rst = devm_reset_control_get(dev, "vic");
|
||||||
|
if (IS_ERR(vic->rst)) {
|
||||||
|
dev_err(&pdev->dev, "failed to get reset\n");
|
||||||
|
return PTR_ERR(vic->rst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vic->falcon.dev = dev;
|
vic->falcon.dev = dev;
|
||||||
vic->falcon.regs = vic->regs;
|
vic->falcon.regs = vic->regs;
|
||||||
vic->falcon.ops = &vic_falcon_ops;
|
vic->falcon.ops = &vic_falcon_ops;
|
||||||
|
|||||||
Reference in New Issue
Block a user