thermal: tegra: add support for gpu hw-throttle
Add support to trigger pulse skippers on the GPU when a HOT trip point is triggered. The pulse skippers can be signalled to throttle at low, medium and high depths\levels. Signed-off-by: Wei Ni <wni@nvidia.com> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
This commit is contained in:
parent
7d8ac6b282
commit
6ca29b7e82
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2014 - 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Author:
|
||||
* Mikko Perttunen <mperttunen@nvidia.com>
|
||||
|
@ -160,6 +161,15 @@
|
|||
/* get dividend from the depth */
|
||||
#define THROT_DEPTH_DIVIDEND(depth) ((256 * (100 - (depth)) / 100) - 1)
|
||||
|
||||
/* gk20a nv_therm interface N:3 Mapping. Levels defined in tegra124-sochterm.h
|
||||
* level vector
|
||||
* NONE 3'b000
|
||||
* LOW 3'b001
|
||||
* MED 3'b011
|
||||
* HIGH 3'b111
|
||||
*/
|
||||
#define THROT_LEVEL_TO_DEPTH(level) ((0x1 << (level)) - 1)
|
||||
|
||||
/* get THROT_PSKIP_xxx offset per LIGHT/HEAVY throt and CPU/GPU dev */
|
||||
#define THROT_OFFSET 0x30
|
||||
#define THROT_PSKIP_CTRL(throt, dev) (THROT_PSKIP_CTRL_LITE_CPU + \
|
||||
|
@ -219,6 +229,7 @@ struct soctherm_throt_cfg {
|
|||
u8 priority;
|
||||
u8 cpu_throt_level;
|
||||
u32 cpu_throt_depth;
|
||||
u32 gpu_throt_level;
|
||||
struct thermal_cooling_device *cdev;
|
||||
bool init;
|
||||
};
|
||||
|
@ -996,6 +1007,50 @@ static int soctherm_thermtrips_parse(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int soctherm_throt_cfg_parse(struct device *dev,
|
||||
struct device_node *np,
|
||||
struct soctherm_throt_cfg *stc)
|
||||
{
|
||||
struct tegra_soctherm *ts = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
ret = of_property_read_u32(np, "nvidia,priority", &val);
|
||||
if (ret) {
|
||||
dev_err(dev, "throttle-cfg: %s: invalid priority\n", stc->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
stc->priority = val;
|
||||
|
||||
ret = of_property_read_u32(np, ts->soc->use_ccroc ?
|
||||
"nvidia,cpu-throt-level" :
|
||||
"nvidia,cpu-throt-percent", &val);
|
||||
if (!ret) {
|
||||
if (ts->soc->use_ccroc &&
|
||||
val <= TEGRA_SOCTHERM_THROT_LEVEL_HIGH)
|
||||
stc->cpu_throt_level = val;
|
||||
else if (!ts->soc->use_ccroc && val <= 100)
|
||||
stc->cpu_throt_depth = val;
|
||||
else
|
||||
goto err;
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "nvidia,gpu-throt-level", &val);
|
||||
if (!ret && val <= TEGRA_SOCTHERM_THROT_LEVEL_HIGH)
|
||||
stc->gpu_throt_level = val;
|
||||
else
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev_err(dev, "throttle-cfg: %s: no throt prop or invalid prop\n",
|
||||
stc->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* soctherm_init_hw_throt_cdev() - Parse the HW throttle configurations
|
||||
* and register them as cooling devices.
|
||||
|
@ -1006,8 +1061,7 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
|
|||
struct tegra_soctherm *ts = dev_get_drvdata(dev);
|
||||
struct device_node *np_stc, *np_stcc;
|
||||
const char *name;
|
||||
u32 val;
|
||||
int i, r;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < THROTTLE_SIZE; i++) {
|
||||
ts->throt_cfgs[i].name = throt_names[i];
|
||||
|
@ -1025,6 +1079,7 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
|
|||
for_each_child_of_node(np_stc, np_stcc) {
|
||||
struct soctherm_throt_cfg *stc;
|
||||
struct thermal_cooling_device *tcd;
|
||||
int err;
|
||||
|
||||
name = np_stcc->name;
|
||||
stc = find_throttle_cfg_by_name(ts, name);
|
||||
|
@ -1034,37 +1089,10 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
|
|||
continue;
|
||||
}
|
||||
|
||||
r = of_property_read_u32(np_stcc, "nvidia,priority", &val);
|
||||
if (r) {
|
||||
dev_info(dev,
|
||||
"throttle-cfg: %s: missing priority\n", name);
|
||||
continue;
|
||||
}
|
||||
stc->priority = val;
|
||||
|
||||
if (ts->soc->use_ccroc) {
|
||||
r = of_property_read_u32(np_stcc,
|
||||
"nvidia,cpu-throt-level",
|
||||
&val);
|
||||
if (r) {
|
||||
dev_info(dev,
|
||||
"throttle-cfg: %s: missing cpu-throt-level\n",
|
||||
name);
|
||||
continue;
|
||||
}
|
||||
stc->cpu_throt_level = val;
|
||||
} else {
|
||||
r = of_property_read_u32(np_stcc,
|
||||
"nvidia,cpu-throt-percent",
|
||||
&val);
|
||||
if (r) {
|
||||
dev_info(dev,
|
||||
"throttle-cfg: %s: missing cpu-throt-percent\n",
|
||||
name);
|
||||
continue;
|
||||
}
|
||||
stc->cpu_throt_depth = val;
|
||||
}
|
||||
err = soctherm_throt_cfg_parse(dev, np_stcc, stc);
|
||||
if (err)
|
||||
continue;
|
||||
|
||||
tcd = thermal_of_cooling_device_register(np_stcc,
|
||||
(char *)name, ts,
|
||||
|
@ -1207,6 +1235,28 @@ static void throttlectl_cpu_mn(struct tegra_soctherm *ts,
|
|||
writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
|
||||
}
|
||||
|
||||
/**
|
||||
* throttlectl_gpu_level_select() - selects throttling level for GPU
|
||||
* @throt: the LIGHT/HEAVY of throttle event id
|
||||
*
|
||||
* This function programs soctherm's interface to GK20a NV_THERM to select
|
||||
* pre-configured "Low", "Medium" or "Heavy" throttle levels.
|
||||
*
|
||||
* Return: boolean true if HW was programmed
|
||||
*/
|
||||
static void throttlectl_gpu_level_select(struct tegra_soctherm *ts,
|
||||
enum soctherm_throttle_id throt)
|
||||
{
|
||||
u32 r, level, throt_vect;
|
||||
|
||||
level = ts->throt_cfgs[throt].gpu_throt_level;
|
||||
throt_vect = THROT_LEVEL_TO_DEPTH(level);
|
||||
r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU));
|
||||
r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);
|
||||
r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT_GPU_MASK, throt_vect);
|
||||
writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU));
|
||||
}
|
||||
|
||||
/**
|
||||
* soctherm_throttle_program() - programs pulse skippers' configuration
|
||||
* @throt: the LIGHT/HEAVY of the throttle event id.
|
||||
|
@ -1229,6 +1279,8 @@ static void soctherm_throttle_program(struct tegra_soctherm *ts,
|
|||
else
|
||||
throttlectl_cpu_mn(ts, throt);
|
||||
|
||||
throttlectl_gpu_level_select(ts, throt);
|
||||
|
||||
r = REG_SET_MASK(0, THROT_PRIORITY_LITE_PRIO_MASK, stc.priority);
|
||||
writel(r, ts->regs + THROT_PRIORITY_CTRL(throt));
|
||||
|
||||
|
|
Loading…
Reference in New Issue