From 00a1ef124fb94dcacf869d92f3d7adbc37763826 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Tue, 25 Feb 2020 15:50:34 -0700 Subject: [PATCH 1/2] msm: kgsl: Move the IOMMU clocks to the KGSL device Move ownership of the IOMMU clocks to the KGSL device and get them from there during IOMMU probe. This ensures that the clocks are owned by a proper platform device that can sync_state() after we are done probing. Change-Id: Ic0dedbad97783984f7d8d1c3c2252a1a8a812d77 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl_iommu.c | 45 ++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 3c7e4ba64e63..18da7050d17e 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -2515,13 +2515,17 @@ static const struct { { "qcom,force-32bit", KGSL_MMU_FORCE_32BIT }, }; +static const char * const kgsl_iommu_clocks[] = { + "gcc_gpu_memnoc_gfx", + "gcc_gpu_snoc_dvm_gfx", + "gpu_cc_ahb", +}; + static int _kgsl_iommu_probe(struct kgsl_device *device, struct device_node *node) { - const char *cname; - struct property *prop; u32 reg_val[2]; - int i = 0, ret; + int ret, i, index = 0; struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct platform_device *pdev = of_find_device_by_node(node); @@ -2538,23 +2542,34 @@ static int _kgsl_iommu_probe(struct kgsl_device *device, iommu->regstart = reg_val[0]; iommu->regsize = reg_val[1]; - of_property_for_each_string(node, "clock-names", prop, cname) { - struct clk *c = devm_clk_get(&pdev->dev, cname); + /* Get the clock from the KGSL device */ + for (i = 0; i < ARRAY_SIZE(kgsl_iommu_clocks); i++) { + struct clk *c; - if (IS_ERR(c)) { - dev_err(device->dev, - "dt: Couldn't get clock: %s\n", cname); - platform_device_put(pdev); - return -ENODEV; - } - if (i >= KGSL_IOMMU_MAX_CLKS) { - dev_err(device->dev, "dt: too many clocks defined.\n"); + /* + * First try to get the clocks from the parent device and if + * that doesn't work fall back to getting them from the iommu + * platform device + */ + c = devm_clk_get(&device->pdev->dev, kgsl_iommu_clocks[i]); + if (IS_ERR(c)) + c = devm_clk_get(&pdev->dev, kgsl_iommu_clocks[i]); + + /* + * The list of clock names may diverge over the years so don't + * worry if we can't get a specific clock, eventually we'll get + * all the ones we need if we walk the list + */ + if (IS_ERR(c)) + continue; + + if (index >= KGSL_IOMMU_MAX_CLKS) { + dev_err(device->dev, "dt: too many clocks defined\n"); platform_device_put(pdev); return -EINVAL; } - iommu->clks[i] = c; - ++i; + iommu->clks[index++] = c; } for (i = 0; i < ARRAY_SIZE(kgsl_iommu_features); i++) { From 1c6fcc54eca96f2b7c35f6329949c4ae44979427 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 27 Feb 2020 10:33:28 -0700 Subject: [PATCH 2/2] msm: kgsl: Enable the CX GSDC before accessing IOMMU registers If needed, the IOMMU device can define a CX GDSC to enable before turning on clocks to directly write IOMMU registers. Change-Id: Ic0dedbadc8479cc36d5603d6d8a2c93133fda668 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl_iommu.c | 10 ++++++++++ drivers/gpu/msm/kgsl_iommu.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 18da7050d17e..d581b6932924 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "adreno.h" @@ -762,6 +763,9 @@ static void kgsl_iommu_disable_clk(struct kgsl_mmu *mmu) for (j = (KGSL_IOMMU_MAX_CLKS - 1); j >= 0; j--) if (iommu->clks[j]) clk_disable_unprepare(iommu->clks[j]); + + if (!IS_ERR_OR_NULL(iommu->cx_gdsc)) + regulator_disable(iommu->cx_gdsc); } /* @@ -789,6 +793,9 @@ static void kgsl_iommu_enable_clk(struct kgsl_mmu *mmu) int j; struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); + if (!IS_ERR_OR_NULL(iommu->cx_gdsc)) + regulator_enable(iommu->cx_gdsc); + for (j = 0; j < KGSL_IOMMU_MAX_CLKS; j++) { if (iommu->clks[j]) kgsl_iommu_clk_prepare_enable(iommu->clks[j]); @@ -2572,6 +2579,9 @@ static int _kgsl_iommu_probe(struct kgsl_device *device, iommu->clks[index++] = c; } + /* Get the CX regulator if it is available */ + iommu->cx_gdsc = devm_regulator_get(&pdev->dev, "vddcx"); + for (i = 0; i < ARRAY_SIZE(kgsl_iommu_features); i++) { if (of_property_read_bool(node, kgsl_iommu_features[i].feature)) device->mmu.features |= kgsl_iommu_features[i].bit; diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h index c20b051f6a84..6de90ba47f95 100644 --- a/drivers/gpu/msm/kgsl_iommu.h +++ b/drivers/gpu/msm/kgsl_iommu.h @@ -131,6 +131,8 @@ struct kgsl_iommu { u32 cb0_offset; /** @pagesize: Size of each context bank register space */ u32 pagesize; + /** @cx_gdsc: CX GDSC handle in case the IOMMU needs it */ + struct regulator *cx_gdsc; }; /*