1bab09acc9
This enables BLCG optimization for kepler1. When using clockgating, nvidia's firmware has a set of registers which are initially programmed by the vbios with various engine delays and other mysterious settings that are safe enough to bring up the GPU. However, the values used by the vbios are more power hungry then they need to be, so the nvidia driver writes it's own more optimized set of BLCG settings before enabling CG_CTRL. This adds support for programming the optimized BLCG values during engine/subdev init, which enables rather significant power savings. This introduces the nvkm_therm_clkgate_init() helper, which we use to program the optimized BLCG settings before enabling clockgating with nvkm_therm_clkgate_enable. As well, this commit shares a lot more code with Fermi since BLCG is mostly the same there as far as we can tell. In the future, it's likely we'll reformat the clkgate_packs for kepler1 so that they share a list of mmio packs with Fermi. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Martin Peres <martin.peres@free.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
120 lines
3.2 KiB
C
120 lines
3.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __NVKM_THERM_H__
|
|
#define __NVKM_THERM_H__
|
|
#include <core/subdev.h>
|
|
|
|
#include <subdev/bios.h>
|
|
#include <subdev/bios/therm.h>
|
|
#include <subdev/timer.h>
|
|
|
|
enum nvkm_therm_thrs_direction {
|
|
NVKM_THERM_THRS_FALLING = 0,
|
|
NVKM_THERM_THRS_RISING = 1
|
|
};
|
|
|
|
enum nvkm_therm_thrs_state {
|
|
NVKM_THERM_THRS_LOWER = 0,
|
|
NVKM_THERM_THRS_HIGHER = 1
|
|
};
|
|
|
|
enum nvkm_therm_thrs {
|
|
NVKM_THERM_THRS_FANBOOST = 0,
|
|
NVKM_THERM_THRS_DOWNCLOCK = 1,
|
|
NVKM_THERM_THRS_CRITICAL = 2,
|
|
NVKM_THERM_THRS_SHUTDOWN = 3,
|
|
NVKM_THERM_THRS_NR
|
|
};
|
|
|
|
enum nvkm_therm_fan_mode {
|
|
NVKM_THERM_CTRL_NONE = 0,
|
|
NVKM_THERM_CTRL_MANUAL = 1,
|
|
NVKM_THERM_CTRL_AUTO = 2,
|
|
};
|
|
|
|
enum nvkm_therm_attr_type {
|
|
NVKM_THERM_ATTR_FAN_MIN_DUTY = 0,
|
|
NVKM_THERM_ATTR_FAN_MAX_DUTY = 1,
|
|
NVKM_THERM_ATTR_FAN_MODE = 2,
|
|
|
|
NVKM_THERM_ATTR_THRS_FAN_BOOST = 10,
|
|
NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST = 11,
|
|
NVKM_THERM_ATTR_THRS_DOWN_CLK = 12,
|
|
NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST = 13,
|
|
NVKM_THERM_ATTR_THRS_CRITICAL = 14,
|
|
NVKM_THERM_ATTR_THRS_CRITICAL_HYST = 15,
|
|
NVKM_THERM_ATTR_THRS_SHUTDOWN = 16,
|
|
NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST = 17,
|
|
};
|
|
|
|
struct nvkm_therm_clkgate_init {
|
|
u32 addr;
|
|
u8 count;
|
|
u32 data;
|
|
};
|
|
|
|
struct nvkm_therm_clkgate_pack {
|
|
const struct nvkm_therm_clkgate_init *init;
|
|
};
|
|
|
|
struct nvkm_therm {
|
|
const struct nvkm_therm_func *func;
|
|
struct nvkm_subdev subdev;
|
|
|
|
/* automatic thermal management */
|
|
struct nvkm_alarm alarm;
|
|
spinlock_t lock;
|
|
struct nvbios_therm_trip_point *last_trip;
|
|
int mode;
|
|
int cstate;
|
|
int suspend;
|
|
|
|
/* bios */
|
|
struct nvbios_therm_sensor bios_sensor;
|
|
|
|
/* fan priv */
|
|
struct nvkm_fan *fan;
|
|
|
|
/* alarms priv */
|
|
struct {
|
|
spinlock_t alarm_program_lock;
|
|
struct nvkm_alarm therm_poll_alarm;
|
|
enum nvkm_therm_thrs_state alarm_state[NVKM_THERM_THRS_NR];
|
|
} sensor;
|
|
|
|
/* what should be done if the card overheats */
|
|
struct {
|
|
void (*downclock)(struct nvkm_therm *, bool active);
|
|
void (*pause)(struct nvkm_therm *, bool active);
|
|
} emergency;
|
|
|
|
/* ic */
|
|
struct i2c_client *ic;
|
|
|
|
int (*fan_get)(struct nvkm_therm *);
|
|
int (*fan_set)(struct nvkm_therm *, int);
|
|
|
|
int (*attr_get)(struct nvkm_therm *, enum nvkm_therm_attr_type);
|
|
int (*attr_set)(struct nvkm_therm *, enum nvkm_therm_attr_type, int);
|
|
|
|
bool clkgating_enabled;
|
|
};
|
|
|
|
int nvkm_therm_temp_get(struct nvkm_therm *);
|
|
int nvkm_therm_fan_sense(struct nvkm_therm *);
|
|
int nvkm_therm_cstate(struct nvkm_therm *, int, int);
|
|
void nvkm_therm_clkgate_init(struct nvkm_therm *,
|
|
const struct nvkm_therm_clkgate_pack *);
|
|
void nvkm_therm_clkgate_enable(struct nvkm_therm *);
|
|
void nvkm_therm_clkgate_fini(struct nvkm_therm *, bool);
|
|
|
|
int nv40_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
|
|
int nv50_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
|
|
int g84_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
|
|
int gt215_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
|
|
int gf119_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
|
|
int gk104_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
|
|
int gm107_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
|
|
int gm200_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
|
|
int gp100_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
|
|
#endif
|