msm: kgsl: Add and link gpu sysfs nodes
Add new sysfs nodes which satisfy a generic format requested by customer. Also add a new node to track GPU temperature. Create links to these nodes at a generic location: /sys/kernel/gpu/ CRs-Fixed: 1064728 Change-Id: I414a07ff4f9ee14b8f882d15644b06a73d5fcf76 Signed-off-by: Harshdeep Dhatt <hdhatt@codeaurora.org>
This commit is contained in:
parent
057bdafd97
commit
1cf6397fff
7 changed files with 355 additions and 41 deletions
|
@ -139,6 +139,10 @@ Optional Properties:
|
||||||
baseAddr - base address of the gpu channels in the qdss stm memory region
|
baseAddr - base address of the gpu channels in the qdss stm memory region
|
||||||
size - size of the gpu stm region
|
size - size of the gpu stm region
|
||||||
|
|
||||||
|
- qcom,tsens-name:
|
||||||
|
Specify the name of GPU temperature sensor. This name will be used
|
||||||
|
to get the temperature from the thermal driver API.
|
||||||
|
|
||||||
GPU Quirks:
|
GPU Quirks:
|
||||||
- qcom,gpu-quirk-two-pass-use-wfi:
|
- qcom,gpu-quirk-two-pass-use-wfi:
|
||||||
Signal the GPU to set Set TWOPASSUSEWFI bit in
|
Signal the GPU to set Set TWOPASSUSEWFI bit in
|
||||||
|
|
|
@ -2799,6 +2799,18 @@ static void adreno_regulator_disable_poll(struct kgsl_device *device)
|
||||||
adreno_iommu_sync(device, false);
|
adreno_iommu_sync(device, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void adreno_gpu_model(struct kgsl_device *device, char *str,
|
||||||
|
size_t bufsz)
|
||||||
|
{
|
||||||
|
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||||
|
|
||||||
|
snprintf(str, bufsz, "Adreno%d%d%dv%d",
|
||||||
|
ADRENO_CHIPID_CORE(adreno_dev->chipid),
|
||||||
|
ADRENO_CHIPID_MAJOR(adreno_dev->chipid),
|
||||||
|
ADRENO_CHIPID_MINOR(adreno_dev->chipid),
|
||||||
|
ADRENO_CHIPID_PATCH(adreno_dev->chipid) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct kgsl_functable adreno_functable = {
|
static const struct kgsl_functable adreno_functable = {
|
||||||
/* Mandatory functions */
|
/* Mandatory functions */
|
||||||
.regread = adreno_regread,
|
.regread = adreno_regread,
|
||||||
|
@ -2835,7 +2847,8 @@ static const struct kgsl_functable adreno_functable = {
|
||||||
.regulator_disable = adreno_regulator_disable,
|
.regulator_disable = adreno_regulator_disable,
|
||||||
.pwrlevel_change_settings = adreno_pwrlevel_change_settings,
|
.pwrlevel_change_settings = adreno_pwrlevel_change_settings,
|
||||||
.regulator_disable_poll = adreno_regulator_disable_poll,
|
.regulator_disable_poll = adreno_regulator_disable_poll,
|
||||||
.clk_set_options = adreno_clk_set_options
|
.clk_set_options = adreno_clk_set_options,
|
||||||
|
.gpu_model = adreno_gpu_model,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct platform_driver adreno_platform_driver = {
|
static struct platform_driver adreno_platform_driver = {
|
||||||
|
|
|
@ -579,4 +579,19 @@ static inline void __user *to_user_ptr(uint64_t address)
|
||||||
return (void __user *)(uintptr_t)address;
|
return (void __user *)(uintptr_t)address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void kgsl_gpu_sysfs_add_link(struct kobject *dst,
|
||||||
|
struct kobject *src, const char *src_name,
|
||||||
|
const char *dst_name)
|
||||||
|
{
|
||||||
|
struct kernfs_node *old;
|
||||||
|
|
||||||
|
if (dst == NULL || src == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
old = sysfs_get_dirent(src->sd, src_name);
|
||||||
|
if (IS_ERR_OR_NULL(old))
|
||||||
|
return;
|
||||||
|
|
||||||
|
kernfs_create_link(dst->sd, dst_name, old);
|
||||||
|
}
|
||||||
#endif /* __KGSL_H */
|
#endif /* __KGSL_H */
|
||||||
|
|
|
@ -167,6 +167,8 @@ struct kgsl_functable {
|
||||||
void (*regulator_disable_poll)(struct kgsl_device *device);
|
void (*regulator_disable_poll)(struct kgsl_device *device);
|
||||||
void (*clk_set_options)(struct kgsl_device *device,
|
void (*clk_set_options)(struct kgsl_device *device,
|
||||||
const char *name, struct clk *clk);
|
const char *name, struct clk *clk);
|
||||||
|
void (*gpu_model)(struct kgsl_device *device, char *str,
|
||||||
|
size_t bufsz);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kgsl_ioctl {
|
struct kgsl_ioctl {
|
||||||
|
@ -281,6 +283,7 @@ struct kgsl_device {
|
||||||
|
|
||||||
/* Number of active contexts seen globally for this device */
|
/* Number of active contexts seen globally for this device */
|
||||||
int active_context_count;
|
int active_context_count;
|
||||||
|
struct kobject *gpu_sysfs_kobj;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define KGSL_MMU_DEVICE(_mmu) \
|
#define KGSL_MMU_DEVICE(_mmu) \
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/msm_adreno_devfreq.h>
|
#include <linux/msm_adreno_devfreq.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/thermal.h>
|
||||||
|
|
||||||
#include "kgsl.h"
|
#include "kgsl.h"
|
||||||
#include "kgsl_pwrscale.h"
|
#include "kgsl_pwrscale.h"
|
||||||
|
@ -590,22 +591,10 @@ static ssize_t kgsl_pwrctrl_max_pwrlevel_show(struct device *dev,
|
||||||
return snprintf(buf, PAGE_SIZE, "%u\n", pwr->max_pwrlevel);
|
return snprintf(buf, PAGE_SIZE, "%u\n", pwr->max_pwrlevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t kgsl_pwrctrl_min_pwrlevel_store(struct device *dev,
|
static void kgsl_pwrctrl_min_pwrlevel_set(struct kgsl_device *device,
|
||||||
struct device_attribute *attr,
|
int level)
|
||||||
const char *buf, size_t count)
|
{
|
||||||
{ struct kgsl_device *device = kgsl_device_from_dev(dev);
|
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
|
||||||
struct kgsl_pwrctrl *pwr;
|
|
||||||
int ret;
|
|
||||||
unsigned int level = 0;
|
|
||||||
|
|
||||||
if (device == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
pwr = &device->pwrctrl;
|
|
||||||
|
|
||||||
ret = kgsl_sysfs_store(buf, &level);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
mutex_lock(&device->mutex);
|
mutex_lock(&device->mutex);
|
||||||
if (level > pwr->num_pwrlevels - 2)
|
if (level > pwr->num_pwrlevels - 2)
|
||||||
|
@ -621,6 +610,24 @@ static ssize_t kgsl_pwrctrl_min_pwrlevel_store(struct device *dev,
|
||||||
kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel);
|
kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel);
|
||||||
|
|
||||||
mutex_unlock(&device->mutex);
|
mutex_unlock(&device->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_min_pwrlevel_store(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
int ret;
|
||||||
|
unsigned int level = 0;
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = kgsl_sysfs_store(buf, &level);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
kgsl_pwrctrl_min_pwrlevel_set(device, level);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -664,24 +671,13 @@ static int _get_nearest_pwrlevel(struct kgsl_pwrctrl *pwr, unsigned int clock)
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t kgsl_pwrctrl_max_gpuclk_store(struct device *dev,
|
static void kgsl_pwrctrl_max_clock_set(struct kgsl_device *device, int val)
|
||||||
struct device_attribute *attr,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
{
|
||||||
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
|
||||||
struct kgsl_pwrctrl *pwr;
|
struct kgsl_pwrctrl *pwr;
|
||||||
unsigned int val = 0;
|
int level;
|
||||||
int level, ret;
|
|
||||||
|
|
||||||
if (device == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
pwr = &device->pwrctrl;
|
pwr = &device->pwrctrl;
|
||||||
|
|
||||||
ret = kgsl_sysfs_store(buf, &val);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
mutex_lock(&device->mutex);
|
mutex_lock(&device->mutex);
|
||||||
level = _get_nearest_pwrlevel(pwr, val);
|
level = _get_nearest_pwrlevel(pwr, val);
|
||||||
/* If the requested power level is not supported by hw, try cycling */
|
/* If the requested power level is not supported by hw, try cycling */
|
||||||
|
@ -715,21 +711,37 @@ static ssize_t kgsl_pwrctrl_max_gpuclk_store(struct device *dev,
|
||||||
if (pwr->sysfs_pwr_limit)
|
if (pwr->sysfs_pwr_limit)
|
||||||
kgsl_pwr_limits_set_freq(pwr->sysfs_pwr_limit,
|
kgsl_pwr_limits_set_freq(pwr->sysfs_pwr_limit,
|
||||||
pwr->pwrlevels[level].gpu_freq);
|
pwr->pwrlevels[level].gpu_freq);
|
||||||
return count;
|
return;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
mutex_unlock(&device->mutex);
|
mutex_unlock(&device->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_max_gpuclk_store(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
unsigned int val = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = kgsl_sysfs_store(buf, &val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
kgsl_pwrctrl_max_clock_set(device, val);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t kgsl_pwrctrl_max_gpuclk_show(struct device *dev,
|
static unsigned int kgsl_pwrctrl_max_clock_get(struct kgsl_device *device)
|
||||||
struct device_attribute *attr,
|
|
||||||
char *buf)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
|
||||||
struct kgsl_pwrctrl *pwr;
|
struct kgsl_pwrctrl *pwr;
|
||||||
unsigned int freq;
|
unsigned int freq;
|
||||||
|
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
pwr = &device->pwrctrl;
|
pwr = &device->pwrctrl;
|
||||||
|
@ -743,7 +755,17 @@ static ssize_t kgsl_pwrctrl_max_gpuclk_show(struct device *dev,
|
||||||
(TH_HZ - pwr->thermal_timeout) * (hfreq / TH_HZ);
|
(TH_HZ - pwr->thermal_timeout) * (hfreq / TH_HZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
return snprintf(buf, PAGE_SIZE, "%d\n", freq);
|
return freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_max_gpuclk_show(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||||
|
kgsl_pwrctrl_max_clock_get(device));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t kgsl_pwrctrl_gpuclk_store(struct device *dev,
|
static ssize_t kgsl_pwrctrl_gpuclk_store(struct device *dev,
|
||||||
|
@ -903,9 +925,14 @@ static ssize_t kgsl_pwrctrl_gpu_available_frequencies_show(
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
pwr = &device->pwrctrl;
|
pwr = &device->pwrctrl;
|
||||||
for (index = 0; index < pwr->num_pwrlevels - 1; index++)
|
for (index = 0; index < pwr->num_pwrlevels - 1; index++) {
|
||||||
num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",
|
num_chars += scnprintf(buf + num_chars,
|
||||||
pwr->pwrlevels[index].gpu_freq);
|
PAGE_SIZE - num_chars - 1,
|
||||||
|
"%d ", pwr->pwrlevels[index].gpu_freq);
|
||||||
|
/* One space for trailing null and another for the newline */
|
||||||
|
if (num_chars >= PAGE_SIZE - 2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
buf[num_chars++] = '\n';
|
buf[num_chars++] = '\n';
|
||||||
return num_chars;
|
return num_chars;
|
||||||
}
|
}
|
||||||
|
@ -1171,6 +1198,195 @@ static ssize_t kgsl_popp_show(struct device *dev,
|
||||||
test_bit(POPP_ON, &device->pwrscale.popp_state));
|
test_bit(POPP_ON, &device->pwrscale.popp_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_gpu_model_show(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
char model_str[32] = {0};
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
device->ftbl->gpu_model(device, model_str, sizeof(model_str));
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%s\n", model_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_gpu_busy_percentage_show(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
struct kgsl_clk_stats *stats;
|
||||||
|
unsigned int busy_percent = 0;
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
stats = &device->pwrctrl.clk_stats;
|
||||||
|
|
||||||
|
if (stats->total_old != 0)
|
||||||
|
busy_percent = (stats->busy_old * 100) / stats->total_old;
|
||||||
|
|
||||||
|
ret = snprintf(buf, PAGE_SIZE, "%d %%\n", busy_percent);
|
||||||
|
|
||||||
|
/* Reset the stats if GPU is OFF */
|
||||||
|
if (!test_bit(KGSL_PWRFLAGS_AXI_ON, &device->pwrctrl.power_flags)) {
|
||||||
|
stats->busy_old = 0;
|
||||||
|
stats->total_old = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_min_clock_mhz_show(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
struct kgsl_pwrctrl *pwr;
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
pwr = &device->pwrctrl;
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||||
|
pwr->pwrlevels[pwr->min_pwrlevel].gpu_freq / 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_min_clock_mhz_store(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
int level, ret;
|
||||||
|
unsigned int freq;
|
||||||
|
struct kgsl_pwrctrl *pwr;
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pwr = &device->pwrctrl;
|
||||||
|
|
||||||
|
ret = kgsl_sysfs_store(buf, &freq);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
freq *= 1000000;
|
||||||
|
level = _get_nearest_pwrlevel(pwr, freq);
|
||||||
|
|
||||||
|
if (level >= 0)
|
||||||
|
kgsl_pwrctrl_min_pwrlevel_set(device, level);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_max_clock_mhz_show(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
unsigned int freq;
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
freq = kgsl_pwrctrl_max_clock_get(device);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%d\n", freq / 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_max_clock_mhz_store(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
unsigned int val = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = kgsl_sysfs_store(buf, &val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val *= 1000000;
|
||||||
|
kgsl_pwrctrl_max_clock_set(device, val);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_clock_mhz_show(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%ld\n",
|
||||||
|
kgsl_pwrctrl_active_freq(&device->pwrctrl) / 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_freq_table_mhz_show(
|
||||||
|
struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
struct kgsl_pwrctrl *pwr;
|
||||||
|
int index, num_chars = 0;
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pwr = &device->pwrctrl;
|
||||||
|
for (index = 0; index < pwr->num_pwrlevels - 1; index++) {
|
||||||
|
num_chars += scnprintf(buf + num_chars,
|
||||||
|
PAGE_SIZE - num_chars - 1,
|
||||||
|
"%d ", pwr->pwrlevels[index].gpu_freq / 1000000);
|
||||||
|
/* One space for trailing null and another for the newline */
|
||||||
|
if (num_chars >= PAGE_SIZE - 2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[num_chars++] = '\n';
|
||||||
|
|
||||||
|
return num_chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t kgsl_pwrctrl_temp_show(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct kgsl_device *device = kgsl_device_from_dev(dev);
|
||||||
|
struct kgsl_pwrctrl *pwr;
|
||||||
|
int ret, id = 0, temperature = 0;
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
pwr = &device->pwrctrl;
|
||||||
|
|
||||||
|
if (!pwr->tsens_name)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
id = sensor_get_id((char *)pwr->tsens_name);
|
||||||
|
if (id < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
ret = sensor_get_temp(id, &temperature);
|
||||||
|
if (ret)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||||
|
temperature);
|
||||||
|
done:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show,
|
static DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show,
|
||||||
kgsl_pwrctrl_gpuclk_store);
|
kgsl_pwrctrl_gpuclk_store);
|
||||||
static DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show,
|
static DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show,
|
||||||
|
@ -1222,6 +1438,17 @@ static DEVICE_ATTR(popp, 0644, kgsl_popp_show, kgsl_popp_store);
|
||||||
static DEVICE_ATTR(force_no_nap, 0644,
|
static DEVICE_ATTR(force_no_nap, 0644,
|
||||||
kgsl_pwrctrl_force_no_nap_show,
|
kgsl_pwrctrl_force_no_nap_show,
|
||||||
kgsl_pwrctrl_force_no_nap_store);
|
kgsl_pwrctrl_force_no_nap_store);
|
||||||
|
static DEVICE_ATTR(gpu_model, 0444, kgsl_pwrctrl_gpu_model_show, NULL);
|
||||||
|
static DEVICE_ATTR(gpu_busy_percentage, 0444,
|
||||||
|
kgsl_pwrctrl_gpu_busy_percentage_show, NULL);
|
||||||
|
static DEVICE_ATTR(min_clock_mhz, 0644, kgsl_pwrctrl_min_clock_mhz_show,
|
||||||
|
kgsl_pwrctrl_min_clock_mhz_store);
|
||||||
|
static DEVICE_ATTR(max_clock_mhz, 0644, kgsl_pwrctrl_max_clock_mhz_show,
|
||||||
|
kgsl_pwrctrl_max_clock_mhz_store);
|
||||||
|
static DEVICE_ATTR(clock_mhz, 0444, kgsl_pwrctrl_clock_mhz_show, NULL);
|
||||||
|
static DEVICE_ATTR(freq_table_mhz, 0444,
|
||||||
|
kgsl_pwrctrl_freq_table_mhz_show, NULL);
|
||||||
|
static DEVICE_ATTR(temp, 0444, kgsl_pwrctrl_temp_show, NULL);
|
||||||
|
|
||||||
static const struct device_attribute *pwrctrl_attr_list[] = {
|
static const struct device_attribute *pwrctrl_attr_list[] = {
|
||||||
&dev_attr_gpuclk,
|
&dev_attr_gpuclk,
|
||||||
|
@ -1243,12 +1470,50 @@ static const struct device_attribute *pwrctrl_attr_list[] = {
|
||||||
&dev_attr_bus_split,
|
&dev_attr_bus_split,
|
||||||
&dev_attr_default_pwrlevel,
|
&dev_attr_default_pwrlevel,
|
||||||
&dev_attr_popp,
|
&dev_attr_popp,
|
||||||
|
&dev_attr_gpu_model,
|
||||||
|
&dev_attr_gpu_busy_percentage,
|
||||||
|
&dev_attr_min_clock_mhz,
|
||||||
|
&dev_attr_max_clock_mhz,
|
||||||
|
&dev_attr_clock_mhz,
|
||||||
|
&dev_attr_freq_table_mhz,
|
||||||
|
&dev_attr_temp,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sysfs_link {
|
||||||
|
const char *src;
|
||||||
|
const char *dst;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sysfs_link link_names[] = {
|
||||||
|
{ "gpu_model", "gpu_model",},
|
||||||
|
{ "gpu_busy_percentage", "gpu_busy",},
|
||||||
|
{ "min_clock_mhz", "gpu_min_clock",},
|
||||||
|
{ "max_clock_mhz", "gpu_max_clock",},
|
||||||
|
{ "clock_mhz", "gpu_clock",},
|
||||||
|
{ "freq_table_mhz", "gpu_freq_table",},
|
||||||
|
{ "temp", "gpu_tmu",},
|
||||||
|
};
|
||||||
|
|
||||||
int kgsl_pwrctrl_init_sysfs(struct kgsl_device *device)
|
int kgsl_pwrctrl_init_sysfs(struct kgsl_device *device)
|
||||||
{
|
{
|
||||||
return kgsl_create_device_sysfs_files(device->dev, pwrctrl_attr_list);
|
int i, ret;
|
||||||
|
|
||||||
|
ret = kgsl_create_device_sysfs_files(device->dev, pwrctrl_attr_list);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
device->gpu_sysfs_kobj = kobject_create_and_add("gpu", kernel_kobj);
|
||||||
|
if (IS_ERR_OR_NULL(device->gpu_sysfs_kobj))
|
||||||
|
return (device->gpu_sysfs_kobj == NULL) ?
|
||||||
|
-ENOMEM : PTR_ERR(device->gpu_sysfs_kobj);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(link_names); i++)
|
||||||
|
kgsl_gpu_sysfs_add_link(device->gpu_sysfs_kobj,
|
||||||
|
&device->dev->kobj, link_names[i].src,
|
||||||
|
link_names[i].dst);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device)
|
void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device)
|
||||||
|
@ -1860,6 +2125,10 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
|
||||||
|
|
||||||
kgsl_pwrctrl_vbif_init();
|
kgsl_pwrctrl_vbif_init();
|
||||||
|
|
||||||
|
/* temperature sensor name */
|
||||||
|
of_property_read_string(pdev->dev.of_node, "qcom,tsens-name",
|
||||||
|
&pwr->tsens_name);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,7 @@ struct kgsl_regulator {
|
||||||
* @sysfs_pwr_limit - pointer to the sysfs limits node
|
* @sysfs_pwr_limit - pointer to the sysfs limits node
|
||||||
* isense_clk_indx - index of isense clock, 0 if no isense
|
* isense_clk_indx - index of isense clock, 0 if no isense
|
||||||
* isense_clk_on_level - isense clock rate is XO rate below this level.
|
* isense_clk_on_level - isense clock rate is XO rate below this level.
|
||||||
|
* tsens_name - pointer to temperature sensor name of GPU temperature sensor
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct kgsl_pwrctrl {
|
struct kgsl_pwrctrl {
|
||||||
|
@ -204,6 +205,7 @@ struct kgsl_pwrctrl {
|
||||||
struct kgsl_pwr_limit *sysfs_pwr_limit;
|
struct kgsl_pwr_limit *sysfs_pwr_limit;
|
||||||
unsigned int gpu_bimc_int_clk_freq;
|
unsigned int gpu_bimc_int_clk_freq;
|
||||||
bool gpu_bimc_interface_enabled;
|
bool gpu_bimc_interface_enabled;
|
||||||
|
const char *tsens_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
int kgsl_pwrctrl_init(struct kgsl_device *device);
|
int kgsl_pwrctrl_init(struct kgsl_device *device);
|
||||||
|
|
|
@ -910,6 +910,14 @@ int kgsl_pwrscale_init(struct device *dev, const char *governor)
|
||||||
pwrscale->history[i].type = i;
|
pwrscale->history[i].type = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add links to the devfreq sysfs nodes */
|
||||||
|
kgsl_gpu_sysfs_add_link(device->gpu_sysfs_kobj,
|
||||||
|
&pwrscale->devfreqptr->dev.kobj, "governor",
|
||||||
|
"gpu_governor");
|
||||||
|
kgsl_gpu_sysfs_add_link(device->gpu_sysfs_kobj,
|
||||||
|
&pwrscale->devfreqptr->dev.kobj,
|
||||||
|
"available_governors", "gpu_available_governor");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kgsl_pwrscale_init);
|
EXPORT_SYMBOL(kgsl_pwrscale_init);
|
||||||
|
|
Loading…
Add table
Reference in a new issue