[Nouveau] [PATCH 2/3] therm: make sure the temperature settings are sane on nv84+

Martin Peres
Sun, 24 Aug 2014 21:15:10 -0000

One of my nv92 has a calibrated internal sensor but it displays 0?C
as the default values use sw calibration values to force the temperature
to 0.

Since we cannot read the temperature from the adt7473 present on this board,
let's re-enable the internal reading!

Signed-off-by: Martin Peres <martin.peres at free.fr>
---
 nvkm/subdev/therm/nv84.c | 31 ++++++++++++++++++++++++++++++-
 nvkm/subdev/therm/nva3.c |  2 ++
 nvkm/subdev/therm/nvd0.c |  2 ++
 nvkm/subdev/therm/priv.h |  1 +
 4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/nvkm/subdev/therm/nv84.c b/nvkm/subdev/therm/nv84.c
index 1d15c52..38b16d9 100644
--- a/nvkm/subdev/therm/nv84.c
+++ b/nvkm/subdev/therm/nv84.c
@@ -24,6 +24,7 @@
  */

 #include "priv.h"
+#include <subdev/fuse.h>

 struct nv84_therm_priv {
 	struct nouveau_therm_priv base;
@@ -35,6 +36,19 @@ nv84_temp_get(struct nouveau_therm *therm)
 	return nv_rd32(therm, 0x20400);
 }

+void
+nv84_sensor_setup(struct nouveau_therm *therm)
+{
+	struct nouveau_fuse *fuse = nouveau_fuse(therm);
+
+	/* 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);
+		mdelay(20); /* wait for the temperature to stabilize */
+	}
+}
+
 static void
 nv84_therm_program_alarms(struct nouveau_therm *therm)
 {
@@ -171,6 +185,21 @@ nv84_therm_intr(struct nouveau_subdev *subdev)
 }

 static int
+nv84_therm_init(struct nouveau_object *object)
+{
+	struct nv84_therm_priv *priv = (void *)object;
+	int ret;
+
+	ret = nouveau_therm_init(&priv->base.base);
+	if (ret)
+		return ret;
+
+	nv84_sensor_setup(&priv->base.base);
+
+	return 0;
+}
+
+static int
 nv84_therm_ctor(struct nouveau_object *parent,
 		struct nouveau_object *engine,
 		struct nouveau_oclass *oclass, void *data, u32 size,
@@ -228,7 +257,7 @@ nv84_therm_oclass = {
 	.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nv84_therm_ctor,
 		.dtor = _nouveau_therm_dtor,
-		.init = _nouveau_therm_init,
+		.init = nv84_therm_init,
 		.fini = nv84_therm_fini,
 	},
 };
diff --git a/nvkm/subdev/therm/nva3.c b/nvkm/subdev/therm/nva3.c
index 0478b2e..7893357 100644
--- a/nvkm/subdev/therm/nva3.c
+++ b/nvkm/subdev/therm/nva3.c
@@ -51,6 +51,8 @@ nva3_therm_init(struct nouveau_object *object)
 	if (ret)
 		return ret;

+	nv84_sensor_setup(&priv->base.base);
+
 	/* enable fan tach, count revolutions per-second */
 	nv_mask(priv, 0x00e720, 0x00000003, 0x00000002);
 	if (tach->func != DCB_GPIO_UNUSED) {
diff --git a/nvkm/subdev/therm/nvd0.c b/nvkm/subdev/therm/nvd0.c
index 04bb84f..b70f7cc 100644
--- a/nvkm/subdev/therm/nvd0.c
+++ b/nvkm/subdev/therm/nvd0.c
@@ -150,6 +150,8 @@ nvd0_therm_ctor(struct nouveau_object *parent,
 	if (ret)
 		return ret;

+	nv84_sensor_setup(&priv->base.base);
+
 	priv->base.base.pwm_ctrl = nvd0_fan_pwm_ctrl;
 	priv->base.base.pwm_get = nvd0_fan_pwm_get;
 	priv->base.base.pwm_set = nvd0_fan_pwm_set;
diff --git a/nvkm/subdev/therm/priv.h b/nvkm/subdev/therm/priv.h
index 4262d1d..7dba8c2 100644
--- a/nvkm/subdev/therm/priv.h
+++ b/nvkm/subdev/therm/priv.h
@@ -145,6 +145,7 @@ int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32
*);
 int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32);
 int nv50_fan_pwm_clock(struct nouveau_therm *, int);
 int nv84_temp_get(struct nouveau_therm *therm);
+void nv84_sensor_setup(struct nouveau_therm *therm);
 int nv84_therm_fini(struct nouveau_object *object, bool suspend);

 int nva3_therm_fan_sense(struct nouveau_therm *);
--
2.0.0