summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c107
1 files changed, 75 insertions, 32 deletions
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index cd9a82a9bf4a..fe6aa45901d0 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1994,6 +1994,42 @@ static int _isense_clk_set_rate(struct kgsl_pwrctrl *pwr, int level)
return clk_set_rate(pwr->grp_clks[pwr->isense_clk_indx], rate);
}
+static inline void _close_pcl(struct kgsl_pwrctrl *pwr)
+{
+ if (pwr->pcl)
+ msm_bus_scale_unregister_client(pwr->pcl);
+
+ pwr->pcl = 0;
+}
+
+static inline void _close_ocmem_pcl(struct kgsl_pwrctrl *pwr)
+{
+ if (pwr->ocmem_pcl)
+ msm_bus_scale_unregister_client(pwr->ocmem_pcl);
+
+ pwr->ocmem_pcl = 0;
+}
+
+static inline void _close_regulators(struct kgsl_pwrctrl *pwr)
+{
+ int i;
+
+ for (i = 0; i < KGSL_MAX_REGULATORS; i++)
+ pwr->regulators[i].reg = NULL;
+}
+
+static inline void _close_clks(struct kgsl_device *device)
+{
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+ int i;
+
+ for (i = 0; i < KGSL_MAX_CLKS; i++)
+ pwr->grp_clks[i] = NULL;
+
+ if (pwr->gpu_bimc_int_clk)
+ devm_clk_put(&device->pdev->dev, pwr->gpu_bimc_int_clk);
+}
+
int kgsl_pwrctrl_init(struct kgsl_device *device)
{
int i, k, m, n = 0, result;
@@ -2011,7 +2047,7 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
result = _get_clocks(device);
if (result)
- return result;
+ goto error_cleanup_clks;
/* Make sure we have a source clk for freq setting */
if (pwr->grp_clks[0] == NULL)
@@ -2029,7 +2065,8 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
if (pwr->num_pwrlevels == 0) {
KGSL_PWR_ERR(device, "No power levels are defined\n");
- return -EINVAL;
+ result = -EINVAL;
+ goto error_cleanup_clks;
}
/* Initialize the user and thermal clock constraints */
@@ -2059,7 +2096,7 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
result = get_regulators(device);
if (result)
- return result;
+ goto error_cleanup_regulators;
pwr->power_flags = 0;
@@ -2079,8 +2116,10 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
pwr->ocmem_pcl = msm_bus_scale_register_client
(ocmem_scale_table);
- if (!pwr->ocmem_pcl)
- return -EINVAL;
+ if (!pwr->ocmem_pcl) {
+ result = -EINVAL;
+ goto error_disable_pm;
+ }
}
/* Bus width in bytes, set it to zero if not found */
@@ -2110,14 +2149,18 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
* from the driver.
*/
pwr->pcl = msm_bus_scale_register_client(bus_scale_table);
- if (pwr->pcl == 0)
- return -EINVAL;
+ if (pwr->pcl == 0) {
+ result = -EINVAL;
+ goto error_cleanup_ocmem_pcl;
+ }
}
pwr->bus_ib = kzalloc(bus_scale_table->num_usecases *
sizeof(*pwr->bus_ib), GFP_KERNEL);
- if (pwr->bus_ib == NULL)
- return -ENOMEM;
+ if (pwr->bus_ib == NULL) {
+ result = -ENOMEM;
+ goto error_cleanup_pcl;
+ }
/*
* Pull the BW vote out of the bus table. They will be used to
@@ -2175,36 +2218,26 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
&pwr->tsens_name);
return result;
+
+error_cleanup_pcl:
+ _close_pcl(pwr);
+error_cleanup_ocmem_pcl:
+ _close_ocmem_pcl(pwr);
+error_disable_pm:
+ pm_runtime_disable(&pdev->dev);
+error_cleanup_regulators:
+ _close_regulators(pwr);
+error_cleanup_clks:
+ _close_clks(device);
+ return result;
}
void kgsl_pwrctrl_close(struct kgsl_device *device)
{
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
- int i;
KGSL_PWR_INFO(device, "close device %d\n", device->id);
- pm_runtime_disable(&device->pdev->dev);
-
- if (pwr->pcl)
- msm_bus_scale_unregister_client(pwr->pcl);
-
- pwr->pcl = 0;
-
- if (pwr->ocmem_pcl)
- msm_bus_scale_unregister_client(pwr->ocmem_pcl);
-
- pwr->ocmem_pcl = 0;
-
- for (i = 0; i < KGSL_MAX_REGULATORS; i++)
- pwr->regulators[i].reg = NULL;
-
- for (i = 0; i < KGSL_MAX_REGULATORS; i++)
- pwr->grp_clks[i] = NULL;
-
- if (pwr->gpu_bimc_int_clk)
- devm_clk_put(&device->pdev->dev, pwr->gpu_bimc_int_clk);
-
pwr->power_flags = 0;
if (!IS_ERR_OR_NULL(pwr->sysfs_pwr_limit)) {
@@ -2213,6 +2246,16 @@ void kgsl_pwrctrl_close(struct kgsl_device *device)
pwr->sysfs_pwr_limit = NULL;
}
kfree(pwr->bus_ib);
+
+ _close_pcl(pwr);
+
+ _close_ocmem_pcl(pwr);
+
+ pm_runtime_disable(&device->pdev->dev);
+
+ _close_regulators(pwr);
+
+ _close_clks(device);
}
/**