From ada604f08f81c517b2da479e40dfd91166708b9c Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:06 -0600 Subject: [PATCH] msm: kgsl: Use bulk clock functions for GMU Instead of using a bespoke function to get the list of clocks, use the built in functions instead. To do this, we'll need a local function to get a clock pointer by name from the list so this is a great time to add a file just for general purpose driver functions. Change-Id: Ic0dedbad96f478afc1a416a94df7c0e203ecca8a Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl_gmu.c | 93 ++++++++------------------------- drivers/gpu/msm/kgsl_gmu.h | 6 ++- drivers/gpu/msm/kgsl_gmu_core.h | 2 - drivers/gpu/msm/kgsl_util.c | 16 ++++++ drivers/gpu/msm/kgsl_util.h | 12 +++++ 5 files changed, 55 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index cca5e2ff240c..c6d9536b947c 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -942,34 +943,6 @@ static int gmu_reg_probe(struct kgsl_device *device) return 0; } -static int gmu_clocks_probe(struct gmu_device *gmu, struct device_node *node) -{ - const char *cname; - struct property *prop; - struct clk *c; - int i = 0; - - of_property_for_each_string(node, "clock-names", prop, cname) { - c = devm_clk_get(&gmu->pdev->dev, cname); - - if (IS_ERR(c)) { - dev_err(&gmu->pdev->dev, - "dt: Couldn't get GMU clock: %s\n", cname); - return PTR_ERR(c); - } - - if (i >= MAX_GMU_CLKS) { - dev_err(&gmu->pdev->dev, - "dt: too many GMU clocks defined\n"); - return -EINVAL; - } - - gmu->clks[i++] = c; - } - - return 0; -} - static int gmu_regulators_probe(struct gmu_device *gmu, struct device_node *node) { @@ -1206,11 +1179,20 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node) if (ret) goto error; - /* Set up GMU clocks */ - ret = gmu_clocks_probe(gmu, node); - if (ret) + ret = devm_clk_bulk_get_all(&gmu->pdev->dev, &gmu->clks); + if (ret < 0) goto error; + gmu->num_clks = ret; + + /* Get a pointer to the GMU clock */ + gmu->gmu_clk = kgsl_of_clk_by_name(gmu->clks, gmu->num_clks, "gmu_clk"); + if (!gmu->gmu_clk) { + dev_err(&gmu->pdev->dev, "Couldn't get gmu_clk\n"); + ret = -ENODEV; + goto error; + } + /* Set up GMU IOMMU and shared memory with GMU */ ret = gmu_iommu_init(gmu, node); if (ret) @@ -1304,48 +1286,30 @@ error: static int gmu_enable_clks(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - int ret, j = 0; + int ret; - if (IS_ERR_OR_NULL(gmu->clks[0])) - return -EINVAL; - - ret = clk_set_rate(gmu->clks[0], GMU_FREQUENCY); + ret = clk_set_rate(gmu->gmu_clk, GMU_FREQUENCY); if (ret) { - dev_err(&gmu->pdev->dev, "fail to set default GMU clk freq %d\n", - GMU_FREQUENCY); + dev_err(&gmu->pdev->dev, "Unable to set GMU clock\n"); return ret; } - while ((j < MAX_GMU_CLKS) && gmu->clks[j]) { - ret = clk_prepare_enable(gmu->clks[j]); - if (ret) { - dev_err(&gmu->pdev->dev, - "fail to enable gpucc clk idx %d\n", - j); - return ret; - } - j++; + ret = clk_bulk_prepare_enable(gmu->num_clks, gmu->clks); + if (ret) { + dev_err(&gmu->pdev->dev, "Cannot enable GMU clocks\n"); + return ret; } set_bit(GMU_CLK_ON, &device->gmu_core.flags); return 0; } -static int gmu_disable_clks(struct kgsl_device *device) +static void gmu_disable_clks(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - int j = 0; - - if (IS_ERR_OR_NULL(gmu->clks[0])) - return 0; - - while ((j < MAX_GMU_CLKS) && gmu->clks[j]) { - clk_disable_unprepare(gmu->clks[j]); - j++; - } + clk_bulk_disable_unprepare(gmu->num_clks, gmu->clks); clear_bit(GMU_CLK_ON, &device->gmu_core.flags); - return 0; } @@ -1592,7 +1556,6 @@ static void gmu_remove(struct kgsl_device *device) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct kgsl_hfi *hfi; - int i = 0; if (gmu == NULL || gmu->pdev == NULL) return; @@ -1608,11 +1571,6 @@ static void gmu_remove(struct kgsl_device *device) clear_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); - while ((i < MAX_GMU_CLKS) && gmu->clks[i]) { - gmu->clks[i] = NULL; - i++; - } - icc_put(gmu->icc_path); if (gmu->fw_image) { @@ -1622,13 +1580,6 @@ static void gmu_remove(struct kgsl_device *device) gmu_memory_close(gmu); - for (i = 0; i < MAX_GMU_CLKS; i++) { - if (gmu->clks[i]) { - devm_clk_put(&gmu->pdev->dev, gmu->clks[i]); - gmu->clks[i] = NULL; - } - } - if (gmu->gx_gdsc) { devm_regulator_put(gmu->gx_gdsc); gmu->gx_gdsc = NULL; diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h index 6f62f63c2c7f..3e539c02039e 100644 --- a/drivers/gpu/msm/kgsl_gmu.h +++ b/drivers/gpu/msm/kgsl_gmu.h @@ -206,7 +206,11 @@ struct gmu_device { struct rpmh_votes_t rpmh_votes; struct regulator *cx_gdsc; struct regulator *gx_gdsc; - struct clk *clks[MAX_GMU_CLKS]; + struct clk_bulk_data *clks; + /** @num_clks: Number of entries in the @clks array */ + int num_clks; + /** @gmu_clk: Pointer to the core GMU clock */ + struct clk *gmu_clk; enum gmu_load_mode load_mode; unsigned int wakeup_pwrlevel; unsigned int pcl; diff --git a/drivers/gpu/msm/kgsl_gmu_core.h b/drivers/gpu/msm/kgsl_gmu_core.h index cf1225a2c2e6..eb2c26bad1d5 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.h +++ b/drivers/gpu/msm/kgsl_gmu_core.h @@ -21,8 +21,6 @@ #error "CNOC levels cannot exceed GX levels" #endif -#define MAX_GMU_CLKS 6 - /* * These are the different ways the GMU can boot. GMU_WARM_BOOT is waking up * from slumber. GMU_COLD_BOOT is booting for the first time. GMU_RESET diff --git a/drivers/gpu/msm/kgsl_util.c b/drivers/gpu/msm/kgsl_util.c index 5a0b4a1baa8e..fbee7a5ace33 100644 --- a/drivers/gpu/msm/kgsl_util.c +++ b/drivers/gpu/msm/kgsl_util.c @@ -3,9 +3,13 @@ * Copyright (c) 2019, The Linux Foundation. All rights reserved. */ + +#include +#include #include #include #include +#include #include "kgsl_util.h" @@ -25,3 +29,15 @@ bool kgsl_regulator_disable_wait(struct regulator *reg, u32 timeout) usleep_range((100 >> 2) + 1, 100); } } + +struct clk *kgsl_of_clk_by_name(struct clk_bulk_data *clks, int count, + const char *id) +{ + int i; + + for (i = 0; clks && i < count; i++) + if (!strcmp(clks[i].id, id)) + return clks[i].clk; + + return NULL; +} diff --git a/drivers/gpu/msm/kgsl_util.h b/drivers/gpu/msm/kgsl_util.h index 403481cbdf26..839c04ffc44d 100644 --- a/drivers/gpu/msm/kgsl_util.h +++ b/drivers/gpu/msm/kgsl_util.h @@ -7,6 +7,7 @@ #define _KGSL_UTIL_H_ struct regulator; +struct clk_bulk_data; /** * kgsl_regulator_disable_wait - Disable a regulator and wait for it @@ -20,4 +21,15 @@ struct regulator; */ bool kgsl_regulator_disable_wait(struct regulator *reg, u32 timeout); +/** + * kgsl_of_clk_by_name - Return a clock device for a given name + * @clks: Pointer to an array of bulk clk data + * @count: Number of entries in the array + * @id: Name of the clock to search for + * + * Returns: A pointer to the clock device for the given name or NULL if not + * found + */ +struct clk *kgsl_of_clk_by_name(struct clk_bulk_data *clks, int count, + const char *id); #endif