aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/therm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/therm')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c305
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c117
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/fannil.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c67
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c80
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/g84.c190
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf110.c174
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c153
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/gm107.c66
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c85
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c51
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c129
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv50.c106
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h86
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c122
16 files changed, 790 insertions, 946 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild
index 5837cf1292d9..135758ba3e28 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild
@@ -9,5 +9,5 @@ nvkm-y += nvkm/subdev/therm/nv40.o
nvkm-y += nvkm/subdev/therm/nv50.o
nvkm-y += nvkm/subdev/therm/g84.o
nvkm-y += nvkm/subdev/therm/gt215.o
-nvkm-y += nvkm/subdev/therm/gf110.o
+nvkm-y += nvkm/subdev/therm/gf119.o
nvkm-y += nvkm/subdev/therm/gm107.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
index ec327cb64a0d..949dc6101a58 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
@@ -23,21 +23,26 @@
*/
#include "priv.h"
-#include <core/device.h>
+int
+nvkm_therm_temp_get(struct nvkm_therm *therm)
+{
+ if (therm->func->temp_get)
+ return therm->func->temp_get(therm);
+ return -ENODEV;
+}
static int
nvkm_therm_update_trip(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvbios_therm_trip_point *trip = priv->fan->bios.trip,
+ struct nvbios_therm_trip_point *trip = therm->fan->bios.trip,
*cur_trip = NULL,
- *last_trip = priv->last_trip;
- u8 temp = therm->temp_get(therm);
+ *last_trip = therm->last_trip;
+ u8 temp = therm->func->temp_get(therm);
u16 duty, i;
/* look for the trip point corresponding to the current temperature */
cur_trip = NULL;
- for (i = 0; i < priv->fan->bios.nr_fan_trip; i++) {
+ for (i = 0; i < therm->fan->bios.nr_fan_trip; i++) {
if (temp >= trip[i].temp)
cur_trip = &trip[i];
}
@@ -49,10 +54,10 @@ nvkm_therm_update_trip(struct nvkm_therm *therm)
if (cur_trip) {
duty = cur_trip->fan_duty;
- priv->last_trip = cur_trip;
+ therm->last_trip = cur_trip;
} else {
duty = 0;
- priv->last_trip = NULL;
+ therm->last_trip = NULL;
}
return duty;
@@ -61,51 +66,50 @@ nvkm_therm_update_trip(struct nvkm_therm *therm)
static int
nvkm_therm_update_linear(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- u8 linear_min_temp = priv->fan->bios.linear_min_temp;
- u8 linear_max_temp = priv->fan->bios.linear_max_temp;
- u8 temp = therm->temp_get(therm);
+ u8 linear_min_temp = therm->fan->bios.linear_min_temp;
+ u8 linear_max_temp = therm->fan->bios.linear_max_temp;
+ u8 temp = therm->func->temp_get(therm);
u16 duty;
/* handle the non-linear part first */
if (temp < linear_min_temp)
- return priv->fan->bios.min_duty;
+ return therm->fan->bios.min_duty;
else if (temp > linear_max_temp)
- return priv->fan->bios.max_duty;
+ return therm->fan->bios.max_duty;
/* we are in the linear zone */
duty = (temp - linear_min_temp);
- duty *= (priv->fan->bios.max_duty - priv->fan->bios.min_duty);
+ duty *= (therm->fan->bios.max_duty - therm->fan->bios.min_duty);
duty /= (linear_max_temp - linear_min_temp);
- duty += priv->fan->bios.min_duty;
+ duty += therm->fan->bios.min_duty;
return duty;
}
static void
nvkm_therm_update(struct nvkm_therm *therm, int mode)
{
- struct nvkm_timer *ptimer = nvkm_timer(therm);
- struct nvkm_therm_priv *priv = (void *)therm;
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_timer *tmr = subdev->device->timer;
unsigned long flags;
bool immd = true;
bool poll = true;
int duty = -1;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&therm->lock, flags);
if (mode < 0)
- mode = priv->mode;
- priv->mode = mode;
+ mode = therm->mode;
+ therm->mode = mode;
switch (mode) {
case NVKM_THERM_CTRL_MANUAL:
- ptimer->alarm_cancel(ptimer, &priv->alarm);
+ nvkm_timer_alarm_cancel(tmr, &therm->alarm);
duty = nvkm_therm_fan_get(therm);
if (duty < 0)
duty = 100;
poll = false;
break;
case NVKM_THERM_CTRL_AUTO:
- switch(priv->fan->bios.fan_mode) {
+ switch(therm->fan->bios.fan_mode) {
case NVBIOS_THERM_FAN_TRIP:
duty = nvkm_therm_update_trip(therm);
break;
@@ -113,8 +117,8 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode)
duty = nvkm_therm_update_linear(therm);
break;
case NVBIOS_THERM_FAN_OTHER:
- if (priv->cstate)
- duty = priv->cstate;
+ if (therm->cstate)
+ duty = therm->cstate;
poll = false;
break;
}
@@ -122,29 +126,29 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode)
break;
case NVKM_THERM_CTRL_NONE:
default:
- ptimer->alarm_cancel(ptimer, &priv->alarm);
+ nvkm_timer_alarm_cancel(tmr, &therm->alarm);
poll = false;
}
- if (list_empty(&priv->alarm.head) && poll)
- ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm);
- spin_unlock_irqrestore(&priv->lock, flags);
+ if (list_empty(&therm->alarm.head) && poll)
+ nvkm_timer_alarm(tmr, 1000000000ULL, &therm->alarm);
+ spin_unlock_irqrestore(&therm->lock, flags);
if (duty >= 0) {
- nv_debug(therm, "FAN target request: %d%%\n", duty);
+ nvkm_debug(subdev, "FAN target request: %d%%\n", duty);
nvkm_therm_fan_set(therm, immd, duty);
}
}
int
-nvkm_therm_cstate(struct nvkm_therm *ptherm, int fan, int dir)
+nvkm_therm_cstate(struct nvkm_therm *therm, int fan, int dir)
{
- struct nvkm_therm_priv *priv = (void *)ptherm;
- if (!dir || (dir < 0 && fan < priv->cstate) ||
- (dir > 0 && fan > priv->cstate)) {
- nv_debug(ptherm, "default fan speed -> %d%%\n", fan);
- priv->cstate = fan;
- nvkm_therm_update(ptherm, -1);
+ struct nvkm_subdev *subdev = &therm->subdev;
+ if (!dir || (dir < 0 && fan < therm->cstate) ||
+ (dir > 0 && fan > therm->cstate)) {
+ nvkm_debug(subdev, "default fan speed -> %d%%\n", fan);
+ therm->cstate = fan;
+ nvkm_therm_update(therm, -1);
}
return 0;
}
@@ -152,16 +156,16 @@ nvkm_therm_cstate(struct nvkm_therm *ptherm, int fan, int dir)
static void
nvkm_therm_alarm(struct nvkm_alarm *alarm)
{
- struct nvkm_therm_priv *priv =
- container_of(alarm, struct nvkm_therm_priv, alarm);
- nvkm_therm_update(&priv->base, -1);
+ struct nvkm_therm *therm =
+ container_of(alarm, struct nvkm_therm, alarm);
+ nvkm_therm_update(therm, -1);
}
int
nvkm_therm_fan_mode(struct nvkm_therm *therm, int mode)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvkm_device *device = nv_device(therm);
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_device *device = subdev->device;
static const char *name[] = {
"disabled",
"manual",
@@ -171,51 +175,49 @@ nvkm_therm_fan_mode(struct nvkm_therm *therm, int mode)
/* The default PPWR ucode on fermi interferes with fan management */
if ((mode >= ARRAY_SIZE(name)) ||
(mode != NVKM_THERM_CTRL_NONE && device->card_type >= NV_C0 &&
- !nvkm_subdev(device, NVDEV_SUBDEV_PMU)))
+ !device->pmu))
return -EINVAL;
/* do not allow automatic fan management if the thermal sensor is
* not available */
- if (mode == NVKM_THERM_CTRL_AUTO && therm->temp_get(therm) < 0)
+ if (mode == NVKM_THERM_CTRL_AUTO &&
+ therm->func->temp_get(therm) < 0)
return -EINVAL;
- if (priv->mode == mode)
+ if (therm->mode == mode)
return 0;
- nv_info(therm, "fan management: %s\n", name[mode]);
+ nvkm_debug(subdev, "fan management: %s\n", name[mode]);
nvkm_therm_update(therm, mode);
return 0;
}
int
-nvkm_therm_attr_get(struct nvkm_therm *therm,
- enum nvkm_therm_attr_type type)
+nvkm_therm_attr_get(struct nvkm_therm *therm, enum nvkm_therm_attr_type type)
{
- struct nvkm_therm_priv *priv = (void *)therm;
-
switch (type) {
case NVKM_THERM_ATTR_FAN_MIN_DUTY:
- return priv->fan->bios.min_duty;
+ return therm->fan->bios.min_duty;
case NVKM_THERM_ATTR_FAN_MAX_DUTY:
- return priv->fan->bios.max_duty;
+ return therm->fan->bios.max_duty;
case NVKM_THERM_ATTR_FAN_MODE:
- return priv->mode;
+ return therm->mode;
case NVKM_THERM_ATTR_THRS_FAN_BOOST:
- return priv->bios_sensor.thrs_fan_boost.temp;
+ return therm->bios_sensor.thrs_fan_boost.temp;
case NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST:
- return priv->bios_sensor.thrs_fan_boost.hysteresis;
+ return therm->bios_sensor.thrs_fan_boost.hysteresis;
case NVKM_THERM_ATTR_THRS_DOWN_CLK:
- return priv->bios_sensor.thrs_down_clock.temp;
+ return therm->bios_sensor.thrs_down_clock.temp;
case NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST:
- return priv->bios_sensor.thrs_down_clock.hysteresis;
+ return therm->bios_sensor.thrs_down_clock.hysteresis;
case NVKM_THERM_ATTR_THRS_CRITICAL:
- return priv->bios_sensor.thrs_critical.temp;
+ return therm->bios_sensor.thrs_critical.temp;
case NVKM_THERM_ATTR_THRS_CRITICAL_HYST:
- return priv->bios_sensor.thrs_critical.hysteresis;
+ return therm->bios_sensor.thrs_critical.hysteresis;
case NVKM_THERM_ATTR_THRS_SHUTDOWN:
- return priv->bios_sensor.thrs_shutdown.temp;
+ return therm->bios_sensor.thrs_shutdown.temp;
case NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST:
- return priv->bios_sensor.thrs_shutdown.hysteresis;
+ return therm->bios_sensor.thrs_shutdown.hysteresis;
}
return -EINVAL;
@@ -225,143 +227,156 @@ int
nvkm_therm_attr_set(struct nvkm_therm *therm,
enum nvkm_therm_attr_type type, int value)
{
- struct nvkm_therm_priv *priv = (void *)therm;
-
switch (type) {
case NVKM_THERM_ATTR_FAN_MIN_DUTY:
if (value < 0)
value = 0;
- if (value > priv->fan->bios.max_duty)
- value = priv->fan->bios.max_duty;
- priv->fan->bios.min_duty = value;
+ if (value > therm->fan->bios.max_duty)
+ value = therm->fan->bios.max_duty;
+ therm->fan->bios.min_duty = value;
return 0;
case NVKM_THERM_ATTR_FAN_MAX_DUTY:
if (value < 0)
value = 0;
- if (value < priv->fan->bios.min_duty)
- value = priv->fan->bios.min_duty;
- priv->fan->bios.max_duty = value;
+ if (value < therm->fan->bios.min_duty)
+ value = therm->fan->bios.min_duty;
+ therm->fan->bios.max_duty = value;
return 0;
case NVKM_THERM_ATTR_FAN_MODE:
return nvkm_therm_fan_mode(therm, value);
case NVKM_THERM_ATTR_THRS_FAN_BOOST:
- priv->bios_sensor.thrs_fan_boost.temp = value;
- priv->sensor.program_alarms(therm);
+ therm->bios_sensor.thrs_fan_boost.temp = value;
+ therm->func->program_alarms(therm);
return 0;
case NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST:
- priv->bios_sensor.thrs_fan_boost.hysteresis = value;
- priv->sensor.program_alarms(therm);
+ therm->bios_sensor.thrs_fan_boost.hysteresis = value;
+ therm->func->program_alarms(therm);
return 0;
case NVKM_THERM_ATTR_THRS_DOWN_CLK:
- priv->bios_sensor.thrs_down_clock.temp = value;
- priv->sensor.program_alarms(therm);
+ therm->bios_sensor.thrs_down_clock.temp = value;
+ therm->func->program_alarms(therm);
return 0;
case NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST:
- priv->bios_sensor.thrs_down_clock.hysteresis = value;
- priv->sensor.program_alarms(therm);
+ therm->bios_sensor.thrs_down_clock.hysteresis = value;
+ therm->func->program_alarms(therm);
return 0;
case NVKM_THERM_ATTR_THRS_CRITICAL:
- priv->bios_sensor.thrs_critical.temp = value;
- priv->sensor.program_alarms(therm);
+ therm->bios_sensor.thrs_critical.temp = value;
+ therm->func->program_alarms(therm);
return 0;
case NVKM_THERM_ATTR_THRS_CRITICAL_HYST:
- priv->bios_sensor.thrs_critical.hysteresis = value;
- priv->sensor.program_alarms(therm);
+ therm->bios_sensor.thrs_critical.hysteresis = value;
+ therm->func->program_alarms(therm);
return 0;
case NVKM_THERM_ATTR_THRS_SHUTDOWN:
- priv->bios_sensor.thrs_shutdown.temp = value;
- priv->sensor.program_alarms(therm);
+ therm->bios_sensor.thrs_shutdown.temp = value;
+ therm->func->program_alarms(therm);
return 0;
case NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST:
- priv->bios_sensor.thrs_shutdown.hysteresis = value;
- priv->sensor.program_alarms(therm);
+ therm->bios_sensor.thrs_shutdown.hysteresis = value;
+ therm->func->program_alarms(therm);
return 0;
}
return -EINVAL;
}
-int
-_nvkm_therm_init(struct nvkm_object *object)
+static void
+nvkm_therm_intr(struct nvkm_subdev *subdev)
{
- struct nvkm_therm *therm = (void *)object;
- struct nvkm_therm_priv *priv = (void *)therm;
- int ret;
-
- ret = nvkm_subdev_init(&therm->base);
- if (ret)
- return ret;
-
- if (priv->suspend >= 0) {
- /* restore the pwm value only when on manual or auto mode */
- if (priv->suspend > 0)
- nvkm_therm_fan_set(therm, true, priv->fan->percent);
-
- nvkm_therm_fan_mode(therm, priv->suspend);
- }
- nvkm_therm_sensor_init(therm);
- nvkm_therm_fan_init(therm);
- return 0;
+ struct nvkm_therm *therm = nvkm_therm(subdev);
+ if (therm->func->intr)
+ therm->func->intr(therm);
}
-int
-_nvkm_therm_fini(struct nvkm_object *object, bool suspend)
+static int
+nvkm_therm_fini(struct nvkm_subdev *subdev, bool suspend)
{
- struct nvkm_therm *therm = (void *)object;
- struct nvkm_therm_priv *priv = (void *)therm;
+ struct nvkm_therm *therm = nvkm_therm(subdev);
+
+ if (therm->func->fini)
+ therm->func->fini(therm);
nvkm_therm_fan_fini(therm, suspend);
nvkm_therm_sensor_fini(therm, suspend);
+
if (suspend) {
- priv->suspend = priv->mode;
- priv->mode = NVKM_THERM_CTRL_NONE;
+ therm->suspend = therm->mode;
+ therm->mode = NVKM_THERM_CTRL_NONE;
}
- return nvkm_subdev_fini(&therm->base, suspend);
-}
-
-int
-nvkm_therm_create_(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, int length, void **pobject)
-{
- struct nvkm_therm_priv *priv;
- int ret;
-
- ret = nvkm_subdev_create_(parent, engine, oclass, 0, "PTHERM",
- "therm", length, pobject);
- priv = *pobject;
- if (ret)
- return ret;
-
- nvkm_alarm_init(&priv->alarm, nvkm_therm_alarm);
- spin_lock_init(&priv->lock);
- spin_lock_init(&priv->sensor.alarm_program_lock);
-
- priv->base.fan_get = nvkm_therm_fan_user_get;
- priv->base.fan_set = nvkm_therm_fan_user_set;
- priv->base.fan_sense = nvkm_therm_fan_sense;
- priv->base.attr_get = nvkm_therm_attr_get;
- priv->base.attr_set = nvkm_therm_attr_set;
- priv->mode = priv->suspend = -1; /* undefined */
return 0;
}
-int
-nvkm_therm_preinit(struct nvkm_therm *therm)
+static int
+nvkm_therm_oneinit(struct nvkm_subdev *subdev)
{
+ struct nvkm_therm *therm = nvkm_therm(subdev);
nvkm_therm_sensor_ctor(therm);
nvkm_therm_ic_ctor(therm);
nvkm_therm_fan_ctor(therm);
-
nvkm_therm_fan_mode(therm, NVKM_THERM_CTRL_AUTO);
nvkm_therm_sensor_preinit(therm);
return 0;
}
-void
-_nvkm_therm_dtor(struct nvkm_object *object)
+static int
+nvkm_therm_init(struct nvkm_subdev *subdev)
+{
+ struct nvkm_therm *therm = nvkm_therm(subdev);
+
+ therm->func->init(therm);
+
+ if (therm->suspend >= 0) {
+ /* restore the pwm value only when on manual or auto mode */
+ if (therm->suspend > 0)
+ nvkm_therm_fan_set(therm, true, therm->fan->percent);
+
+ nvkm_therm_fan_mode(therm, therm->suspend);
+ }
+
+ nvkm_therm_sensor_init(therm);
+ nvkm_therm_fan_init(therm);
+ return 0;
+}
+
+static void *
+nvkm_therm_dtor(struct nvkm_subdev *subdev)
+{
+ struct nvkm_therm *therm = nvkm_therm(subdev);
+ kfree(therm->fan);
+ return therm;
+}
+
+static const struct nvkm_subdev_func
+nvkm_therm = {
+ .dtor = nvkm_therm_dtor,
+ .oneinit = nvkm_therm_oneinit,
+ .init = nvkm_therm_init,
+ .fini = nvkm_therm_fini,
+ .intr = nvkm_therm_intr,
+};
+
+int
+nvkm_therm_new_(const struct nvkm_therm_func *func, struct nvkm_device *device,
+ int index, struct nvkm_therm **ptherm)
{
- struct nvkm_therm_priv *priv = (void *)object;
- kfree(priv->fan);
- nvkm_subdev_destroy(&priv->base.base);
+ struct nvkm_therm *therm;
+
+ if (!(therm = *ptherm = kzalloc(sizeof(*therm), GFP_KERNEL)))
+ return -ENOMEM;
+
+ nvkm_subdev_ctor(&nvkm_therm, device, index, 0, &therm->subdev);
+ therm->func = func;
+
+ nvkm_alarm_init(&therm->alarm, nvkm_therm_alarm);
+ spin_lock_init(&therm->lock);
+ spin_lock_init(&therm->sensor.alarm_program_lock);
+
+ therm->fan_get = nvkm_therm_fan_user_get;
+ therm->fan_set = nvkm_therm_fan_user_set;
+ therm->attr_get = nvkm_therm_attr_get;
+ therm->attr_set = nvkm_therm_attr_set;
+ therm->mode = therm->suspend = -1; /* undefined */
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c
index 434fa745ca40..91198d79393a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c
@@ -32,8 +32,8 @@ static int
nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
{
struct nvkm_therm *therm = fan->parent;
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvkm_timer *ptimer = nvkm_timer(priv);
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_timer *tmr = subdev->device->timer;
unsigned long flags;
int ret = 0;
int duty;
@@ -45,7 +45,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
target = max_t(u8, target, fan->bios.min_duty);
target = min_t(u8, target, fan->bios.max_duty);
if (fan->percent != target) {
- nv_debug(therm, "FAN target: %d\n", target);
+ nvkm_debug(subdev, "FAN target: %d\n", target);
fan->percent = target;
}
@@ -70,7 +70,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
duty = target;
}
- nv_debug(therm, "FAN update: %d\n", duty);
+ nvkm_debug(subdev, "FAN update: %d\n", duty);
ret = fan->set(therm, duty);
if (ret) {
spin_unlock_irqrestore(&fan->lock, flags);
@@ -95,7 +95,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
else
delay = bump_period;
- ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm);
+ nvkm_timer_alarm(tmr, delay * 1000 * 1000, &fan->alarm);
}
return ret;
@@ -111,48 +111,51 @@ nvkm_fan_alarm(struct nvkm_alarm *alarm)
int
nvkm_therm_fan_get(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- return priv->fan->get(therm);
+ return therm->fan->get(therm);
}
int
nvkm_therm_fan_set(struct nvkm_therm *therm, bool immediate, int percent)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- return nvkm_fan_update(priv->fan, immediate, percent);
+ return nvkm_fan_update(therm->fan, immediate, percent);
}
int
nvkm_therm_fan_sense(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvkm_timer *ptimer = nvkm_timer(therm);
- struct nvkm_gpio *gpio = nvkm_gpio(therm);
+ struct nvkm_device *device = therm->subdev.device;
+ struct nvkm_timer *tmr = device->timer;
+ struct nvkm_gpio *gpio = device->gpio;
u32 cycles, cur, prev;
u64 start, end, tach;
- if (priv->fan->tach.func == DCB_GPIO_UNUSED)
+ if (therm->func->fan_sense)
+ return therm->func->fan_sense(therm);
+
+ if (therm->fan->tach.func == DCB_GPIO_UNUSED)
return -ENODEV;
/* Time a complete rotation and extrapolate to RPM:
* When the fan spins, it changes the value of GPIO FAN_SENSE.
* We get 4 changes (0 -> 1 -> 0 -> 1) per complete rotation.
*/
- start = ptimer->read(ptimer);
- prev = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line);
+ start = nvkm_timer_read(tmr);
+ prev = nvkm_gpio_get(gpio, 0, therm->fan->tach.func,
+ therm->fan->tach.line);
cycles = 0;
do {
usleep_range(500, 1000); /* supports 0 < rpm < 7500 */
- cur = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line);
+ cur = nvkm_gpio_get(gpio, 0, therm->fan->tach.func,
+ therm->fan->tach.line);
if (prev != cur) {
if (!start)
- start = ptimer->read(ptimer);
+ start = nvkm_timer_read(tmr);
cycles++;
prev = cur;
}
- } while (cycles < 5 && ptimer->read(ptimer) - start < 250000000);
- end = ptimer->read(ptimer);
+ } while (cycles < 5 && nvkm_timer_read(tmr) - start < 250000000);
+ end = nvkm_timer_read(tmr);
if (cycles == 5) {
tach = (u64)60000000000ULL;
@@ -171,9 +174,7 @@ nvkm_therm_fan_user_get(struct nvkm_therm *therm)
int
nvkm_therm_fan_user_set(struct nvkm_therm *therm, int percent)
{
- struct nvkm_therm_priv *priv = (void *)therm;
-
- if (priv->mode != NVKM_THERM_CTRL_MANUAL)
+ if (therm->mode != NVKM_THERM_CTRL_MANUAL)
return -EINVAL;
return nvkm_therm_fan_set(therm, true, percent);
@@ -182,29 +183,25 @@ nvkm_therm_fan_user_set(struct nvkm_therm *therm, int percent)
static void
nvkm_therm_fan_set_defaults(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
-
- priv->fan->bios.pwm_freq = 0;
- priv->fan->bios.min_duty = 0;
- priv->fan->bios.max_duty = 100;
- priv->fan->bios.bump_period = 500;
- priv->fan->bios.slow_down_period = 2000;
- priv->fan->bios.linear_min_temp = 40;
- priv->fan->bios.linear_max_temp = 85;
+ therm->fan->bios.pwm_freq = 0;
+ therm->fan->bios.min_duty = 0;
+ therm->fan->bios.max_duty = 100;
+ therm->fan->bios.bump_period = 500;
+ therm->fan->bios.slow_down_period = 2000;
+ therm->fan->bios.linear_min_temp = 40;
+ therm->fan->bios.linear_max_temp = 85;
}
static void
nvkm_therm_fan_safety_checks(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
+ if (therm->fan->bios.min_duty > 100)
+ therm->fan->bios.min_duty = 100;
+ if (therm->fan->bios.max_duty > 100)
+ therm->fan->bios.max_duty = 100;
- if (priv->fan->bios.min_duty > 100)
- priv->fan->bios.min_duty = 100;
- if (priv->fan->bios.max_duty > 100)
- priv->fan->bios.max_duty = 100;
-
- if (priv->fan->bios.min_duty > priv->fan->bios.max_duty)
- priv->fan->bios.min_duty = priv->fan->bios.max_duty;
+ if (therm->fan->bios.min_duty > therm->fan->bios.max_duty)
+ therm->fan->bios.min_duty = therm->fan->bios.max_duty;
}
int
@@ -216,29 +213,28 @@ nvkm_therm_fan_init(struct nvkm_therm *therm)
int
nvkm_therm_fan_fini(struct nvkm_therm *therm, bool suspend)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvkm_timer *ptimer = nvkm_timer(therm);
-
+ struct nvkm_timer *tmr = therm->subdev.device->timer;
if (suspend)
- ptimer->alarm_cancel(ptimer, &priv->fan->alarm);
+ nvkm_timer_alarm_cancel(tmr, &therm->fan->alarm);
return 0;
}
int
nvkm_therm_fan_ctor(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvkm_gpio *gpio = nvkm_gpio(therm);
- struct nvkm_bios *bios = nvkm_bios(therm);
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_device *device = subdev->device;
+ struct nvkm_gpio *gpio = device->gpio;
+ struct nvkm_bios *bios = device->bios;
struct dcb_gpio_func func;
int ret;
/* attempt to locate a drivable fan, and determine control method */
- ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
+ ret = nvkm_gpio_find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
if (ret == 0) {
/* FIXME: is this really the place to perform such checks ? */
if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) {
- nv_debug(therm, "GPIO_FAN is in input mode\n");
+ nvkm_debug(subdev, "GPIO_FAN is in input mode\n");
ret = -EINVAL;
} else {
ret = nvkm_fanpwm_create(therm, &func);
@@ -254,28 +250,29 @@ nvkm_therm_fan_ctor(struct nvkm_therm *therm)
return ret;
}
- nv_info(therm, "FAN control: %s\n", priv->fan->type);
+ nvkm_debug(subdev, "FAN control: %s\n", therm->fan->type);
/* read the current speed, it is useful when resuming */
- priv->fan->percent = nvkm_therm_fan_get(therm);
+ therm->fan->percent = nvkm_therm_fan_get(therm);
/* attempt to detect a tachometer connection */
- ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach);
+ ret = nvkm_gpio_find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff,
+ &therm->fan->tach);
if (ret)
- priv->fan->tach.func = DCB_GPIO_UNUSED;
+ therm->fan->tach.func = DCB_GPIO_UNUSED;
/* initialise fan bump/slow update handling */
- priv->fan->parent = therm;
- nvkm_alarm_init(&priv->fan->alarm, nvkm_fan_alarm);
- spin_lock_init(&priv->fan->lock);
+ therm->fan->parent = therm;
+ nvkm_alarm_init(&therm->fan->alarm, nvkm_fan_alarm);
+ spin_lock_init(&therm->fan->lock);
/* other random init... */
nvkm_therm_fan_set_defaults(therm);
- nvbios_perf_fan_parse(bios, &priv->fan->perf);
- if (!nvbios_fan_parse(bios, &priv->fan->bios)) {
- nv_debug(therm, "parsing the fan table failed\n");
- if (nvbios_therm_fan_parse(bios, &priv->fan->bios))
- nv_error(therm, "parsing both fan tables failed\n");
+ nvbios_perf_fan_parse(bios, &therm->fan->perf);
+ if (!nvbios_fan_parse(bios, &therm->fan->bios)) {
+ nvkm_debug(subdev, "parsing the fan table failed\n");
+ if (nvbios_therm_fan_parse(bios, &therm->fan->bios))
+ nvkm_error(subdev, "parsing both fan tables failed\n");
}
nvkm_therm_fan_safety_checks(therm);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fannil.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fannil.c
index 534e5970ec9c..8ae300f911b6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fannil.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fannil.c
@@ -38,11 +38,10 @@ nvkm_fannil_set(struct nvkm_therm *therm, int percent)
int
nvkm_fannil_create(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *tpriv = (void *)therm;
struct nvkm_fan *priv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- tpriv->fan = priv;
+ therm->fan = priv;
if (!priv)
return -ENOMEM;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c
index bde5ceaeb70a..340f37a299dc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c
@@ -24,13 +24,12 @@
*/
#include "priv.h"
-#include <core/device.h>
#include <core/option.h>
#include <subdev/bios.h>
#include <subdev/bios/fan.h>
#include <subdev/gpio.h>
-struct nvkm_fanpwm_priv {
+struct nvkm_fanpwm {
struct nvkm_fan base;
struct dcb_gpio_func func;
};
@@ -38,76 +37,74 @@ struct nvkm_fanpwm_priv {
static int
nvkm_fanpwm_get(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *tpriv = (void *)therm;
- struct nvkm_fanpwm_priv *priv = (void *)tpriv->fan;
- struct nvkm_gpio *gpio = nvkm_gpio(therm);
- int card_type = nv_device(therm)->card_type;
+ struct nvkm_fanpwm *fan = (void *)therm->fan;
+ struct nvkm_device *device = therm->subdev.device;
+ struct nvkm_gpio *gpio = device->gpio;
+ int card_type = device->card_type;
u32 divs, duty;
int ret;
- ret = therm->pwm_get(therm, priv->func.line, &divs, &duty);
+ ret = therm->func->pwm_get(therm, fan->func.line, &divs, &duty);
if (ret == 0 && divs) {
divs = max(divs, duty);
- if (card_type <= NV_40 || (priv->func.log[0] & 1))
+ if (card_type <= NV_40 || (fan->func.log[0] & 1))
duty = divs - duty;
return (duty * 100) / divs;
}
- return gpio->get(gpio, 0, priv->func.func, priv->func.line) * 100;
+ return nvkm_gpio_get(gpio, 0, fan->func.func, fan->func.line) * 100;
}
static int
nvkm_fanpwm_set(struct nvkm_therm *therm, int percent)
{
- struct nvkm_therm_priv *tpriv = (void *)therm;
- struct nvkm_fanpwm_priv *priv = (void *)tpriv->fan;
- int card_type = nv_device(therm)->card_type;
+ struct nvkm_fanpwm *fan = (void *)therm->fan;
+ int card_type = therm->subdev.device->card_type;
u32 divs, duty;
int ret;
- divs = priv->base.perf.pwm_divisor;
- if (priv->base.bios.pwm_freq) {
+ divs = fan->base.perf.pwm_divisor;
+ if (fan->base.bios.pwm_freq) {
divs = 1;
- if (therm->pwm_clock)
- divs = therm->pwm_clock(therm, priv->func.line);
- divs /= priv->base.bios.pwm_freq;
+ if (therm->func->pwm_clock)
+ divs = therm->func->pwm_clock(therm, fan->func.line);
+ divs /= fan->base.bios.pwm_freq;
}
duty = ((divs * percent) + 99) / 100;
- if (card_type <= NV_40 || (priv->func.log[0] & 1))
+ if (card_type <= NV_40 || (fan->func.log[0] & 1))
duty = divs - duty;
- ret = therm->pwm_set(therm, priv->func.line, divs, duty);
+ ret = therm->func->pwm_set(therm, fan->func.line, divs, duty);
if (ret == 0)
- ret = therm->pwm_ctrl(therm, priv->func.line, true);
+ ret = therm->func->pwm_ctrl(therm, fan->func.line, true);
return ret;
}
int
nvkm_fanpwm_create(struct nvkm_therm *therm, struct dcb_gpio_func *func)
{
- struct nvkm_device *device = nv_device(therm);
- struct nvkm_therm_priv *tpriv = (void *)therm;
- struct nvkm_bios *bios = nvkm_bios(therm);
- struct nvkm_fanpwm_priv *priv;
- struct nvbios_therm_fan fan;
+ struct nvkm_device *device = therm->subdev.device;
+ struct nvkm_bios *bios = device->bios;
+ struct nvkm_fanpwm *fan;
+ struct nvbios_therm_fan info = {};
u32 divs, duty;
- nvbios_fan_parse(bios, &fan);
+ nvbios_fan_parse(bios, &info);
if (!nvkm_boolopt(device->cfgopt, "NvFanPWM", func->param) ||
- !therm->pwm_ctrl || fan.type == NVBIOS_THERM_FAN_TOGGLE ||
- therm->pwm_get(therm, func->line, &divs, &duty) == -ENODEV)
+ !therm->func->pwm_ctrl || info.type == NVBIOS_THERM_FAN_TOGGLE ||
+ therm->func->pwm_get(therm, func->line, &divs, &duty) == -ENODEV)
return -ENODEV;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- tpriv->fan = &priv->base;
- if (!priv)
+ fan = kzalloc(sizeof(*fan), GFP_KERNEL);
+ therm->fan = &fan->base;
+ if (!fan)
return -ENOMEM;
- priv->base.type = "PWM";
- priv->base.get = nvkm_fanpwm_get;
- priv->base.set = nvkm_fanpwm_set;
- priv->func = *func;
+ fan->base.type = "PWM";
+ fan->base.get = nvkm_fanpwm_get;
+ fan->base.set = nvkm_fanpwm_set;
+ fan->func = *func;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c
index 4ce041e81371..59701b7a6597 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c
@@ -26,7 +26,7 @@
#include <subdev/gpio.h>
#include <subdev/timer.h>
-struct nvkm_fantog_priv {
+struct nvkm_fantog {
struct nvkm_fan base;
struct nvkm_alarm alarm;
spinlock_t lock;
@@ -36,83 +36,81 @@ struct nvkm_fantog_priv {
};
static void
-nvkm_fantog_update(struct nvkm_fantog_priv *priv, int percent)
+nvkm_fantog_update(struct nvkm_fantog *fan, int percent)
{
- struct nvkm_therm_priv *tpriv = (void *)priv->base.parent;
- struct nvkm_timer *ptimer = nvkm_timer(tpriv);
- struct nvkm_gpio *gpio = nvkm_gpio(tpriv);
+ struct nvkm_therm *therm = fan->base.parent;
+ struct nvkm_device *device = therm->subdev.device;
+ struct nvkm_timer *tmr = device->timer;
+ struct nvkm_gpio *gpio = device->gpio;
unsigned long flags;
int duty;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&fan->lock, flags);
if (percent < 0)
- percent = priv->percent;
- priv->percent = percent;
+ percent = fan->percent;
+ fan->percent = percent;
- duty = !gpio->get(gpio, 0, DCB_GPIO_FAN, 0xff);
- gpio->set(gpio, 0, DCB_GPIO_FAN, 0xff, duty);
+ duty = !nvkm_gpio_get(gpio, 0, DCB_GPIO_FAN, 0xff);
+ nvkm_gpio_set(gpio, 0, DCB_GPIO_FAN, 0xff, duty);
- if (list_empty(&priv->alarm.head) && percent != (duty * 100)) {
- u64 next_change = (percent * priv->period_us) / 100;
+ if (list_empty(&fan->alarm.head) && percent != (duty * 100)) {
+ u64 next_change = (percent * fan->period_us) / 100;
if (!duty)
- next_change = priv->period_us - next_change;
- ptimer->alarm(ptimer, next_change * 1000, &priv->alarm);
+ next_change = fan->period_us - next_change;
+ nvkm_timer_alarm(tmr, next_change * 1000, &fan->alarm);
}
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&fan->lock, flags);
}
static void
nvkm_fantog_alarm(struct nvkm_alarm *alarm)
{
- struct nvkm_fantog_priv *priv =
- container_of(alarm, struct nvkm_fantog_priv, alarm);
- nvkm_fantog_update(priv, -1);
+ struct nvkm_fantog *fan =
+ container_of(alarm, struct nvkm_fantog, alarm);
+ nvkm_fantog_update(fan, -1);
}
static int
nvkm_fantog_get(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *tpriv = (void *)therm;
- struct nvkm_fantog_priv *priv = (void *)tpriv->fan;
- return priv->percent;
+ struct nvkm_fantog *fan = (void *)therm->fan;
+ return fan->percent;
}
static int
nvkm_fantog_set(struct nvkm_therm *therm, int percent)
{
- struct nvkm_therm_priv *tpriv = (void *)therm;
- struct nvkm_fantog_priv *priv = (void *)tpriv->fan;
- if (therm->pwm_ctrl)
- therm->pwm_ctrl(therm, priv->func.line, false);
- nvkm_fantog_update(priv, percent);
+ struct nvkm_fantog *fan = (void *)therm->fan;
+ if (therm->func->pwm_ctrl)
+ therm->func->pwm_ctrl(therm, fan->func.line, false);
+ nvkm_fantog_update(fan, percent);
return 0;
}
int
nvkm_fantog_create(struct nvkm_therm *therm, struct dcb_gpio_func *func)
{
- struct nvkm_therm_priv *tpriv = (void *)therm;
- struct nvkm_fantog_priv *priv;
+ struct nvkm_fantog *fan;
int ret;
- if (therm->pwm_ctrl) {
- ret = therm->pwm_ctrl(therm, func->line, false);
+ if (therm->func->pwm_ctrl) {
+ ret = therm->func->pwm_ctrl(therm, func->line, false);
if (ret)
return ret;
}
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- tpriv->fan = &priv->base;
- if (!priv)
+ fan = kzalloc(sizeof(*fan), GFP_KERNEL);
+ therm->fan = &fan->base;
+ if (!fan)
return -ENOMEM;
- priv->base.type = "toggle";
- priv->base.get = nvkm_fantog_get;
- priv->base.set = nvkm_fantog_set;
- nvkm_alarm_init(&priv->alarm, nvkm_fantog_alarm);
- priv->period_us = 100000; /* 10Hz */
- priv->percent = 100;
- priv->func = *func;
- spin_lock_init(&priv->lock);
+ fan->base.type = "toggle";
+ fan->base.get = nvkm_fantog_get;
+ fan->base.set = nvkm_fantog_set;
+ nvkm_alarm_init(&fan->alarm, nvkm_fantog_alarm);
+ fan->period_us = 100000; /* 10Hz */
+ fan->percent = 100;
+ fan->func = *func;
+ spin_lock_init(&fan->lock);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/g84.c
index 85b5d0c18c0b..86e81930d8ee 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/g84.c
@@ -26,17 +26,13 @@
#include <subdev/fuse.h>
-struct g84_therm_priv {
- struct nvkm_therm_priv base;
-};
-
int
g84_temp_get(struct nvkm_therm *therm)
{
- struct nvkm_fuse *fuse = nvkm_fuse(therm);
+ struct nvkm_device *device = therm->subdev.device;
- if (nv_ro32(fuse, 0x1a8) == 1)
- return nv_rd32(therm, 0x20400);
+ if (nvkm_fuse_read(device->fuse, 0x1a8) == 1)
+ return nvkm_rd32(device, 0x20400);
else
return -ENODEV;
}
@@ -44,12 +40,12 @@ g84_temp_get(struct nvkm_therm *therm)
void
g84_sensor_setup(struct nvkm_therm *therm)
{
- struct nvkm_fuse *fuse = nvkm_fuse(therm);
+ struct nvkm_device *device = therm->subdev.device;
/* enable temperature reading for cards with insane defaults */
- if (nv_ro32(fuse, 0x1a8) == 1) {
- nv_mask(therm, 0x20008, 0x80008000, 0x80000000);
- nv_mask(therm, 0x2000c, 0x80000003, 0x00000000);
+ if (nvkm_fuse_read(device->fuse, 0x1a8) == 1) {
+ nvkm_mask(device, 0x20008, 0x80008000, 0x80000000);
+ nvkm_mask(device, 0x2000c, 0x80000003, 0x00000000);
mdelay(20); /* wait for the temperature to stabilize */
}
}
@@ -57,36 +53,40 @@ g84_sensor_setup(struct nvkm_therm *therm)
static void
g84_therm_program_alarms(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
+ struct nvbios_therm_sensor *sensor = &therm->bios_sensor;
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_device *device = subdev->device;
unsigned long flags;
- spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
+ spin_lock_irqsave(&therm->sensor.alarm_program_lock, flags);
/* enable RISING and FALLING IRQs for shutdown, THRS 0, 1, 2 and 4 */
- nv_wr32(therm, 0x20000, 0x000003ff);
+ nvkm_wr32(device, 0x20000, 0x000003ff);
/* shutdown: The computer should be shutdown when reached */
- nv_wr32(therm, 0x20484, sensor->thrs_shutdown.hysteresis);
- nv_wr32(therm, 0x20480, sensor->thrs_shutdown.temp);
+ nvkm_wr32(device, 0x20484, sensor->thrs_shutdown.hysteresis);
+ nvkm_wr32(device, 0x20480, sensor->thrs_shutdown.temp);
/* THRS_1 : fan boost*/
- nv_wr32(therm, 0x204c4, sensor->thrs_fan_boost.temp);
+ nvkm_wr32(device, 0x204c4, sensor->thrs_fan_boost.temp);
/* THRS_2 : critical */
- nv_wr32(therm, 0x204c0, sensor->thrs_critical.temp);
+ nvkm_wr32(device, 0x204c0, sensor->thrs_critical.temp);
/* THRS_4 : down clock */
- nv_wr32(therm, 0x20414, sensor->thrs_down_clock.temp);
- spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
-
- nv_debug(therm,
- "Programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
- sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis,
- sensor->thrs_down_clock.temp,
- sensor->thrs_down_clock.hysteresis,
- sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis,
- sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis);
+ nvkm_wr32(device, 0x20414, sensor->thrs_down_clock.temp);
+ spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags);
+
+ nvkm_debug(subdev,
+ "Programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
+ sensor->thrs_fan_boost.temp,
+ sensor->thrs_fan_boost.hysteresis,
+ sensor->thrs_down_clock.temp,
+ sensor->thrs_down_clock.hysteresis,
+ sensor->thrs_critical.temp,
+ sensor->thrs_critical.hysteresis,
+ sensor->thrs_shutdown.temp,
+ sensor->thrs_shutdown.hysteresis);
}
@@ -97,24 +97,25 @@ g84_therm_threshold_hyst_emulation(struct nvkm_therm *therm,
const struct nvbios_therm_threshold *thrs,
enum nvkm_therm_thrs thrs_name)
{
+ struct nvkm_device *device = therm->subdev.device;
enum nvkm_therm_thrs_direction direction;
enum nvkm_therm_thrs_state prev_state, new_state;
int temp, cur;
prev_state = nvkm_therm_sensor_get_threshold_state(therm, thrs_name);
- temp = nv_rd32(therm, thrs_reg);
+ temp = nvkm_rd32(device, thrs_reg);
/* program the next threshold */
if (temp == thrs->temp) {
- nv_wr32(therm, thrs_reg, thrs->temp - thrs->hysteresis);
+ nvkm_wr32(device, thrs_reg, thrs->temp - thrs->hysteresis);
new_state = NVKM_THERM_THRS_HIGHER;
} else {
- nv_wr32(therm, thrs_reg, thrs->temp);
+ nvkm_wr32(device, thrs_reg, thrs->temp);
new_state = NVKM_THERM_THRS_LOWER;
}
/* fix the state (in case someone reprogrammed the alarms) */
- cur = therm->temp_get(therm);
+ cur = therm->func->temp_get(therm);
if (new_state == NVKM_THERM_THRS_LOWER && cur > thrs->temp)
new_state = NVKM_THERM_THRS_HIGHER;
else if (new_state == NVKM_THERM_THRS_HIGHER &&
@@ -135,17 +136,17 @@ g84_therm_threshold_hyst_emulation(struct nvkm_therm *therm,
}
static void
-g84_therm_intr(struct nvkm_subdev *subdev)
+g84_therm_intr(struct nvkm_therm *therm)
{
- struct nvkm_therm *therm = nvkm_therm(subdev);
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_device *device = subdev->device;
+ struct nvbios_therm_sensor *sensor = &therm->bios_sensor;
unsigned long flags;
uint32_t intr;
- spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
+ spin_lock_irqsave(&therm->sensor.alarm_program_lock, flags);
- intr = nv_rd32(therm, 0x20100) & 0x3ff;
+ intr = nvkm_rd32(device, 0x20100) & 0x3ff;
/* THRS_4: downclock */
if (intr & 0x002) {
@@ -180,87 +181,66 @@ g84_therm_intr(struct nvkm_subdev *subdev)
}
if (intr)
- nv_error(therm, "unhandled intr 0x%08x\n", intr);
+ nvkm_error(subdev, "intr %08x\n", intr);
/* ACK everything */
- nv_wr32(therm, 0x20100, 0xffffffff);
- nv_wr32(therm, 0x1100, 0x10000); /* PBUS */
+ nvkm_wr32(device, 0x20100, 0xffffffff);
+ nvkm_wr32(device, 0x1100, 0x10000); /* PBUS */
- spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
+ spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags);
}
-static int
-g84_therm_init(struct nvkm_object *object)
+void
+g84_therm_fini(struct nvkm_therm *therm)
{
- struct g84_therm_priv *priv = (void *)object;
- int ret;
+ struct nvkm_device *device = therm->subdev.device;
- ret = nvkm_therm_init(&priv->base.base);
- if (ret)
- return ret;
+ /* Disable PTherm IRQs */
+ nvkm_wr32(device, 0x20000, 0x00000000);
- g84_sensor_setup(&priv->base.base);
- return 0;
+ /* ACK all PTherm IRQs */
+ nvkm_wr32(device, 0x20100, 0xffffffff);
+ nvkm_wr32(device, 0x1100, 0x10000); /* PBUS */
}
-static int
-g84_therm_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+static void
+g84_therm_init(struct nvkm_therm *therm)
{
- struct g84_therm_priv *priv;
- int ret;
-
- ret = nvkm_therm_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl;
- priv->base.base.pwm_get = nv50_fan_pwm_get;
- priv->base.base.pwm_set = nv50_fan_pwm_set;
- priv->base.base.pwm_clock = nv50_fan_pwm_clock;
- priv->base.base.temp_get = g84_temp_get;
- priv->base.sensor.program_alarms = g84_therm_program_alarms;
- nv_subdev(priv)->intr = g84_therm_intr;
-
- /* init the thresholds */
- nvkm_therm_sensor_set_threshold_state(&priv->base.base,
- NVKM_THERM_THRS_SHUTDOWN,
- NVKM_THERM_THRS_LOWER);
- nvkm_therm_sensor_set_threshold_state(&priv->base.base,
- NVKM_THERM_THRS_FANBOOST,
- NVKM_THERM_THRS_LOWER);
- nvkm_therm_sensor_set_threshold_state(&priv->base.base,
- NVKM_THERM_THRS_CRITICAL,
- NVKM_THERM_THRS_LOWER);
- nvkm_therm_sensor_set_threshold_state(&priv->base.base,
- NVKM_THERM_THRS_DOWNCLOCK,
- NVKM_THERM_THRS_LOWER);
-
- return nvkm_therm_preinit(&priv->base.base);
+ g84_sensor_setup(therm);
}
+static const struct nvkm_therm_func
+g84_therm = {
+ .init = g84_therm_init,
+ .fini = g84_therm_fini,
+ .intr = g84_therm_intr,
+ .pwm_ctrl = nv50_fan_pwm_ctrl,
+ .pwm_get = nv50_fan_pwm_get,
+ .pwm_set = nv50_fan_pwm_set,
+ .pwm_clock = nv50_fan_pwm_clock,
+ .temp_get = g84_temp_get,
+ .program_alarms = g84_therm_program_alarms,
+};
+
int
-g84_therm_fini(struct nvkm_object *object, bool suspend)
+g84_therm_new(struct nvkm_device *device, int index, struct nvkm_therm **ptherm)
{
- /* Disable PTherm IRQs */
- nv_wr32(object, 0x20000, 0x00000000);
+ struct nvkm_therm *therm;
+ int ret;
- /* ACK all PTherm IRQs */
- nv_wr32(object, 0x20100, 0xffffffff);
- nv_wr32(object, 0x1100, 0x10000); /* PBUS */
+ ret = nvkm_therm_new_(&g84_therm, device, index, &therm);
+ *ptherm = therm;
+ if (ret)
+ return ret;
- return _nvkm_therm_fini(object, suspend);
+ /* init the thresholds */
+ nvkm_therm_sensor_set_threshold_state(therm, NVKM_THERM_THRS_SHUTDOWN,
+ NVKM_THERM_THRS_LOWER);
+ nvkm_therm_sensor_set_threshold_state(therm, NVKM_THERM_THRS_FANBOOST,
+ NVKM_THERM_THRS_LOWER);
+ nvkm_therm_sensor_set_threshold_state(therm, NVKM_THERM_THRS_CRITICAL,
+ NVKM_THERM_THRS_LOWER);
+ nvkm_therm_sensor_set_threshold_state(therm, NVKM_THERM_THRS_DOWNCLOCK,
+ NVKM_THERM_THRS_LOWER);
+ return 0;
}
-
-struct nvkm_oclass
-g84_therm_oclass = {
- .handle = NV_SUBDEV(THERM, 0x84),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = g84_therm_ctor,
- .dtor = _nvkm_therm_dtor,
- .init = g84_therm_init,
- .fini = g84_therm_fini,
- },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf110.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf110.c
deleted file mode 100644
index 46b7e656a752..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf110.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-#include "priv.h"
-
-#include <core/device.h>
-
-struct gf110_therm_priv {
- struct nvkm_therm_priv base;
-};
-
-static int
-pwm_info(struct nvkm_therm *therm, int line)
-{
- u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04));
-
- switch (gpio & 0x000000c0) {
- case 0x00000000: /* normal mode, possibly pwm forced off by us */
- case 0x00000040: /* nvio special */
- switch (gpio & 0x0000001f) {
- case 0x00: return 2;
- case 0x19: return 1;
- case 0x1c: return 0;
- case 0x1e: return 2;
- default:
- break;
- }
- default:
- break;
- }
-
- nv_error(therm, "GPIO %d unknown PWM: 0x%08x\n", line, gpio);
- return -ENODEV;
-}
-
-static int
-gf110_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
-{
- u32 data = enable ? 0x00000040 : 0x00000000;
- int indx = pwm_info(therm, line);
- if (indx < 0)
- return indx;
- else if (indx < 2)
- nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
- /* nothing to do for indx == 2, it seems hardwired to PTHERM */
- return 0;
-}
-
-static int
-gf110_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
-{
- int indx = pwm_info(therm, line);
- if (indx < 0)
- return indx;
- else if (indx < 2) {
- if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
- *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
- *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
- return 0;
- }
- } else if (indx == 2) {
- *divs = nv_rd32(therm, 0x0200d8) & 0x1fff;
- *duty = nv_rd32(therm, 0x0200dc) & 0x1fff;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int
-gf110_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty)
-{
- int indx = pwm_info(therm, line);
- if (indx < 0)
- return indx;
- else if (indx < 2) {
- nv_wr32(therm, 0x00e114 + (indx * 8), divs);
- nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000);
- } else if (indx == 2) {
- nv_mask(therm, 0x0200d8, 0x1fff, divs); /* keep the high bits */
- nv_wr32(therm, 0x0200dc, duty | 0x40000000);
- }
- return 0;
-}
-
-static int
-gf110_fan_pwm_clock(struct nvkm_therm *therm, int line)
-{
- int indx = pwm_info(therm, line);
- if (indx < 0)
- return 0;
- else if (indx < 2)
- return (nv_device(therm)->crystal * 1000) / 20;
- else
- return nv_device(therm)->crystal * 1000 / 10;
-}
-
-int
-gf110_therm_init(struct nvkm_object *object)
-{
- struct gf110_therm_priv *priv = (void *)object;
- int ret;
-
- ret = nvkm_therm_init(&priv->base.base);
- if (ret)
- return ret;
-
- /* enable fan tach, count revolutions per-second */
- nv_mask(priv, 0x00e720, 0x00000003, 0x00000002);
- if (priv->base.fan->tach.func != DCB_GPIO_UNUSED) {
- nv_mask(priv, 0x00d79c, 0x000000ff, priv->base.fan->tach.line);
- nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000);
- nv_mask(priv, 0x00e720, 0x00000001, 0x00000001);
- }
- nv_mask(priv, 0x00e720, 0x00000002, 0x00000000);
-
- return 0;
-}
-
-static int
-gf110_therm_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
-{
- struct gf110_therm_priv *priv;
- int ret;
-
- ret = nvkm_therm_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- g84_sensor_setup(&priv->base.base);
-
- priv->base.base.pwm_ctrl = gf110_fan_pwm_ctrl;
- priv->base.base.pwm_get = gf110_fan_pwm_get;
- priv->base.base.pwm_set = gf110_fan_pwm_set;
- priv->base.base.pwm_clock = gf110_fan_pwm_clock;
- priv->base.base.temp_get = g84_temp_get;
- priv->base.base.fan_sense = gt215_therm_fan_sense;
- priv->base.sensor.program_alarms = nvkm_therm_program_alarms_polling;
- return nvkm_therm_preinit(&priv->base.base);
-}
-
-struct nvkm_oclass
-gf110_therm_oclass = {
- .handle = NV_SUBDEV(THERM, 0xd0),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = gf110_therm_ctor,
- .dtor = _nvkm_therm_dtor,
- .init = gf110_therm_init,
- .fini = g84_therm_fini,
- },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c
new file mode 100644
index 000000000000..06dcfd6ee966
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+#include "priv.h"
+
+static int
+pwm_info(struct nvkm_therm *therm, int line)
+{
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 gpio = nvkm_rd32(device, 0x00d610 + (line * 0x04));
+
+ switch (gpio & 0x000000c0) {
+ case 0x00000000: /* normal mode, possibly pwm forced off by us */
+ case 0x00000040: /* nvio special */
+ switch (gpio & 0x0000001f) {
+ case 0x00: return 2;
+ case 0x19: return 1;
+ case 0x1c: return 0;
+ case 0x1e: return 2;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ nvkm_error(subdev, "GPIO %d unknown PWM: %08x\n", line, gpio);
+ return -ENODEV;
+}
+
+static int
+gf119_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
+{
+ struct nvkm_device *device = therm->subdev.device;
+ u32 data = enable ? 0x00000040 : 0x00000000;
+ int indx = pwm_info(therm, line);
+ if (indx < 0)
+ return indx;
+ else if (indx < 2)
+ nvkm_mask(device, 0x00d610 + (line * 0x04), 0x000000c0, data);
+ /* nothing to do for indx == 2, it seems hardwired to PTHERM */
+ return 0;
+}
+
+static int
+gf119_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
+{
+ struct nvkm_device *device = therm->subdev.device;
+ int indx = pwm_info(therm, line);
+ if (indx < 0)
+ return indx;
+ else if (indx < 2) {
+ if (nvkm_rd32(device, 0x00d610 + (line * 0x04)) & 0x00000040) {
+ *divs = nvkm_rd32(device, 0x00e114 + (indx * 8));
+ *duty = nvkm_rd32(device, 0x00e118 + (indx * 8));
+ return 0;
+ }
+ } else if (indx == 2) {
+ *divs = nvkm_rd32(device, 0x0200d8) & 0x1fff;
+ *duty = nvkm_rd32(device, 0x0200dc) & 0x1fff;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int
+gf119_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty)
+{
+ struct nvkm_device *device = therm->subdev.device;
+ int indx = pwm_info(therm, line);
+ if (indx < 0)
+ return indx;
+ else if (indx < 2) {
+ nvkm_wr32(device, 0x00e114 + (indx * 8), divs);
+ nvkm_wr32(device, 0x00e118 + (indx * 8), duty | 0x80000000);
+ } else if (indx == 2) {
+ nvkm_mask(device, 0x0200d8, 0x1fff, divs); /* keep the high bits */
+ nvkm_wr32(device, 0x0200dc, duty | 0x40000000);
+ }
+ return 0;
+}
+
+static int
+gf119_fan_pwm_clock(struct nvkm_therm *therm, int line)
+{
+ struct nvkm_device *device = therm->subdev.device;
+ int indx = pwm_info(therm, line);
+ if (indx < 0)
+ return 0;
+ else if (indx < 2)
+ return (device->crystal * 1000) / 20;
+ else
+ return device->crystal * 1000 / 10;
+}
+
+void
+gf119_therm_init(struct nvkm_therm *therm)
+{
+ struct nvkm_device *device = therm->subdev.device;
+
+ g84_sensor_setup(therm);
+
+ /* enable fan tach, count revolutions per-second */
+ nvkm_mask(device, 0x00e720, 0x00000003, 0x00000002);
+ if (therm->fan->tach.func != DCB_GPIO_UNUSED) {
+ nvkm_mask(device, 0x00d79c, 0x000000ff, therm->fan->tach.line);
+ nvkm_wr32(device, 0x00e724, device->crystal * 1000);
+ nvkm_mask(device, 0x00e720, 0x00000001, 0x00000001);
+ }
+ nvkm_mask(device, 0x00e720, 0x00000002, 0x00000000);
+}
+
+static const struct nvkm_therm_func
+gf119_therm = {
+ .init = gf119_therm_init,
+ .fini = g84_therm_fini,
+ .pwm_ctrl = gf119_fan_pwm_ctrl,
+ .pwm_get = gf119_fan_pwm_get,
+ .pwm_set = gf119_fan_pwm_set,
+ .pwm_clock = gf119_fan_pwm_clock,
+ .temp_get = g84_temp_get,
+ .fan_sense = gt215_therm_fan_sense,
+ .program_alarms = nvkm_therm_program_alarms_polling,
+};
+
+int
+gf119_therm_new(struct nvkm_device *device, int index,
+ struct nvkm_therm **ptherm)
+{
+ return nvkm_therm_new_(&gf119_therm, device, index, ptherm);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gm107.c
index 2fd110f09878..86848ece4d89 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gm107.c
@@ -23,12 +23,6 @@
*/
#include "priv.h"
-#include <core/device.h>
-
-struct gm107_therm_priv {
- struct nvkm_therm_priv base;
-};
-
static int
gm107_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
{
@@ -39,55 +33,43 @@ gm107_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
static int
gm107_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
{
- *divs = nv_rd32(therm, 0x10eb20) & 0x1fff;
- *duty = nv_rd32(therm, 0x10eb24) & 0x1fff;
+ struct nvkm_device *device = therm->subdev.device;
+ *divs = nvkm_rd32(device, 0x10eb20) & 0x1fff;
+ *duty = nvkm_rd32(device, 0x10eb24) & 0x1fff;
return 0;
}
static int
gm107_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty)
{
- nv_mask(therm, 0x10eb10, 0x1fff, divs); /* keep the high bits */
- nv_wr32(therm, 0x10eb14, duty | 0x80000000);
+ struct nvkm_device *device = therm->subdev.device;
+ nvkm_mask(device, 0x10eb10, 0x1fff, divs); /* keep the high bits */
+ nvkm_wr32(device, 0x10eb14, duty | 0x80000000);
return 0;
}
static int
gm107_fan_pwm_clock(struct nvkm_therm *therm, int line)
{
- return nv_device(therm)->crystal * 1000;
+ return therm->subdev.device->crystal * 1000;
}
-static int
-gm107_therm_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
-{
- struct gm107_therm_priv *priv;
- int ret;
-
- ret = nvkm_therm_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
+static const struct nvkm_therm_func
+gm107_therm = {
+ .init = gf119_therm_init,
+ .fini = g84_therm_fini,
+ .pwm_ctrl = gm107_fan_pwm_ctrl,
+ .pwm_get = gm107_fan_pwm_get,
+ .pwm_set = gm107_fan_pwm_set,
+ .pwm_clock = gm107_fan_pwm_clock,
+ .temp_get = g84_temp_get,
+ .fan_sense = gt215_therm_fan_sense,
+ .program_alarms = nvkm_therm_program_alarms_polling,
+};
- priv->base.base.pwm_ctrl = gm107_fan_pwm_ctrl;
- priv->base.base.pwm_get = gm107_fan_pwm_get;
- priv->base.base.pwm_set = gm107_fan_pwm_set;
- priv->base.base.pwm_clock = gm107_fan_pwm_clock;
- priv->base.base.temp_get = g84_temp_get;
- priv->base.base.fan_sense = gt215_therm_fan_sense;
- priv->base.sensor.program_alarms = nvkm_therm_program_alarms_polling;
- return nvkm_therm_preinit(&priv->base.base);
+int
+gm107_therm_new(struct nvkm_device *device, int index,
+ struct nvkm_therm **ptherm)
+{
+ return nvkm_therm_new_(&gm107_therm, device, index, ptherm);
}
-
-struct nvkm_oclass
-gm107_therm_oclass = {
- .handle = NV_SUBDEV(THERM, 0x117),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = gm107_therm_ctor,
- .dtor = _nvkm_therm_dtor,
- .init = gf110_therm_init,
- .fini = g84_therm_fini,
- },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c
index e99be20332f2..c08097f2aff5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c
@@ -23,78 +23,53 @@
*/
#include "priv.h"
-#include <core/device.h>
#include <subdev/gpio.h>
-struct gt215_therm_priv {
- struct nvkm_therm_priv base;
-};
-
int
gt215_therm_fan_sense(struct nvkm_therm *therm)
{
- u32 tach = nv_rd32(therm, 0x00e728) & 0x0000ffff;
- u32 ctrl = nv_rd32(therm, 0x00e720);
+ struct nvkm_device *device = therm->subdev.device;
+ u32 tach = nvkm_rd32(device, 0x00e728) & 0x0000ffff;
+ u32 ctrl = nvkm_rd32(device, 0x00e720);
if (ctrl & 0x00000001)
return tach * 60 / 2;
return -ENODEV;
}
-static int
-gt215_therm_init(struct nvkm_object *object)
+static void
+gt215_therm_init(struct nvkm_therm *therm)
{
- struct gt215_therm_priv *priv = (void *)object;
- struct dcb_gpio_func *tach = &priv->base.fan->tach;
- int ret;
-
- ret = nvkm_therm_init(&priv->base.base);
- if (ret)
- return ret;
+ struct nvkm_device *device = therm->subdev.device;
+ struct dcb_gpio_func *tach = &therm->fan->tach;
- g84_sensor_setup(&priv->base.base);
+ g84_sensor_setup(therm);
/* enable fan tach, count revolutions per-second */
- nv_mask(priv, 0x00e720, 0x00000003, 0x00000002);
+ nvkm_mask(device, 0x00e720, 0x00000003, 0x00000002);
if (tach->func != DCB_GPIO_UNUSED) {
- nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000);
- nv_mask(priv, 0x00e720, 0x001f0000, tach->line << 16);
- nv_mask(priv, 0x00e720, 0x00000001, 0x00000001);
+ nvkm_wr32(device, 0x00e724, device->crystal * 1000);
+ nvkm_mask(device, 0x00e720, 0x001f0000, tach->line << 16);
+ nvkm_mask(device, 0x00e720, 0x00000001, 0x00000001);
}
- nv_mask(priv, 0x00e720, 0x00000002, 0x00000000);
-
- return 0;
+ nvkm_mask(device, 0x00e720, 0x00000002, 0x00000000);
}
-static int
-gt215_therm_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
-{
- struct gt215_therm_priv *priv;
- int ret;
-
- ret = nvkm_therm_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
+static const struct nvkm_therm_func
+gt215_therm = {
+ .init = gt215_therm_init,
+ .fini = g84_therm_fini,
+ .pwm_ctrl = nv50_fan_pwm_ctrl,
+ .pwm_get = nv50_fan_pwm_get,
+ .pwm_set = nv50_fan_pwm_set,
+ .pwm_clock = nv50_fan_pwm_clock,
+ .temp_get = g84_temp_get,
+ .fan_sense = gt215_therm_fan_sense,
+ .program_alarms = nvkm_therm_program_alarms_polling,
+};
- priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl;
- priv->base.base.pwm_get = nv50_fan_pwm_get;
- priv->base.base.pwm_set = nv50_fan_pwm_set;
- priv->base.base.pwm_clock = nv50_fan_pwm_clock;
- priv->base.base.temp_get = g84_temp_get;
- priv->base.base.fan_sense = gt215_therm_fan_sense;
- priv->base.sensor.program_alarms = nvkm_therm_program_alarms_polling;
- return nvkm_therm_preinit(&priv->base.base);
+int
+gt215_therm_new(struct nvkm_device *device, int index,
+ struct nvkm_therm **ptherm)
+{
+ return nvkm_therm_new_(&gt215_therm, device, index, ptherm);
}
-
-struct nvkm_oclass
-gt215_therm_oclass = {
- .handle = NV_SUBDEV(THERM, 0xa3),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = gt215_therm_ctor,
- .dtor = _nvkm_therm_dtor,
- .init = gt215_therm_init,
- .fini = g84_therm_fini,
- },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c
index 09fc4605e853..6e0ddc1bb583 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c
@@ -27,16 +27,16 @@
#include <subdev/i2c.h>
static bool
-probe_monitoring_device(struct nvkm_i2c_port *i2c,
+probe_monitoring_device(struct nvkm_i2c_bus *bus,
struct i2c_board_info *info, void *data)
{
- struct nvkm_therm_priv *priv = data;
- struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
+ struct nvkm_therm *therm = data;
+ struct nvbios_therm_sensor *sensor = &therm->bios_sensor;
struct i2c_client *client;
request_module("%s%s", I2C_MODULE_PREFIX, info->type);
- client = i2c_new_device(&i2c->adapter, info);
+ client = i2c_new_device(&bus->i2c, info);
if (!client)
return false;
@@ -46,15 +46,15 @@ probe_monitoring_device(struct nvkm_i2c_port *i2c,
return false;
}
- nv_info(priv,
- "Found an %s at address 0x%x (controlled by lm_sensors, "
- "temp offset %+i C)\n",
- info->type, info->addr, sensor->offset_constant);
- priv->ic = client;
+ nvkm_debug(&therm->subdev,
+ "Found an %s at address 0x%x (controlled by lm_sensors, "
+ "temp offset %+i C)\n",
+ info->type, info->addr, sensor->offset_constant);
+ therm->ic = client;
return true;
}
-static struct nvkm_i2c_board_info
+static struct nvkm_i2c_bus_probe
nv_board_infos[] = {
{ { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 0 },
{ { I2C_BOARD_INFO("w83781d", 0x2d) }, 0 },
@@ -82,38 +82,43 @@ nv_board_infos[] = {
void
nvkm_therm_ic_ctor(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvkm_bios *bios = nvkm_bios(therm);
- struct nvkm_i2c *i2c = nvkm_i2c(therm);
+ struct nvkm_device *device = therm->subdev.device;
+ struct nvkm_bios *bios = device->bios;
+ struct nvkm_i2c *i2c = device->i2c;
+ struct nvkm_i2c_bus *bus;
struct nvbios_extdev_func extdev_entry;
+ bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_PRI);
+ if (!bus)
+ return;
+
if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) {
- struct nvkm_i2c_board_info board[] = {
+ struct nvkm_i2c_bus_probe board[] = {
{ { I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) }, 0},
{ }
};
- i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
- board, probe_monitoring_device, therm);
- if (priv->ic)
+ nvkm_i2c_bus_probe(bus, "monitoring device", board,
+ probe_monitoring_device, therm);
+ if (therm->ic)
return;
}
if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_ADT7473, &extdev_entry)) {
- struct nvkm_i2c_board_info board[] = {
+ struct nvkm_i2c_bus_probe board[] = {
{ { I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) }, 20 },
{ }
};
- i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
- board, probe_monitoring_device, therm);
- if (priv->ic)
+ nvkm_i2c_bus_probe(bus, "monitoring device", board,
+ probe_monitoring_device, therm);
+ if (therm->ic)
return;
}
/* The vbios doesn't provide the address of an exisiting monitoring
device. Let's try our static list.
*/
- i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
- nv_board_infos, probe_monitoring_device, therm);
+ nvkm_i2c_bus_probe(bus, "monitoring device", nv_board_infos,
+ probe_monitoring_device, therm);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c
index 8496fffd4688..6326fdc5a48d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c
@@ -24,26 +24,17 @@
*/
#include "priv.h"
-#include <core/device.h>
-
-struct nv40_therm_priv {
- struct nvkm_therm_priv base;
-};
-
enum nv40_sensor_style { INVALID_STYLE = -1, OLD_STYLE = 0, NEW_STYLE = 1 };
static enum nv40_sensor_style
nv40_sensor_style(struct nvkm_therm *therm)
{
- struct nvkm_device *device = nv_device(therm);
-
- switch (device->chipset) {
+ switch (therm->subdev.device->chipset) {
case 0x43:
case 0x44:
case 0x4a:
case 0x47:
return OLD_STYLE;
-
case 0x46:
case 0x49:
case 0x4b:
@@ -61,18 +52,19 @@ nv40_sensor_style(struct nvkm_therm *therm)
static int
nv40_sensor_setup(struct nvkm_therm *therm)
{
+ struct nvkm_device *device = therm->subdev.device;
enum nv40_sensor_style style = nv40_sensor_style(therm);
/* enable ADC readout and disable the ALARM threshold */
if (style == NEW_STYLE) {
- nv_mask(therm, 0x15b8, 0x80000000, 0);
- nv_wr32(therm, 0x15b0, 0x80003fff);
+ nvkm_mask(device, 0x15b8, 0x80000000, 0);
+ nvkm_wr32(device, 0x15b0, 0x80003fff);
mdelay(20); /* wait for the temperature to stabilize */
- return nv_rd32(therm, 0x15b4) & 0x3fff;
+ return nvkm_rd32(device, 0x15b4) & 0x3fff;
} else if (style == OLD_STYLE) {
- nv_wr32(therm, 0x15b0, 0xff);
+ nvkm_wr32(device, 0x15b0, 0xff);
mdelay(20); /* wait for the temperature to stabilize */
- return nv_rd32(therm, 0x15b4) & 0xff;
+ return nvkm_rd32(device, 0x15b4) & 0xff;
} else
return -ENODEV;
}
@@ -80,17 +72,17 @@ nv40_sensor_setup(struct nvkm_therm *therm)
static int
nv40_temp_get(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
+ struct nvkm_device *device = therm->subdev.device;
+ struct nvbios_therm_sensor *sensor = &therm->bios_sensor;
enum nv40_sensor_style style = nv40_sensor_style(therm);
int core_temp;
if (style == NEW_STYLE) {
- nv_wr32(therm, 0x15b0, 0x80003fff);
- core_temp = nv_rd32(therm, 0x15b4) & 0x3fff;
+ nvkm_wr32(device, 0x15b0, 0x80003fff);
+ core_temp = nvkm_rd32(device, 0x15b4) & 0x3fff;
} else if (style == OLD_STYLE) {
- nv_wr32(therm, 0x15b0, 0xff);
- core_temp = nv_rd32(therm, 0x15b4) & 0xff;
+ nvkm_wr32(device, 0x15b0, 0xff);
+ core_temp = nvkm_rd32(device, 0x15b4) & 0xff;
} else
return -ENODEV;
@@ -113,11 +105,13 @@ nv40_temp_get(struct nvkm_therm *therm)
static int
nv40_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
{
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_device *device = subdev->device;
u32 mask = enable ? 0x80000000 : 0x0000000;
- if (line == 2) nv_mask(therm, 0x0010f0, 0x80000000, mask);
- else if (line == 9) nv_mask(therm, 0x0015f4, 0x80000000, mask);
+ if (line == 2) nvkm_mask(device, 0x0010f0, 0x80000000, mask);
+ else if (line == 9) nvkm_mask(device, 0x0015f4, 0x80000000, mask);
else {
- nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
+ nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", line);
return -ENODEV;
}
return 0;
@@ -126,8 +120,10 @@ nv40_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
static int
nv40_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
{
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_device *device = subdev->device;
if (line == 2) {
- u32 reg = nv_rd32(therm, 0x0010f0);
+ u32 reg = nvkm_rd32(device, 0x0010f0);
if (reg & 0x80000000) {
*duty = (reg & 0x7fff0000) >> 16;
*divs = (reg & 0x00007fff);
@@ -135,14 +131,14 @@ nv40_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
}
} else
if (line == 9) {
- u32 reg = nv_rd32(therm, 0x0015f4);
+ u32 reg = nvkm_rd32(device, 0x0015f4);
if (reg & 0x80000000) {
- *divs = nv_rd32(therm, 0x0015f8);
+ *divs = nvkm_rd32(device, 0x0015f8);
*duty = (reg & 0x7fffffff);
return 0;
}
} else {
- nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
+ nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", line);
return -ENODEV;
}
@@ -152,14 +148,16 @@ nv40_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
static int
nv40_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty)
{
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_device *device = subdev->device;
if (line == 2) {
- nv_mask(therm, 0x0010f0, 0x7fff7fff, (duty << 16) | divs);
+ nvkm_mask(device, 0x0010f0, 0x7fff7fff, (duty << 16) | divs);
} else
if (line == 9) {
- nv_wr32(therm, 0x0015f8, divs);
- nv_mask(therm, 0x0015f4, 0x7fffffff, duty);
+ nvkm_wr32(device, 0x0015f8, divs);
+ nvkm_mask(device, 0x0015f4, 0x7fffffff, duty);
} else {
- nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
+ nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", line);
return -ENODEV;
}
@@ -167,59 +165,40 @@ nv40_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty)
}
void
-nv40_therm_intr(struct nvkm_subdev *subdev)
+nv40_therm_intr(struct nvkm_therm *therm)
{
- struct nvkm_therm *therm = nvkm_therm(subdev);
- uint32_t stat = nv_rd32(therm, 0x1100);
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_device *device = subdev->device;
+ uint32_t stat = nvkm_rd32(device, 0x1100);
/* traitement */
/* ack all IRQs */
- nv_wr32(therm, 0x1100, 0x70000);
+ nvkm_wr32(device, 0x1100, 0x70000);
- nv_error(therm, "THERM received an IRQ: stat = %x\n", stat);
+ nvkm_error(subdev, "THERM received an IRQ: stat = %x\n", stat);
}
-static int
-nv40_therm_ctor(struct nvkm_object *parent,
- struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+static void
+nv40_therm_init(struct nvkm_therm *therm)
{
- struct nv40_therm_priv *priv;
- int ret;
-
- ret = nvkm_therm_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.base.pwm_ctrl = nv40_fan_pwm_ctrl;
- priv->base.base.pwm_get = nv40_fan_pwm_get;
- priv->base.base.pwm_set = nv40_fan_pwm_set;
- priv->base.base.temp_get = nv40_temp_get;
- priv->base.sensor.program_alarms = nvkm_therm_program_alarms_polling;
- nv_subdev(priv)->intr = nv40_therm_intr;
- return nvkm_therm_preinit(&priv->base.base);
-}
-
-static int
-nv40_therm_init(struct nvkm_object *object)
-{
- struct nvkm_therm *therm = (void *)object;
-
nv40_sensor_setup(therm);
-
- return _nvkm_therm_init(object);
}
-struct nvkm_oclass
-nv40_therm_oclass = {
- .handle = NV_SUBDEV(THERM, 0x40),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv40_therm_ctor,
- .dtor = _nvkm_therm_dtor,
- .init = nv40_therm_init,
- .fini = _nvkm_therm_fini,
- },
+static const struct nvkm_therm_func
+nv40_therm = {
+ .init = nv40_therm_init,
+ .intr = nv40_therm_intr,
+ .pwm_ctrl = nv40_fan_pwm_ctrl,
+ .pwm_get = nv40_fan_pwm_get,
+ .pwm_set = nv40_fan_pwm_set,
+ .temp_get = nv40_temp_get,
+ .program_alarms = nvkm_therm_program_alarms_polling,
};
+
+int
+nv40_therm_new(struct nvkm_device *device, int index,
+ struct nvkm_therm **ptherm)
+{
+ return nvkm_therm_new_(&nv40_therm, device, index, ptherm);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv50.c
index 1ef59e8922d4..9b57b433d4cf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv50.c
@@ -24,15 +24,11 @@
*/
#include "priv.h"
-#include <core/device.h>
-
-struct nv50_therm_priv {
- struct nvkm_therm_priv base;
-};
-
static int
pwm_info(struct nvkm_therm *therm, int *line, int *ctrl, int *indx)
{
+ struct nvkm_subdev *subdev = &therm->subdev;
+
if (*line == 0x04) {
*ctrl = 0x00e100;
*line = 4;
@@ -48,7 +44,7 @@ pwm_info(struct nvkm_therm *therm, int *line, int *ctrl, int *indx)
*line = 0;
*indx = 0;
} else {
- nv_error(therm, "unknown pwm ctrl for gpio %d\n", *line);
+ nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", *line);
return -ENODEV;
}
@@ -58,23 +54,25 @@ pwm_info(struct nvkm_therm *therm, int *line, int *ctrl, int *indx)
int
nv50_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
{
+ struct nvkm_device *device = therm->subdev.device;
u32 data = enable ? 0x00000001 : 0x00000000;
int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id);
if (ret == 0)
- nv_mask(therm, ctrl, 0x00010001 << line, data << line);
+ nvkm_mask(device, ctrl, 0x00010001 << line, data << line);
return ret;
}
int
nv50_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
{
+ struct nvkm_device *device = therm->subdev.device;
int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id);
if (ret)
return ret;
- if (nv_rd32(therm, ctrl) & (1 << line)) {
- *divs = nv_rd32(therm, 0x00e114 + (id * 8));
- *duty = nv_rd32(therm, 0x00e118 + (id * 8));
+ if (nvkm_rd32(device, ctrl) & (1 << line)) {
+ *divs = nvkm_rd32(device, 0x00e114 + (id * 8));
+ *duty = nvkm_rd32(device, 0x00e118 + (id * 8));
return 0;
}
@@ -84,36 +82,36 @@ nv50_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
int
nv50_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty)
{
+ struct nvkm_device *device = therm->subdev.device;
int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id);
if (ret)
return ret;
- nv_wr32(therm, 0x00e114 + (id * 8), divs);
- nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000);
+ nvkm_wr32(device, 0x00e114 + (id * 8), divs);
+ nvkm_wr32(device, 0x00e118 + (id * 8), duty | 0x80000000);
return 0;
}
int
nv50_fan_pwm_clock(struct nvkm_therm *therm, int line)
{
- int chipset = nv_device(therm)->chipset;
- int crystal = nv_device(therm)->crystal;
+ struct nvkm_device *device = therm->subdev.device;
int pwm_clock;
/* determine the PWM source clock */
- if (chipset > 0x50 && chipset < 0x94) {
- u8 pwm_div = nv_rd32(therm, 0x410c);
- if (nv_rd32(therm, 0xc040) & 0x800000) {
+ if (device->chipset > 0x50 && device->chipset < 0x94) {
+ u8 pwm_div = nvkm_rd32(device, 0x410c);
+ if (nvkm_rd32(device, 0xc040) & 0x800000) {
/* Use the HOST clock (100 MHz)
* Where does this constant(2.4) comes from? */
pwm_clock = (100000000 >> pwm_div) * 10 / 24;
} else {
/* Where does this constant(20) comes from? */
- pwm_clock = (crystal * 1000) >> pwm_div;
+ pwm_clock = (device->crystal * 1000) >> pwm_div;
pwm_clock /= 20;
}
} else {
- pwm_clock = (crystal * 1000) / 20;
+ pwm_clock = (device->crystal * 1000) / 20;
}
return pwm_clock;
@@ -122,18 +120,19 @@ nv50_fan_pwm_clock(struct nvkm_therm *therm, int line)
static void
nv50_sensor_setup(struct nvkm_therm *therm)
{
- nv_mask(therm, 0x20010, 0x40000000, 0x0);
+ struct nvkm_device *device = therm->subdev.device;
+ nvkm_mask(device, 0x20010, 0x40000000, 0x0);
mdelay(20); /* wait for the temperature to stabilize */
}
static int
nv50_temp_get(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
+ struct nvkm_device *device = therm->subdev.device;
+ struct nvbios_therm_sensor *sensor = &therm->bios_sensor;
int core_temp;
- core_temp = nv_rd32(therm, 0x20014) & 0x3fff;
+ core_temp = nvkm_rd32(device, 0x20014) & 0x3fff;
/* if the slope or the offset is unset, do no use the sensor */
if (!sensor->slope_div || !sensor->slope_mult ||
@@ -151,48 +150,27 @@ nv50_temp_get(struct nvkm_therm *therm)
return core_temp;
}
-static int
-nv50_therm_ctor(struct nvkm_object *parent,
- struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
-{
- struct nv50_therm_priv *priv;
- int ret;
-
- ret = nvkm_therm_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl;
- priv->base.base.pwm_get = nv50_fan_pwm_get;
- priv->base.base.pwm_set = nv50_fan_pwm_set;
- priv->base.base.pwm_clock = nv50_fan_pwm_clock;
- priv->base.base.temp_get = nv50_temp_get;
- priv->base.sensor.program_alarms = nvkm_therm_program_alarms_polling;
- nv_subdev(priv)->intr = nv40_therm_intr;
-
- return nvkm_therm_preinit(&priv->base.base);
-}
-
-static int
-nv50_therm_init(struct nvkm_object *object)
+static void
+nv50_therm_init(struct nvkm_therm *therm)
{
- struct nvkm_therm *therm = (void *)object;
-
nv50_sensor_setup(therm);
-
- return _nvkm_therm_init(object);
}
-struct nvkm_oclass
-nv50_therm_oclass = {
- .handle = NV_SUBDEV(THERM, 0x50),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv50_therm_ctor,
- .dtor = _nvkm_therm_dtor,
- .init = nv50_therm_init,
- .fini = _nvkm_therm_fini,
- },
+static const struct nvkm_therm_func
+nv50_therm = {
+ .init = nv50_therm_init,
+ .intr = nv40_therm_intr,
+ .pwm_ctrl = nv50_fan_pwm_ctrl,
+ .pwm_get = nv50_fan_pwm_get,
+ .pwm_set = nv50_fan_pwm_set,
+ .pwm_clock = nv50_fan_pwm_clock,
+ .temp_get = nv50_temp_get,
+ .program_alarms = nvkm_therm_program_alarms_polling,
};
+
+int
+nv50_therm_new(struct nvkm_device *device, int index,
+ struct nvkm_therm **ptherm)
+{
+ return nvkm_therm_new_(&nv50_therm, device, index, ptherm);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h
index 916a149efe6e..235a5d8daff6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h
@@ -1,5 +1,6 @@
#ifndef __NVTHERM_PRIV_H__
#define __NVTHERM_PRIV_H__
+#define nvkm_therm(p) container_of((p), struct nvkm_therm, subdev)
/*
* Copyright 2012 The Nouveau community
*
@@ -28,8 +29,9 @@
#include <subdev/bios/extdev.h>
#include <subdev/bios/gpio.h>
#include <subdev/bios/perf.h>
-#include <subdev/bios/therm.h>
-#include <subdev/timer.h>
+
+int nvkm_therm_new_(const struct nvkm_therm_func *, struct nvkm_device *,
+ int index, struct nvkm_therm **);
struct nvkm_fan {
struct nvkm_therm *parent;
@@ -48,59 +50,6 @@ struct nvkm_fan {
struct dcb_gpio_func tach;
};
-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
-};
-
-struct nvkm_therm_priv {
- struct nvkm_therm base;
-
- /* 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];
- void (*program_alarms)(struct nvkm_therm *);
- } 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 nvkm_therm_fan_mode(struct nvkm_therm *, int mode);
int nvkm_therm_attr_get(struct nvkm_therm *, enum nvkm_therm_attr_type);
int nvkm_therm_attr_set(struct nvkm_therm *, enum nvkm_therm_attr_type, int);
@@ -117,8 +66,6 @@ int nvkm_therm_fan_set(struct nvkm_therm *, bool now, int percent);
int nvkm_therm_fan_user_get(struct nvkm_therm *);
int nvkm_therm_fan_user_set(struct nvkm_therm *, int percent);
-int nvkm_therm_fan_sense(struct nvkm_therm *);
-
int nvkm_therm_preinit(struct nvkm_therm *);
int nvkm_therm_sensor_init(struct nvkm_therm *);
@@ -134,18 +81,37 @@ void nvkm_therm_sensor_event(struct nvkm_therm *, enum nvkm_therm_thrs,
enum nvkm_therm_thrs_direction);
void nvkm_therm_program_alarms_polling(struct nvkm_therm *);
-void nv40_therm_intr(struct nvkm_subdev *);
+struct nvkm_therm_func {
+ void (*init)(struct nvkm_therm *);
+ void (*fini)(struct nvkm_therm *);
+ void (*intr)(struct nvkm_therm *);
+
+ int (*pwm_ctrl)(struct nvkm_therm *, int line, bool);
+ int (*pwm_get)(struct nvkm_therm *, int line, u32 *, u32 *);
+ int (*pwm_set)(struct nvkm_therm *, int line, u32, u32);
+ int (*pwm_clock)(struct nvkm_therm *, int line);
+
+ int (*temp_get)(struct nvkm_therm *);
+
+ int (*fan_sense)(struct nvkm_therm *);
+
+ void (*program_alarms)(struct nvkm_therm *);
+};
+
+void nv40_therm_intr(struct nvkm_therm *);
+
int nv50_fan_pwm_ctrl(struct nvkm_therm *, int, bool);
int nv50_fan_pwm_get(struct nvkm_therm *, int, u32 *, u32 *);
int nv50_fan_pwm_set(struct nvkm_therm *, int, u32, u32);
int nv50_fan_pwm_clock(struct nvkm_therm *, int);
+
int g84_temp_get(struct nvkm_therm *);
void g84_sensor_setup(struct nvkm_therm *);
-int g84_therm_fini(struct nvkm_object *, bool suspend);
+void g84_therm_fini(struct nvkm_therm *);
int gt215_therm_fan_sense(struct nvkm_therm *);
-int gf110_therm_init(struct nvkm_object *);
+void gf119_therm_init(struct nvkm_therm *);
int nvkm_fanpwm_create(struct nvkm_therm *, struct dcb_gpio_func *);
int nvkm_fantog_create(struct nvkm_therm *, struct dcb_gpio_func *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c
index aa13744f3854..b9703c02d8ca 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c
@@ -26,29 +26,25 @@
static void
nvkm_therm_temp_set_defaults(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
+ therm->bios_sensor.offset_constant = 0;
- priv->bios_sensor.offset_constant = 0;
+ therm->bios_sensor.thrs_fan_boost.temp = 90;
+ therm->bios_sensor.thrs_fan_boost.hysteresis = 3;
- priv->bios_sensor.thrs_fan_boost.temp = 90;
- priv->bios_sensor.thrs_fan_boost.hysteresis = 3;
+ therm->bios_sensor.thrs_down_clock.temp = 95;
+ therm->bios_sensor.thrs_down_clock.hysteresis = 3;
- priv->bios_sensor.thrs_down_clock.temp = 95;
- priv->bios_sensor.thrs_down_clock.hysteresis = 3;
+ therm->bios_sensor.thrs_critical.temp = 105;
+ therm->bios_sensor.thrs_critical.hysteresis = 5;
- priv->bios_sensor.thrs_critical.temp = 105;
- priv->bios_sensor.thrs_critical.hysteresis = 5;
-
- priv->bios_sensor.thrs_shutdown.temp = 135;
- priv->bios_sensor.thrs_shutdown.hysteresis = 5; /*not that it matters */
+ therm->bios_sensor.thrs_shutdown.temp = 135;
+ therm->bios_sensor.thrs_shutdown.hysteresis = 5; /*not that it matters */
}
-
static void
nvkm_therm_temp_safety_checks(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvbios_therm_sensor *s = &priv->bios_sensor;
+ struct nvbios_therm_sensor *s = &therm->bios_sensor;
/* enforce a minimum hysteresis on thresholds */
s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2);
@@ -63,8 +59,7 @@ nvkm_therm_sensor_set_threshold_state(struct nvkm_therm *therm,
enum nvkm_therm_thrs thrs,
enum nvkm_therm_thrs_state st)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- priv->sensor.alarm_state[thrs] = st;
+ therm->sensor.alarm_state[thrs] = st;
}
/* must be called with alarm_program_lock taken ! */
@@ -72,8 +67,7 @@ enum nvkm_therm_thrs_state
nvkm_therm_sensor_get_threshold_state(struct nvkm_therm *therm,
enum nvkm_therm_thrs thrs)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- return priv->sensor.alarm_state[thrs];
+ return therm->sensor.alarm_state[thrs];
}
static void
@@ -87,22 +81,23 @@ void
nvkm_therm_sensor_event(struct nvkm_therm *therm, enum nvkm_therm_thrs thrs,
enum nvkm_therm_thrs_direction dir)
{
- struct nvkm_therm_priv *priv = (void *)therm;
+ struct nvkm_subdev *subdev = &therm->subdev;
bool active;
const char *thresolds[] = {
"fanboost", "downclock", "critical", "shutdown"
};
- int temperature = therm->temp_get(therm);
+ int temperature = therm->func->temp_get(therm);
if (thrs < 0 || thrs > 3)
return;
if (dir == NVKM_THERM_THRS_FALLING)
- nv_info(therm, "temperature (%i C) went below the '%s' threshold\n",
- temperature, thresolds[thrs]);
+ nvkm_info(subdev,
+ "temperature (%i C) went below the '%s' threshold\n",
+ temperature, thresolds[thrs]);
else
- nv_info(therm, "temperature (%i C) hit the '%s' threshold\n",
- temperature, thresolds[thrs]);
+ nvkm_info(subdev, "temperature (%i C) hit the '%s' threshold\n",
+ temperature, thresolds[thrs]);
active = (dir == NVKM_THERM_THRS_RISING);
switch (thrs) {
@@ -113,12 +108,12 @@ nvkm_therm_sensor_event(struct nvkm_therm *therm, enum nvkm_therm_thrs thrs,
}
break;
case NVKM_THERM_THRS_DOWNCLOCK:
- if (priv->emergency.downclock)
- priv->emergency.downclock(therm, active);
+ if (therm->emergency.downclock)
+ therm->emergency.downclock(therm, active);
break;
case NVKM_THERM_THRS_CRITICAL:
- if (priv->emergency.pause)
- priv->emergency.pause(therm, active);
+ if (therm->emergency.pause)
+ therm->emergency.pause(therm, active);
break;
case NVKM_THERM_THRS_SHUTDOWN:
if (active) {
@@ -145,7 +140,7 @@ nvkm_therm_threshold_hyst_polling(struct nvkm_therm *therm,
{
enum nvkm_therm_thrs_direction direction;
enum nvkm_therm_thrs_state prev_state, new_state;
- int temp = therm->temp_get(therm);
+ int temp = therm->func->temp_get(therm);
prev_state = nvkm_therm_sensor_get_threshold_state(therm, thrs_name);
@@ -166,19 +161,19 @@ nvkm_therm_threshold_hyst_polling(struct nvkm_therm *therm,
static void
alarm_timer_callback(struct nvkm_alarm *alarm)
{
- struct nvkm_therm_priv *priv =
- container_of(alarm, struct nvkm_therm_priv, sensor.therm_poll_alarm);
- struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
- struct nvkm_timer *ptimer = nvkm_timer(priv);
- struct nvkm_therm *therm = &priv->base;
+ struct nvkm_therm *therm =
+ container_of(alarm, struct nvkm_therm, sensor.therm_poll_alarm);
+ struct nvbios_therm_sensor *sensor = &therm->bios_sensor;
+ struct nvkm_timer *tmr = therm->subdev.device->timer;
unsigned long flags;
- spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
+ spin_lock_irqsave(&therm->sensor.alarm_program_lock, flags);
nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost,
NVKM_THERM_THRS_FANBOOST);
- nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_down_clock,
+ nvkm_therm_threshold_hyst_polling(therm,
+ &sensor->thrs_down_clock,
NVKM_THERM_THRS_DOWNCLOCK);
nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_critical,
@@ -187,46 +182,45 @@ alarm_timer_callback(struct nvkm_alarm *alarm)
nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_shutdown,
NVKM_THERM_THRS_SHUTDOWN);
- spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
+ spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags);
/* schedule the next poll in one second */
- if (therm->temp_get(therm) >= 0 && list_empty(&alarm->head))
- ptimer->alarm(ptimer, 1000000000ULL, alarm);
+ if (therm->func->temp_get(therm) >= 0 && list_empty(&alarm->head))
+ nvkm_timer_alarm(tmr, 1000000000ULL, alarm);
}
void
nvkm_therm_program_alarms_polling(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
-
- nv_debug(therm,
- "programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
- sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis,
- sensor->thrs_down_clock.temp,
- sensor->thrs_down_clock.hysteresis,
- sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis,
- sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis);
-
- alarm_timer_callback(&priv->sensor.therm_poll_alarm);
+ struct nvbios_therm_sensor *sensor = &therm->bios_sensor;
+
+ nvkm_debug(&therm->subdev,
+ "programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
+ sensor->thrs_fan_boost.temp,
+ sensor->thrs_fan_boost.hysteresis,
+ sensor->thrs_down_clock.temp,
+ sensor->thrs_down_clock.hysteresis,
+ sensor->thrs_critical.temp,
+ sensor->thrs_critical.hysteresis,
+ sensor->thrs_shutdown.temp,
+ sensor->thrs_shutdown.hysteresis);
+
+ alarm_timer_callback(&therm->sensor.therm_poll_alarm);
}
int
nvkm_therm_sensor_init(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- priv->sensor.program_alarms(therm);
+ therm->func->program_alarms(therm);
return 0;
}
int
nvkm_therm_sensor_fini(struct nvkm_therm *therm, bool suspend)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvkm_timer *ptimer = nvkm_timer(therm);
-
+ struct nvkm_timer *tmr = therm->subdev.device->timer;
if (suspend)
- ptimer->alarm_cancel(ptimer, &priv->sensor.therm_poll_alarm);
+ nvkm_timer_alarm_cancel(tmr, &therm->sensor.therm_poll_alarm);
return 0;
}
@@ -235,24 +229,24 @@ nvkm_therm_sensor_preinit(struct nvkm_therm *therm)
{
const char *sensor_avail = "yes";
- if (therm->temp_get(therm) < 0)
+ if (therm->func->temp_get(therm) < 0)
sensor_avail = "no";
- nv_info(therm, "internal sensor: %s\n", sensor_avail);
+ nvkm_debug(&therm->subdev, "internal sensor: %s\n", sensor_avail);
}
int
nvkm_therm_sensor_ctor(struct nvkm_therm *therm)
{
- struct nvkm_therm_priv *priv = (void *)therm;
- struct nvkm_bios *bios = nvkm_bios(therm);
+ struct nvkm_subdev *subdev = &therm->subdev;
+ struct nvkm_bios *bios = subdev->device->bios;
- nvkm_alarm_init(&priv->sensor.therm_poll_alarm, alarm_timer_callback);
+ nvkm_alarm_init(&therm->sensor.therm_poll_alarm, alarm_timer_callback);
nvkm_therm_temp_set_defaults(therm);
if (nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE,
- &priv->bios_sensor))
- nv_error(therm, "nvbios_therm_sensor_parse failed\n");
+ &therm->bios_sensor))
+ nvkm_error(subdev, "nvbios_therm_sensor_parse failed\n");
nvkm_therm_temp_safety_checks(therm);
return 0;