drm/nouveau/tegra: acquire and enable reference clock if needed

GM20B requires an extra clock compared to GK20A. Add that information
into the platform data and acquire and enable this clock if necessary.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Alexandre Courbot 2016-04-01 11:37:44 +09:00 committed by Ben Skeggs
parent 52829d4fab
commit 34440ed697
3 changed files with 28 additions and 1 deletions

View file

@ -11,6 +11,7 @@ struct nvkm_device_tegra {
struct reset_control *rst;
struct clk *clk;
struct clk *clk_ref;
struct clk *clk_pwr;
struct regulator *vdd;
@ -36,6 +37,10 @@ struct nvkm_device_tegra_func {
* bypassed). A value of 0 means an IOMMU is never used.
*/
u8 iommu_bit;
/*
* Whether the chip requires a reference clock
*/
bool require_ref_clk;
};
int nvkm_device_tegra_new(const struct nvkm_device_tegra_func *,

View file

@ -55,6 +55,11 @@ static const struct nvkm_device_tegra_func gk20a_platform_data = {
.iommu_bit = 34,
};
static const struct nvkm_device_tegra_func gm20b_platform_data = {
.iommu_bit = 34,
.require_ref_clk = true,
};
static const struct of_device_id nouveau_platform_match[] = {
{
.compatible = "nvidia,gk20a",
@ -62,7 +67,7 @@ static const struct of_device_id nouveau_platform_match[] = {
},
{
.compatible = "nvidia,gm20b",
.data = &gk20a_platform_data,
.data = &gm20b_platform_data,
},
{ }
};

View file

@ -35,6 +35,11 @@ nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev)
ret = clk_prepare_enable(tdev->clk);
if (ret)
goto err_clk;
if (tdev->clk_ref) {
ret = clk_prepare_enable(tdev->clk_ref);
if (ret)
goto err_clk_ref;
}
ret = clk_prepare_enable(tdev->clk_pwr);
if (ret)
goto err_clk_pwr;
@ -57,6 +62,9 @@ nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev)
err_clamp:
clk_disable_unprepare(tdev->clk_pwr);
err_clk_pwr:
if (tdev->clk_ref)
clk_disable_unprepare(tdev->clk_ref);
err_clk_ref:
clk_disable_unprepare(tdev->clk);
err_clk:
regulator_disable(tdev->vdd);
@ -71,6 +79,8 @@ nvkm_device_tegra_power_down(struct nvkm_device_tegra *tdev)
udelay(10);
clk_disable_unprepare(tdev->clk_pwr);
if (tdev->clk_ref)
clk_disable_unprepare(tdev->clk_ref);
clk_disable_unprepare(tdev->clk);
udelay(10);
@ -274,6 +284,13 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
goto free;
}
if (func->require_ref_clk)
tdev->clk_ref = devm_clk_get(&pdev->dev, "ref");
if (IS_ERR(tdev->clk_ref)) {
ret = PTR_ERR(tdev->clk_ref);
goto free;
}
tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
if (IS_ERR(tdev->clk_pwr)) {
ret = PTR_ERR(tdev->clk_pwr);