diff --git a/core/sensor.c b/core/sensor.c
index 2099579cee4c..b109030d8c44 100644
--- a/core/sensor.c
+++ b/core/sensor.c
@@ -19,10 +19,18 @@
 #include <skiboot.h>
 #include <opal.h>
 #include <fsp.h>
+#include <dts.h>
 
 static int64_t opal_sensor_read(uint32_t sensor_hndl, int token,
 		uint32_t *sensor_data)
 {
+	/*
+	 * Dispatch the read to other OPAL components. This is just for
+	 * the core temperature for the moment.
+	 */
+	if (sensor_is_dts(sensor_hndl))
+		return dts_sensor_read(sensor_hndl, sensor_data);
+
 	if (platform.sensor_read)
 		return platform.sensor_read(sensor_hndl, token, sensor_data);
 
diff --git a/hw/Makefile.inc b/hw/Makefile.inc
index 83125beeee7f..f55654a08792 100644
--- a/hw/Makefile.inc
+++ b/hw/Makefile.inc
@@ -4,7 +4,7 @@ SUBDIRS += hw
 HW_OBJS  = xscom.o chiptod.o gx.o cec.o lpc.o lpc-uart.o psi.o
 HW_OBJS += homer.o slw.o occ.o nx.o fsi-master.o centaur.o
 HW_OBJS += p7ioc.o p7ioc-inits.o p7ioc-phb.o p5ioc2.o p5ioc2-phb.o
-HW_OBJS += phb3.o sfc-ctrl.o fake-rtc.o bt.o p8-i2c.o
+HW_OBJS += phb3.o sfc-ctrl.o fake-rtc.o bt.o p8-i2c.o dts.o
 HW=hw/built-in.o
 
 include $(SRC)/hw/fsp/Makefile.inc
diff --git a/hw/dts.c b/hw/dts.c
new file mode 100644
index 000000000000..c94e879b192a
--- /dev/null
+++ b/hw/dts.c
@@ -0,0 +1,166 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <xscom.h>
+#include <chip.h>
+#include <sensor.h>
+#include <dts.h>
+
+
+struct dts_core_temp {
+	uint8_t		valid;
+	uint8_t		trip;
+	int16_t		temp;
+};
+
+
+/* Therm mac result masking for DTS (result(0:15)
+ *  0:3   - 0x0
+ *  4:11  - Temperature in degrees C
+ *  12:13 - trip bits: 00 - no trip; 01 - warning; 10 - critical; 11 - fatal
+ *  14    - spare
+ *  15    - valid
+ */
+static void dts_decode_one_dts(uint16_t dts, struct dts_core_temp *ts)
+{
+	/*
+	 * The value is both signed and unsigned :-) 0xff could be
+	 * either 255C or -1C, so for now we treat this as unsigned
+	 * which is sufficient for our purpose. We could try to be
+	 * a bit smarter and treat it as signed for values between
+	 * -10 and 0 and unsigned to 239 or something like that...
+	 */
+	ts->valid = dts & 1;
+	if (ts->valid) {
+		ts->temp = (dts >> 4) & 0xff;
+		ts->trip = (dts >> 2) & 0x3;
+	} else {
+		ts->temp = 0;
+		ts->trip = 0;
+	}
+}
+
+/* Different sensor locations */
+#define P8_CT_ZONE_LSU	0
+#define P8_CT_ZONE_ISU	1
+#define P8_CT_ZONE_FXU	2
+#define P8_CT_ZONE_L3C	3
+#define P8_CT_ZONES	4
+
+/*
+ * Returns the temperature as the max of all 4 zones and a global trip
+ * attribute.
+ */
+static int dts_read_core_temp(uint32_t pir, struct dts_core_temp *ts)
+{
+	int32_t chip_id = pir_to_chip_id(pir);
+	int32_t core = pir_to_core_id(pir);
+	uint64_t dts0, dts1;
+	struct dts_core_temp temps[P8_CT_ZONES];
+	int i;
+	int rc;
+
+	rc = xscom_read(chip_id, XSCOM_ADDR_P8_EX(core, EX_THERM_DTS_RESULT0),
+			&dts0);
+	if (rc)
+		return rc;
+
+	rc = xscom_read(chip_id, XSCOM_ADDR_P8_EX(core, EX_THERM_DTS_RESULT1),
+			&dts1);
+	if (rc)
+		return rc;
+
+	dts_decode_one_dts(dts0 >> 48, &temps[P8_CT_ZONE_LSU]);
+	dts_decode_one_dts(dts0 >> 32, &temps[P8_CT_ZONE_ISU]);
+	dts_decode_one_dts(dts0 >> 16, &temps[P8_CT_ZONE_FXU]);
+	dts_decode_one_dts(dts1 >> 48, &temps[P8_CT_ZONE_L3C]);
+
+	for (i = 0; i < P8_CT_ZONES; i++) {
+		int16_t t = temps[i].temp;
+
+		if (!temps[i].valid)
+			continue;
+
+		/* keep the max temperature of all 4 sensors */
+		if (t > ts->temp)
+			ts->temp = t;
+
+		ts->valid++;
+		ts->trip |= temps[i].trip;
+	}
+
+	prlog(PR_TRACE, "DTS: Chip %x Core %x temp:%dC trip:%x\n",
+	      chip_id, core, ts->temp, ts->trip);
+	return 0;
+}
+
+/*
+ * DTS sensor class ids. Only one for the moment: the core
+ * temperature.
+ */
+enum sensor_dts_class {
+	SENSOR_DTS_CORE_TEMP,
+	/* To be continued */
+};
+
+/*
+ * Attributes for the core temperature sensor
+ */
+enum {
+	SENSOR_DTS_ATTR_CORE_TEMP_MAX,
+	SENSOR_DTS_ATTR_CORE_TEMP_TRIP
+};
+
+static int64_t dts_sensor_read_core_temp(uint32_t sensor_hndl,
+	uint32_t *sensor_data)
+{
+	uint8_t	attr = sensor_get_attr(sensor_hndl);
+	uint32_t pir = sensor_get_rid(sensor_hndl);
+	struct dts_core_temp ts;
+	int64_t rc;
+
+	if (attr > SENSOR_DTS_ATTR_CORE_TEMP_TRIP)
+		return OPAL_PARAMETER;
+
+	memset(&ts, 0, sizeof(struct dts_core_temp));
+
+	rc = dts_read_core_temp(pir, &ts);
+	if (rc)
+		return rc;
+
+	if (attr == SENSOR_DTS_ATTR_CORE_TEMP_MAX)
+		*sensor_data = ts.temp;
+	else if (attr == SENSOR_DTS_ATTR_CORE_TEMP_TRIP)
+		*sensor_data = ts.trip;
+
+	return 0;
+}
+
+int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data)
+{
+	int64_t rc;
+
+	switch (sensor_get_frc(sensor_hndl) & ~SENSOR_DTS) {
+	case SENSOR_DTS_CORE_TEMP:
+		rc = dts_sensor_read_core_temp(sensor_hndl, sensor_data);
+		break;
+	default:
+		rc = OPAL_PARAMETER;
+		break;
+	}
+
+	return rc;
+}
diff --git a/include/dts.h b/include/dts.h
new file mode 100644
index 000000000000..18933909ee08
--- /dev/null
+++ b/include/dts.h
@@ -0,0 +1,24 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DTS_H
+#define __DTS_H
+
+#include <stdint.h>
+
+extern int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data);
+
+#endif /* __DTS_H */
diff --git a/include/sensor.h b/include/sensor.h
index 5acc740dd459..1ed156a3398f 100644
--- a/include/sensor.h
+++ b/include/sensor.h
@@ -46,7 +46,9 @@
  * the appropriate component. FSP is the initial family.
  */
 #define SENSOR_FSP 0x0
+#define SENSOR_DTS 0x80
 
+#define sensor_is_dts(handler)	(sensor_get_frc(handler) & SENSOR_DTS)
 
 extern void sensor_init(void);
 
diff --git a/include/xscom.h b/include/xscom.h
index 5eed85f50753..e321c4535b9b 100644
--- a/include/xscom.h
+++ b/include/xscom.h
@@ -154,6 +154,14 @@
 #define EX_PM_IDLE_ST_HIST_PM_STATE_MASK	PPC_BITMASK(0, 2)
 #define EX_PM_IDLE_ST_HIST_PM_STATE_LSH		PPC_BITLSHIFT(2)
 
+/* Per core Digital Thermal Sensors */
+#define EX_THERM_DTS_RESULT0	0x10050000
+#define EX_THERM_DTS_RESULT1	0x10050001
+
+/* Per core Digital Thermal Sensors control registers */
+#define EX_THERM_MODE_REG	0x1005000F
+#define EX_THERM_CONTROL_REG	0x10050012
+#define EX_THERM_ERR_STATUS_REG	0x10050013
 
 /*
  * Error handling:
