aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCédric Le Goater <clg@fr.ibm.com>2015-03-09 21:56:19 +0100
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-03-24 18:22:55 +1100
commit3c0627cb13b40f76a2339c021ed7581fa6293fdf (patch)
treea8e94d08540dccd77fa8d0450de3e492e17343b9
parenta5413878280a0cccd58d76802beffcce95f15c89 (diff)
downloadskiboot-3c0627cb13b40f76a2339c021ed7581fa6293fdf.zip
skiboot-3c0627cb13b40f76a2339c021ed7581fa6293fdf.tar.gz
skiboot-3c0627cb13b40f76a2339c021ed7581fa6293fdf.tar.bz2
dts: add memory buffers temperature sensors
The memory buffer chips (Centaur) have DTS very similar to the ones we find on the cores. Only available on open power machines for the moment. Signed-off-by: Cédric Le Goater <clg@fr.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--doc/device-tree/ibm,opal/sensors.txt26
-rw-r--r--hw/dts.c96
2 files changed, 122 insertions, 0 deletions
diff --git a/doc/device-tree/ibm,opal/sensors.txt b/doc/device-tree/ibm,opal/sensors.txt
index 81aeff8..80a6d81 100644
--- a/doc/device-tree/ibm,opal/sensors.txt
+++ b/doc/device-tree/ibm,opal/sensors.txt
@@ -64,4 +64,30 @@ ibm,opal/sensors/ {
ibm,pir = <0x20>;
label = "Core";
};
+
+ /*
+ * Centaur temperatures (DTS) nodes. Open Power only.
+ *
+ * We use the PIR of the core as a resource identifier.
+ */
+ mem-temp@1 {
+ compatible = "ibm,opal-sensor";
+ name = "mem-temp";
+ sensor-type = "temp";
+
+ /* Status bits :
+ *
+ * 0x0003 FATAL
+ * 0x0002 CRITICAL
+ * 0x0001 WARNING
+ */
+ sensor-data = <0x00810001>;
+
+ /*
+ * These are extra properties to help Linux output.
+ */
+ ibm,chip-id = <0x80000001>;
+ label = "Centaur";
+ };
+
};
diff --git a/hw/dts.c b/hw/dts.c
index de8a38b..68c77a0 100644
--- a/hw/dts.c
+++ b/hw/dts.c
@@ -30,6 +30,14 @@
#define EX_THERM_CONTROL_REG 0x10050012
#define EX_THERM_ERR_STATUS_REG 0x10050013
+/* Per memory controller Digital Thermal Sensors */
+#define THERM_MEM_DTS_RESULT0 0x2050000
+
+/* Per memory controller Digital Thermal Sensors control registers */
+#define THERM_MEM_MODE_REG 0x205000F
+#define THERM_MEM_CONTROL_REG 0x2050012
+#define THERM_MEM_ERR_STATUS_REG 0x2050013
+
struct dts {
uint8_t valid;
uint8_t trip;
@@ -123,12 +131,58 @@ static int dts_read_core_temp(uint32_t pir, struct dts *dts)
return 0;
}
+
+/* Different sensor locations */
+#define P8_MEM_DTS0 0
+#define P8_MEM_DTS1 1
+#define P8_MEM_ZONES 2
+
+static int dts_read_mem_temp(uint32_t chip_id, struct dts *dts)
+{
+ uint64_t dts0;
+ struct dts temps[P8_MEM_ZONES];
+ int i;
+ int rc;
+
+ rc = xscom_read(chip_id, THERM_MEM_DTS_RESULT0, &dts0);
+ if (rc)
+ return rc;
+
+ dts_decode_one_dts(dts0 >> 48, &temps[P8_MEM_DTS0]);
+ dts_decode_one_dts(dts0 >> 32, &temps[P8_MEM_DTS1]);
+
+ for (i = 0; i < P8_MEM_ZONES; i++) {
+ int16_t t = temps[i].temp;
+
+ if (!temps[i].valid)
+ continue;
+
+ /* keep the max temperature of all 4 sensors */
+ if (t > dts->temp)
+ dts->temp = t;
+
+ dts->valid++;
+ dts->trip |= temps[i].trip;
+ }
+
+ prlog(PR_TRACE, "DTS: Chip %x temp:%dC trip:%x\n",
+ chip_id, dts->temp, dts->trip);
+
+ /*
+ * FIXME: The trip bits are always set ?! Just discard
+ * them for the moment until we understand why.
+ */
+ dts->trip = 0;
+ return 0;
+}
+
/*
* DTS sensor class ids. Only one for the moment: the core
* temperature.
*/
enum sensor_dts_class {
SENSOR_DTS_CORE_TEMP,
+ SENSOR_DTS_MEM_TEMP,
/* To be continued */
};
@@ -156,6 +210,14 @@ int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data)
case SENSOR_DTS_CORE_TEMP:
rc = dts_read_core_temp(rid, &dts);
break;
+ case SENSOR_DTS_MEM_TEMP:
+ /*
+ * restore centaur chip id which was truncated to fit
+ * in the sensor handler
+ */
+ rid |= 0x80000000;
+ rc = dts_read_mem_temp(rid, &dts);
+ break;
default:
rc = OPAL_PARAMETER;
break;
@@ -176,6 +238,7 @@ bool dts_sensor_create_nodes(struct dt_node *sensors)
uint8_t sensor_class = SENSOR_DTS_CORE_TEMP|SENSOR_DTS;
struct proc_chip *chip;
+ struct dt_node *cn;
char name[64];
/* build the device tree nodes :
@@ -209,5 +272,38 @@ bool dts_sensor_create_nodes(struct dt_node *sensors)
}
}
+ sensor_class = SENSOR_DTS_MEM_TEMP|SENSOR_DTS;
+
+ /*
+ * sensors/mem-temp@chip for Centaurs
+ */
+ dt_for_each_compatible(dt_root, cn, "ibm,centaur") {
+ uint32_t chip_id;
+ struct dt_node *node;
+ uint32_t handler;
+
+ chip_id = dt_prop_get_u32(cn, "ibm,chip-id");
+
+ snprintf(name, sizeof(name), "mem-temp@%x", chip_id);
+
+ /*
+ * We only have two bytes for the resource
+ * identifier. Let's trunctate the centaur chip id
+ */
+ handler = sensor_make_handler(sensor_class,
+ chip_id & 0xffff, SENSOR_DTS_ATTR_TEMP_MAX);
+ node = dt_new(sensors, name);
+ dt_add_property_string(node, "compatible",
+ "ibm,opal-sensor");
+ dt_add_property_cells(node, "sensor-data", handler);
+
+ handler = sensor_make_handler(sensor_class,
+ chip_id, SENSOR_DTS_ATTR_TEMP_TRIP);
+ dt_add_property_cells(node, "sensor-status", handler);
+ dt_add_property_string(node, "sensor-type", "temp");
+ dt_add_property_cells(node, "ibm,chip-id", chip_id);
+ dt_add_property_string(node, "label", "Centaur");
+ }
+
return true;
}