Skip to content

Commit

Permalink
drm/nouveau/therm: split the nv50 and nv84 code
Browse files Browse the repository at this point in the history
This is needed because temperature management on nv50 can be enabled and it
looks about the same as nv40.

Signed-off-by: Martin Peres <martin.peres@labri.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Martin Peres authored and Ben Skeggs committed Apr 26, 2013
1 parent 897a6e2 commit 2f45736
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 164 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ nouveau-y += core/subdev/therm/ic.o
nouveau-y += core/subdev/therm/temp.o
nouveau-y += core/subdev/therm/nv40.o
nouveau-y += core/subdev/therm/nv50.o
nouveau-y += core/subdev/therm/nv84.o
nouveau-y += core/subdev/therm/nva3.o
nouveau-y += core/subdev/therm/nvd0.o
nouveau-y += core/subdev/timer/base.o
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/core/include/subdev/therm.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ int _nouveau_therm_fini(struct nouveau_object *, bool);

extern struct nouveau_oclass nv40_therm_oclass;
extern struct nouveau_oclass nv50_therm_oclass;
extern struct nouveau_oclass nv84_therm_oclass;
extern struct nouveau_oclass nva3_therm_oclass;
extern struct nouveau_oclass nvd0_therm_oclass;

Expand Down
18 changes: 9 additions & 9 deletions drivers/gpu/drm/nouveau/core/subdev/device/nv50.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
Expand All @@ -109,7 +109,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
Expand All @@ -135,7 +135,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
Expand All @@ -161,7 +161,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
Expand All @@ -187,7 +187,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
Expand All @@ -213,7 +213,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
Expand All @@ -239,7 +239,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
Expand All @@ -265,7 +265,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
Expand All @@ -291,7 +291,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
return 0;
}

static void
void
nv40_therm_intr(struct nouveau_subdev *subdev)
{
struct nouveau_therm *therm = nouveau_therm(subdev);
Expand Down
153 changes: 2 additions & 151 deletions drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,141 +124,6 @@ nv50_temp_get(struct nouveau_therm *therm)
return nv_rd32(therm, 0x20400);
}

static void
nv50_therm_program_alarms(struct nouveau_therm *therm)
{
struct nouveau_therm_priv *priv = (void *)therm;
struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
unsigned long flags;

spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);

/* enable RISING and FALLING IRQs for shutdown, THRS 0, 1, 2 and 4 */
nv_wr32(therm, 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);

/* THRS_1 : fan boost*/
nv_wr32(therm, 0x204c4, sensor->thrs_fan_boost.temp);

/* THRS_2 : critical */
nv_wr32(therm, 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_info(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);

}

/* must be called with alarm_program_lock taken ! */
static void
nv50_therm_threshold_hyst_emulation(struct nouveau_therm *therm,
uint32_t thrs_reg, u8 status_bit,
const struct nvbios_therm_threshold *thrs,
enum nouveau_therm_thrs thrs_name)
{
enum nouveau_therm_thrs_direction direction;
enum nouveau_therm_thrs_state prev_state, new_state;
int temp, cur;

prev_state = nouveau_therm_sensor_get_threshold_state(therm, thrs_name);
temp = nv_rd32(therm, thrs_reg);

/* program the next threshold */
if (temp == thrs->temp) {
nv_wr32(therm, thrs_reg, thrs->temp - thrs->hysteresis);
new_state = NOUVEAU_THERM_THRS_HIGHER;
} else {
nv_wr32(therm, thrs_reg, thrs->temp);
new_state = NOUVEAU_THERM_THRS_LOWER;
}

/* fix the state (in case someone reprogrammed the alarms) */
cur = therm->temp_get(therm);
if (new_state == NOUVEAU_THERM_THRS_LOWER && cur > thrs->temp)
new_state = NOUVEAU_THERM_THRS_HIGHER;
else if (new_state == NOUVEAU_THERM_THRS_HIGHER &&
cur < thrs->temp - thrs->hysteresis)
new_state = NOUVEAU_THERM_THRS_LOWER;
nouveau_therm_sensor_set_threshold_state(therm, thrs_name, new_state);

/* find the direction */
if (prev_state < new_state)
direction = NOUVEAU_THERM_THRS_RISING;
else if (prev_state > new_state)
direction = NOUVEAU_THERM_THRS_FALLING;
else
return;

/* advertise a change in direction */
nouveau_therm_sensor_event(therm, thrs_name, direction);
}

static void
nv50_therm_intr(struct nouveau_subdev *subdev)
{
struct nouveau_therm *therm = nouveau_therm(subdev);
struct nouveau_therm_priv *priv = (void *)therm;
struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
unsigned long flags;
uint32_t intr;

spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);

intr = nv_rd32(therm, 0x20100);

/* THRS_4: downclock */
if (intr & 0x002) {
nv50_therm_threshold_hyst_emulation(therm, 0x20414, 24,
&sensor->thrs_down_clock,
NOUVEAU_THERM_THRS_DOWNCLOCK);
intr &= ~0x002;
}

/* shutdown */
if (intr & 0x004) {
nv50_therm_threshold_hyst_emulation(therm, 0x20480, 20,
&sensor->thrs_shutdown,
NOUVEAU_THERM_THRS_SHUTDOWN);
intr &= ~0x004;
}

/* THRS_1 : fan boost */
if (intr & 0x008) {
nv50_therm_threshold_hyst_emulation(therm, 0x204c4, 21,
&sensor->thrs_fan_boost,
NOUVEAU_THERM_THRS_FANBOOST);
intr &= ~0x008;
}

/* THRS_2 : critical */
if (intr & 0x010) {
nv50_therm_threshold_hyst_emulation(therm, 0x204c0, 22,
&sensor->thrs_critical,
NOUVEAU_THERM_THRS_CRITICAL);
intr &= ~0x010;
}

if (intr)
nv_error(therm, "unhandled intr 0x%08x\n", intr);

/* ACK everything */
nv_wr32(therm, 0x20100, 0xffffffff);
nv_wr32(therm, 0x1100, 0x10000); /* PBUS */

spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
}

static int
nv50_therm_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
Expand All @@ -278,22 +143,8 @@ nv50_therm_ctor(struct nouveau_object *parent,
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 = nv50_therm_program_alarms;
nv_subdev(priv)->intr = nv50_therm_intr;

/* init the thresholds */
nouveau_therm_sensor_set_threshold_state(&priv->base.base,
NOUVEAU_THERM_THRS_SHUTDOWN,
NOUVEAU_THERM_THRS_LOWER);
nouveau_therm_sensor_set_threshold_state(&priv->base.base,
NOUVEAU_THERM_THRS_FANBOOST,
NOUVEAU_THERM_THRS_LOWER);
nouveau_therm_sensor_set_threshold_state(&priv->base.base,
NOUVEAU_THERM_THRS_CRITICAL,
NOUVEAU_THERM_THRS_LOWER);
nouveau_therm_sensor_set_threshold_state(&priv->base.base,
NOUVEAU_THERM_THRS_DOWNCLOCK,
NOUVEAU_THERM_THRS_LOWER);
priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling;
nv_subdev(priv)->intr = nv40_therm_intr;

return nouveau_therm_preinit(&priv->base.base);
}
Expand Down
Loading

0 comments on commit 2f45736

Please sign in to comment.