diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index e052dae614eb..eaeb2b2ee6e9 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -76,6 +76,10 @@ config THERMAL_OF
 	  Say 'Y' here if you need to build thermal infrastructure
 	  based on device tree.
 
+config THERMAL_ACPI
+       depends on ACPI
+       bool
+
 config THERMAL_WRITABLE_TRIPS
 	bool "Enable writable trip points"
 	help
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 2506c6c8ca83..60f0dfa9aae2 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -13,6 +13,7 @@ thermal_sys-$(CONFIG_THERMAL_NETLINK)		+= thermal_netlink.o
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)		+= thermal_hwmon.o
 thermal_sys-$(CONFIG_THERMAL_OF)		+= thermal_of.o
+thermal_sys-$(CONFIG_THERMAL_ACPI)		+= thermal_acpi.o
 
 # governors
 thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)	+= gov_fair_share.o
diff --git a/drivers/thermal/thermal_acpi.c b/drivers/thermal/thermal_acpi.c
new file mode 100644
index 000000000000..c72fca44bc86
--- /dev/null
+++ b/drivers/thermal/thermal_acpi.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2022 Linaro Limited
+ *
+ * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
+ * ACPI thermal configuration
+ */
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/units.h>
+#include <uapi/linux/thermal.h>
+
+#include "thermal_core.h"
+
+/*
+ * An hysteresis value below zero is invalid and we can consider a
+ * value greater than 20°K/°C is invalid too.
+ */
+#define HYST_MIN_DECIK	0
+#define HYST_MAX_DECIK	200
+
+/*
+ * Minimum temperature for full military grade is 218°K (-55°C) and
+ * max temperature is 448°K (175°C). We can consider those values as
+ * the boundaries for the [trips] temperature returned by the
+ * firmware. Any values out of these boundaries may be considered
+ * bogus and we can assume the firmware has no data to provide.
+ */
+#define TEMP_MIN_DECIK	2180
+#define TEMP_MAX_DECIK	4480
+
+static int thermal_acpi_get_temp(struct acpi_device *adev, char *object_name)
+{
+	unsigned long long temp;
+	acpi_status status;
+
+	status = acpi_evaluate_integer(adev->handle, object_name, NULL, &temp);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_debug(adev->handle, "Failed to get temperature object '%s'\n", object_name);
+		return -ENODATA;
+	}
+
+	if (temp < TEMP_MIN_DECIK || temp >= TEMP_MAX_DECIK) {
+		acpi_handle_debug(adev->handle, "Invalid value '%llu' returned by '%s'\n", temp, object_name);
+		return -ENODATA;
+	}
+
+	return (int)temp;
+}
+
+/**
+ * thermal_acpi_active_trip_temp() - Get the specified active trip point
+ * @adev: Thermal zone ACPI device object to get the description from
+ * @trip: Trip point structure to be populated on success
+ * @id: Active cooling level (0 - 9)
+ *
+ * Evaluate the _ACx object for the thermal zone represented by @adev
+ * to obtain the temperature of the active cooling trip point
+ * corresponding to the active cooling level given by @id and
+ * initialize @trip as an active trip point using that temperature
+ * value.
+ *
+ * Return: 
+ * * 0 - Success
+ * * -ENODATA - Failed to get the ACPI object, or the value appears to be inconsistent
+ */
+int thermal_acpi_active_trip_temp(struct acpi_device *adev,
+				  struct thermal_trip *trip, int id)
+{
+	char name[] = "_AC0";
+	int temp;
+
+	if (id < 0 || id > 9)
+		return -EINVAL;
+
+	name[3] += id;
+	
+	temp = thermal_acpi_get_temp(adev, name);
+	if (temp < 0)
+		return temp;
+
+	trip->temperature = deci_kelvin_to_millicelsius(temp);
+	trip->hysteresis = 0;
+	trip->type = THERMAL_TRIP_ACTIVE;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(thermal_acpi_active_trip_temp);
+
+/**
+ * thermal_acpi_passive_trip_temp() - Get the passive trip point
+ * @adev: Thermal zone ACPI device object to get the description from
+ * @trip: Trip point structure to be populated on success
+ *
+ * Evaluate the _PSV object for the thermal zone represented by @adev
+ * to obtain the temperature of the passive cooling trip point and
+ * initialize @trip as a passive trip point using that temperature
+ * value.
+ *
+ * Return:
+ * * 0 - Success
+ * * -ENODATA - Failed to get the ACPI object, or the value appears to be inconsistent
+ */
+int thermal_acpi_passive_trip_temp(struct acpi_device *adev, struct thermal_trip *trip)
+{
+	int temp;
+
+	temp = thermal_acpi_get_temp(adev, "_PSV");
+	if (temp < 0)
+		return temp;
+
+	trip->temperature = deci_kelvin_to_millicelsius(temp);
+	trip->hysteresis = 0;
+	trip->type = THERMAL_TRIP_PASSIVE;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(thermal_acpi_passive_trip_temp);
+
+/**
+ * thermal_acpi_hot_trip_temp() - Get the near critical trip point
+ * @adev: the ACPI device to get the description from
+ * @trip: a &struct thermal_trip to be filled if the function succeed
+ *
+ * Evaluate the _HOT object for the thermal zone represented by @adev
+ * to obtain the temperature of the trip point at which the system is
+ * expected to be put into the S4 sleep state and initialize @trip as
+ * a hot trip point using that temperature value.
+ *
+ * Return:
+ * * 0 - Success
+ * * -ENODATA - Failed to get the ACPI object, or the value appears to be inconsistent
+ */
+int thermal_acpi_hot_trip_temp(struct acpi_device *adev, struct thermal_trip *trip)
+{
+	int temp;
+
+	temp = thermal_acpi_get_temp(adev, "_HOT");
+	if (temp < 0)
+		return temp;
+
+	trip->temperature = deci_kelvin_to_millicelsius(temp);
+	trip->hysteresis = 0;
+	trip->type = THERMAL_TRIP_HOT;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(thermal_acpi_hot_trip_temp);
+
+/**
+ * thermal_acpi_critical_trip_temp() - Get the critical trip point
+ * @adev: the ACPI device to get the description from
+ * @trip: a &struct thermal_trip to be filled if the function succeed
+ *
+ * Evaluate the _CRT object for the thermal zone represented by @adev
+ * to obtain the temperature of the critical cooling trip point and
+ * initialize @trip as a critical trip point using that temperature
+ * value.
+ *
+ * Return:
+ * * 0 - Success
+ * * -ENODATA - Failed to get the ACPI object, or the value appears to be inconsistent
+ */
+int thermal_acpi_critical_trip_temp(struct acpi_device *adev, struct thermal_trip *trip)
+{
+	int temp;
+
+	temp = thermal_acpi_get_temp(adev, "_CRT");
+	if (temp < 0)
+		return temp;
+
+	/*
+	 * The hysteresis value has no sense here because critical
+	 * trip point has no u-turn
+	 */
+	trip->temperature = deci_kelvin_to_millicelsius(temp);
+	trip->hysteresis = 0;
+	trip->type = THERMAL_TRIP_CRITICAL;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(thermal_acpi_critical_trip_temp);
+
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 30353e4b1424..2aee1f0d5fac 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -334,6 +334,13 @@ static inline void devm_thermal_of_zone_unregister(struct device *dev,
 }
 #endif
 
+#ifdef CONFIG_THERMAL_ACPI
+int thermal_acpi_critical_trip_temp(struct acpi_device *adev, struct thermal_trip *trip);
+int thermal_acpi_hot_trip_temp(struct acpi_device *adev, struct thermal_trip *trip);
+int thermal_acpi_passive_trip_temp(struct acpi_device *adev, struct thermal_trip *trip);
+int thermal_acpi_active_trip_temp(struct acpi_device *adev, struct thermal_trip *trip, int id);
+#endif
+
 int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
 			    struct thermal_trip *trip);
 int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
