diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c
index 305baba..ae7a8df 100644
--- a/drivers/raw/ifpga/base/opae_intel_max10.c
+++ b/drivers/raw/ifpga/base/opae_intel_max10.c
@@ -7,6 +7,9 @@
 
 static struct intel_max10_device *g_max10;
 
+struct opae_sensor_list opae_sensor_list =
+	TAILQ_HEAD_INITIALIZER(opae_sensor_list);
+
 int max10_reg_read(unsigned int reg, unsigned int *val)
 {
 	if (!g_max10)
@@ -195,6 +198,277 @@ static int init_max10_device_table(struct intel_max10_device *max10)
 	return ret;
 }
 
+static u64 fdt_get_number(const fdt32_t *cell, int size)
+{
+	u64 r = 0;
+
+	while (size--)
+		r = (r << 32) | fdt32_to_cpu(*cell++);
+
+	return r;
+}
+
+static int fdt_get_reg(const void *fdt, int node, unsigned int idx,
+		u64 *start, u64 *size)
+{
+	const fdt32_t *prop, *end;
+	int na = 0, ns = 0, len = 0, parent;
+
+	parent = fdt_parent_offset(fdt, node);
+	if (parent < 0)
+		return parent;
+
+	prop = fdt_getprop(fdt, parent, "#address-cells", NULL);
+	na = prop ? fdt32_to_cpu(*prop) : 2;
+
+	prop = fdt_getprop(fdt, parent, "#size-cells", NULL);
+	ns = prop ? fdt32_to_cpu(*prop) : 2;
+
+	prop = fdt_getprop(fdt, node, "reg", &len);
+	if (!prop)
+		return -FDT_ERR_NOTFOUND;
+
+	end = prop + len/sizeof(*prop);
+	prop = prop + (na + ns) * idx;
+
+	if (prop + na + ns > end)
+		return -FDT_ERR_NOTFOUND;
+
+	*start = fdt_get_number(prop, na);
+	*size = fdt_get_number(prop + na, ns);
+
+	return 0;
+}
+
+static int __fdt_stringlist_search(const void *fdt, int offset,
+		const char *prop, const char *string)
+{
+	int length, len, index = 0;
+	const char *list, *end;
+
+	list = fdt_getprop(fdt, offset, prop, &length);
+	if (!list)
+		return length;
+
+	len = strlen(string) + 1;
+	end = list + length;
+
+	while (list < end) {
+		length = strnlen(list, end - list) + 1;
+
+		if (list + length > end)
+			return -FDT_ERR_BADVALUE;
+
+		if (length == len && memcmp(list, string, length) == 0)
+			return index;
+
+		list += length;
+		index++;
+	}
+
+	return -FDT_ERR_NOTFOUND;
+}
+
+static int fdt_get_named_reg(const void *fdt, int node, const char *name,
+		u64 *start, u64 *size)
+{
+	int idx;
+
+	idx = __fdt_stringlist_search(fdt, node, "reg-names", name);
+	if (idx < 0)
+		return idx;
+
+	return fdt_get_reg(fdt, node, idx, start, size);
+}
+
+static void max10_sensor_uinit(void)
+{
+	struct opae_sensor_info *info;
+
+	TAILQ_FOREACH(info, &opae_sensor_list, node) {
+		TAILQ_REMOVE(&opae_sensor_list, info, node);
+		opae_free(info);
+	}
+}
+
+static bool sensor_reg_valid(struct sensor_reg *reg)
+{
+	return !!reg->size;
+}
+
+static int max10_add_sensor(struct raw_sensor_info *info,
+		struct opae_sensor_info *sensor)
+{
+	int i;
+	int ret = 0;
+	unsigned int val;
+
+	if (!info || !sensor)
+		return -ENODEV;
+
+	sensor->id = info->id;
+	sensor->name = info->name;
+	sensor->type = info->type;
+	sensor->multiplier = info->multiplier;
+
+	for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++) {
+		if (!sensor_reg_valid(&info->regs[i]))
+			continue;
+
+		ret = max10_reg_read(info->regs[i].regoff, &val);
+		if (ret)
+			break;
+
+		if (val == 0xdeadbeef)
+			continue;
+
+		val *= info->multiplier;
+
+		switch (i) {
+		case SENSOR_REG_VALUE:
+			sensor->value_reg = info->regs[i].regoff;
+			sensor->flags |= OPAE_SENSOR_VALID;
+			break;
+		case SENSOR_REG_HIGH_WARN:
+			sensor->high_warn = val;
+			sensor->flags |= OPAE_SENSOR_HIGH_WARN_VALID;
+			break;
+		case SENSOR_REG_HIGH_FATAL:
+			sensor->high_fatal = val;
+			sensor->flags |= OPAE_SENSOR_HIGH_FATAL_VALID;
+			break;
+		case SENSOR_REG_LOW_WARN:
+			sensor->low_warn = val;
+			sensor->flags |= OPAE_SENSOR_LOW_WARN_VALID;
+			break;
+		case SENSOR_REG_LOW_FATAL:
+			sensor->low_fatal = val;
+			sensor->flags |= OPAE_SENSOR_LOW_FATAL_VALID;
+			break;
+		case SENSOR_REG_HYSTERESIS:
+			sensor->hysteresis = val;
+			sensor->flags |= OPAE_SENSOR_HYSTERESIS_VALID;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int max10_sensor_init(struct intel_max10_device *dev)
+{
+	int i, ret = 0, offset = 0;
+	const fdt32_t *num;
+	const char *ptr;
+	u64 start, size;
+	struct raw_sensor_info *raw;
+	struct opae_sensor_info *sensor;
+	char *fdt_root = dev->fdt_root;
+
+	if (!fdt_root) {
+		dev_debug(dev, "skip sensor init as not find Device Tree\n");
+		return 0;
+	}
+
+	fdt_for_each_subnode(offset, fdt_root, 0) {
+		ptr = fdt_get_name(fdt_root, offset, NULL);
+		if (!ptr) {
+			dev_err(dev, "failed to fdt get name\n");
+			continue;
+		}
+
+		if (!strstr(ptr, "sensor")) {
+			dev_debug(dev, "%s is not a sensor node\n", ptr);
+			continue;
+		}
+
+		dev_debug(dev, "found sensor node %s\n", ptr);
+
+		raw = (struct raw_sensor_info *)opae_zmalloc(sizeof(*raw));
+		if (!raw) {
+			ret = -ENOMEM;
+			goto free_sensor;
+		}
+
+		raw->name = fdt_getprop(fdt_root, offset, "sensor_name", NULL);
+		if (!raw->name) {
+			ret = -EINVAL;
+			goto free_sensor;
+		}
+
+		raw->type = fdt_getprop(fdt_root, offset, "type", NULL);
+		if (!raw->type) {
+			ret = -EINVAL;
+			goto free_sensor;
+		}
+
+		for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++) {
+			ret = fdt_get_named_reg(fdt_root, offset,
+					sensor_reg_name[i], &start,
+					&size);
+			if (ret) {
+				dev_debug(dev, "no found %d: sensor node %s, %s\n",
+						ret, ptr, sensor_reg_name[i]);
+				if (i == SENSOR_REG_VALUE) {
+					ret = -EINVAL;
+					goto free_sensor;
+				}
+
+				continue;
+			}
+
+			raw->regs[i].regoff = start;
+			raw->regs[i].size = size;
+		}
+
+		num = fdt_getprop(fdt_root, offset, "id", NULL);
+		if (!num) {
+			ret = -EINVAL;
+			goto free_sensor;
+		}
+
+		raw->id = fdt32_to_cpu(*num);
+		num = fdt_getprop(fdt_root, offset, "multiplier", NULL);
+		raw->multiplier = num ? fdt32_to_cpu(*num) : 1;
+
+		dev_info(dev, "found sensor from DTB: %s: %s: %u: %u\n",
+				raw->name, raw->type,
+				raw->id, raw->multiplier);
+
+		for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++)
+			dev_debug(dev, "sensor reg[%d]: %x: %zu\n",
+					i, raw->regs[i].regoff,
+					raw->regs[i].size);
+
+		sensor = opae_zmalloc(sizeof(*sensor));
+		if (!sensor) {
+			ret = -EINVAL;
+			goto free_sensor;
+		}
+
+		if (max10_add_sensor(raw, sensor)) {
+			ret = -EINVAL;
+			opae_free(sensor);
+			goto free_sensor;
+		}
+
+		if (sensor->flags & OPAE_SENSOR_VALID)
+			TAILQ_INSERT_TAIL(&opae_sensor_list, sensor, node);
+		else
+			opae_free(sensor);
+
+		opae_free(raw);
+	}
+
+	return 0;
+
+free_sensor:
+	if (raw)
+		opae_free(raw);
+	max10_sensor_uinit();
+	return ret;
+}
+
 struct intel_max10_device *
 intel_max10_device_probe(struct altera_spi_device *spi,
 		int chipselect)
@@ -235,6 +509,9 @@ struct intel_max10_device *
 	}
 	dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory");
 
+
+	max10_sensor_init(dev);
+
 	return dev;
 
 spi_tran_fail:
@@ -253,6 +530,8 @@ int intel_max10_device_remove(struct intel_max10_device *dev)
 	if (!dev)
 		return 0;
 
+	max10_sensor_uinit();
+
 	if (dev->spi_tran_dev)
 		spi_transaction_remove(dev->spi_tran_dev);
 
diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h b/drivers/raw/ifpga/base/opae_intel_max10.h
index a52b63e..90bf098 100644
--- a/drivers/raw/ifpga/base/opae_intel_max10.h
+++ b/drivers/raw/ifpga/base/opae_intel_max10.h
@@ -103,4 +103,60 @@ struct intel_max10_device *
 		int chipselect);
 int intel_max10_device_remove(struct intel_max10_device *dev);
 
+/** List of opae sensors */
+TAILQ_HEAD(opae_sensor_list, opae_sensor_info);
+
+#define SENSOR_REG_VALUE 0x0
+#define SENSOR_REG_HIGH_WARN 0x1
+#define SENSOR_REG_HIGH_FATAL 0x2
+#define SENSOR_REG_LOW_WARN 0x3
+#define SENSOR_REG_LOW_FATAL 0x4
+#define SENSOR_REG_HYSTERESIS 0x5
+#define SENSOR_REG_MAX 0x6
+
+static const char * const sensor_reg_name[] = {
+	"value",
+	"high_warn",
+	"high_fatal",
+	"low_warn",
+	"low_fatal",
+	"hysteresis",
+};
+
+struct sensor_reg {
+	unsigned int regoff;
+	size_t size;
+};
+
+struct raw_sensor_info {
+	const char *name;
+	const char *type;
+	unsigned int id;
+	unsigned int multiplier;
+	struct sensor_reg regs[SENSOR_REG_MAX];
+};
+
+#define OPAE_SENSOR_VALID 0x1
+#define OPAE_SENSOR_HIGH_WARN_VALID 0x2
+#define OPAE_SENSOR_HIGH_FATAL_VALID 0x4
+#define OPAE_SENSOR_LOW_WARN_VALID 0x8
+#define OPAE_SENSOR_LOW_FATAL_VALID 0x10
+#define OPAE_SENSOR_HYSTERESIS_VALID 0x20
+
+struct opae_sensor_info {
+	TAILQ_ENTRY(opae_sensor_info) node;
+	const char *name;
+	const char *type;
+	unsigned int id;
+	unsigned int high_fatal;
+	unsigned int high_warn;
+	unsigned int low_fatal;
+	unsigned int low_warn;
+	unsigned int hysteresis;
+	unsigned int multiplier;
+	unsigned int flags;
+	unsigned int value;
+	unsigned int value_reg;
+};
+
 #endif
