Merge "msm: kgsl: Add GPU Cx ipeak client support on SDM660"
This commit is contained in:
commit
eee829e625
3 changed files with 86 additions and 1 deletions
|
@ -110,6 +110,17 @@ Optional Properties:
|
|||
- qcom,l2pc-cpu-mask-latency:
|
||||
The CPU mask latency in microseconds to avoid L2PC
|
||||
on masked CPUs.
|
||||
|
||||
- qcom,gpu-cx-ipeak:
|
||||
To handle Cx peak current limit.
|
||||
<phandle bit>
|
||||
phandle - phandle of cx ipeak device node
|
||||
bit - bit number of client in relevant register
|
||||
- qcom,gpu-cx-ipeak-clk:
|
||||
GPU clock threshold for Cx Ipeak voting. KGSL votes
|
||||
to Cx Ipeak driver when GPU clock crosses this threshold.
|
||||
Cx Ipeak can limit peak current based on voting from other clients.
|
||||
|
||||
- qcom,force-32bit:
|
||||
Force the GPU to use 32 bit data sizes even if
|
||||
it is capable of doing 64 bit.
|
||||
|
|
|
@ -361,6 +361,26 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
|
|||
if (new_level == old_level)
|
||||
return;
|
||||
|
||||
if (pwr->gpu_cx_ipeak) {
|
||||
unsigned int old_freq = pwr->pwrlevels[old_level].gpu_freq;
|
||||
unsigned int new_freq = pwr->pwrlevels[new_level].gpu_freq;
|
||||
|
||||
/*
|
||||
* Set Cx ipeak vote for GPU if it tries to cross
|
||||
* threshold frequency.
|
||||
*/
|
||||
if (old_freq < pwr->gpu_cx_ipeak_clk &&
|
||||
new_freq >= pwr->gpu_cx_ipeak_clk) {
|
||||
int ret = cx_ipeak_update(pwr->gpu_cx_ipeak, true);
|
||||
|
||||
if (ret) {
|
||||
KGSL_PWR_ERR(device,
|
||||
"cx_ipeak_update failed %d\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kgsl_pwrscale_update_stats(device);
|
||||
|
||||
/*
|
||||
|
@ -422,6 +442,24 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
|
|||
|
||||
/* Timestamp the frequency change */
|
||||
device->pwrscale.freq_change_time = ktime_to_ms(ktime_get());
|
||||
|
||||
if (pwr->gpu_cx_ipeak) {
|
||||
unsigned int old_freq = pwr->pwrlevels[old_level].gpu_freq;
|
||||
unsigned int new_freq = pwr->pwrlevels[new_level].gpu_freq;
|
||||
|
||||
/*
|
||||
* Reset Cx ipeak vote for GPU if it goes below
|
||||
* threshold frequency.
|
||||
*/
|
||||
if (old_freq >= pwr->gpu_cx_ipeak_clk &&
|
||||
new_freq < pwr->gpu_cx_ipeak_clk) {
|
||||
int ret = cx_ipeak_update(pwr->gpu_cx_ipeak, false);
|
||||
|
||||
if (ret)
|
||||
KGSL_PWR_ERR(device,
|
||||
"cx_ipeak_update failed %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(kgsl_pwrctrl_pwrlevel_change);
|
||||
|
||||
|
@ -2217,8 +2255,37 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
|
|||
of_property_read_string(pdev->dev.of_node, "qcom,tsens-name",
|
||||
&pwr->tsens_name);
|
||||
|
||||
/* Cx ipeak client support */
|
||||
if (of_find_property(pdev->dev.of_node, "qcom,gpu-cx-ipeak", NULL)) {
|
||||
if (!of_property_read_u32(pdev->dev.of_node,
|
||||
"qcom,gpu-cx-ipeak-clk", &pwr->gpu_cx_ipeak_clk)) {
|
||||
pwr->gpu_cx_ipeak = cx_ipeak_register(pdev->dev.of_node,
|
||||
"qcom,gpu-cx-ipeak");
|
||||
} else {
|
||||
KGSL_PWR_ERR(device, "failed to get gpu cxip clk\n");
|
||||
result = -EINVAL;
|
||||
goto error_cleanup_pwr_limit;
|
||||
}
|
||||
|
||||
if (IS_ERR(pwr->gpu_cx_ipeak)) {
|
||||
result = PTR_ERR(pwr->gpu_cx_ipeak);
|
||||
KGSL_PWR_ERR(device,
|
||||
"Failed to register Cx ipeak client %d\n",
|
||||
result);
|
||||
goto error_cleanup_pwr_limit;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
error_cleanup_pwr_limit:
|
||||
pwr->power_flags = 0;
|
||||
|
||||
if (!IS_ERR_OR_NULL(pwr->sysfs_pwr_limit)) {
|
||||
list_del(&pwr->sysfs_pwr_limit->node);
|
||||
kfree(pwr->sysfs_pwr_limit);
|
||||
pwr->sysfs_pwr_limit = NULL;
|
||||
}
|
||||
kfree(pwr->bus_ib);
|
||||
error_cleanup_pcl:
|
||||
_close_pcl(pwr);
|
||||
error_cleanup_ocmem_pcl:
|
||||
|
@ -2238,6 +2305,8 @@ void kgsl_pwrctrl_close(struct kgsl_device *device)
|
|||
|
||||
KGSL_PWR_INFO(device, "close device %d\n", device->id);
|
||||
|
||||
cx_ipeak_unregister(pwr->gpu_cx_ipeak);
|
||||
|
||||
pwr->power_flags = 0;
|
||||
|
||||
if (!IS_ERR_OR_NULL(pwr->sysfs_pwr_limit)) {
|
||||
|
|
|
@ -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
|
||||
|
@ -14,6 +14,7 @@
|
|||
#define __KGSL_PWRCTRL_H
|
||||
|
||||
#include <linux/pm_qos.h>
|
||||
#include <soc/qcom/cx_ipeak.h>
|
||||
|
||||
/*****************************************************************************
|
||||
** power flags
|
||||
|
@ -153,6 +154,8 @@ struct kgsl_regulator {
|
|||
* isense_clk_indx - index of isense clock, 0 if no isense
|
||||
* isense_clk_on_level - isense clock rate is XO rate below this level.
|
||||
* tsens_name - pointer to temperature sensor name of GPU temperature sensor
|
||||
* gpu_cx_ipeak - pointer to cx ipeak client used by GPU
|
||||
* gpu_cx_ipeak_clk - GPU threshold frequency to call cx ipeak driver API
|
||||
*/
|
||||
|
||||
struct kgsl_pwrctrl {
|
||||
|
@ -206,6 +209,8 @@ struct kgsl_pwrctrl {
|
|||
unsigned int gpu_bimc_int_clk_freq;
|
||||
bool gpu_bimc_interface_enabled;
|
||||
const char *tsens_name;
|
||||
struct cx_ipeak_client *gpu_cx_ipeak;
|
||||
unsigned int gpu_cx_ipeak_clk;
|
||||
};
|
||||
|
||||
int kgsl_pwrctrl_init(struct kgsl_device *device);
|
||||
|
|
Loading…
Add table
Reference in a new issue