diff mbox series

[meta-oe] thermald: backport support for non-Intel platforms

Message ID 20260311062343.428910-1-priyansh.jain@oss.qualcomm.com
State New
Headers show
Series [meta-oe] thermald: backport support for non-Intel platforms | expand

Commit Message

Priyansh Jain March 11, 2026, 6:23 a.m. UTC
Backport three upstream patches that refactor thermald to support
non-Intel architectures, including ARM platforms. These commits were
merged upstream after the 2.5.11 release and are required to enable
correct thermal management on non-x86 SoCs.

Also update COMPATIBLE_HOST to allow building thermald on both Intel
and ARM hosts.

Upstream patches:
 - Backport from commit 4cf42fc89ccdbcecdcd30b32a7ca8040be55c253
 - Backport from commit 857fbdf3e9079cec04bfa5fe7a93a432485b5cab
 - Backport from commit 1931a12e7e44b6b85a02a5d8158829eff4b9cc92

Signed-off-by: Priyansh Jain <priyansh.jain@oss.qualcomm.com>
---
 ...l-specific-logic-into-separate-files.patch | 829 ++++++++++++++++++
 ...ke-parser_init-before-platform_match.patch |  41 +
 ...nd-and-enable-ARM-platform-detection.patch | 234 +++++
 .../recipes-bsp/thermald/thermald_2.5.11.bb   |   5 +-
 4 files changed, 1108 insertions(+), 1 deletion(-)
 create mode 100644 meta-oe/recipes-bsp/thermald/thermald/0001-Refactor-Intel-specific-logic-into-separate-files.patch
 create mode 100644 meta-oe/recipes-bsp/thermald/thermald/0002-Invoke-parser_init-before-platform_match.patch
 create mode 100644 meta-oe/recipes-bsp/thermald/thermald/0003-Add-ARM-backend-and-enable-ARM-platform-detection.patch
diff mbox series

Patch

diff --git a/meta-oe/recipes-bsp/thermald/thermald/0001-Refactor-Intel-specific-logic-into-separate-files.patch b/meta-oe/recipes-bsp/thermald/thermald/0001-Refactor-Intel-specific-logic-into-separate-files.patch
new file mode 100644
index 0000000000..86f6874daf
--- /dev/null
+++ b/meta-oe/recipes-bsp/thermald/thermald/0001-Refactor-Intel-specific-logic-into-separate-files.patch
@@ -0,0 +1,829 @@ 
+From 4cf42fc89ccdbcecdcd30b32a7ca8040be55c253 Mon Sep 17 00:00:00 2001
+From: Priyansh Jain <priyansh.jain@oss.qualcomm.com>
+Date: Tue, 27 Jan 2026 14:58:05 +0530
+Subject: [PATCH 1/3] Refactor Intel-specific logic into separate files
+
+Thermald currently only supports x86 platforms but is a very useful tool for
+controlling user-space thermal policy on a wide range of systems. As more
+SoCs and architectures adopt user-space driven thermal management models,
+the limitation to x86-only backends prevents thermald from being used on
+non-x86 platforms.
+
+This series adds support for non-x86 platforms by first refactoring all
+x86-specific logic into a dedicated backend. This separation enables a clean
+and modular structure where additional platform backends can be introduced
+without impacting the existing Intel implementation. Once the backend
+abstraction is in place, subsequent patches add support for ARM backends
+and integrate them into the new platform detection logic.
+
+Suggested-by: Amit Kucheria <amit.kucheria@oss.qualcomm.com>
+Signed-off-by: Priyansh Jain <priyansh.jain@oss.qualcomm.com>
+
+Upstream-Status: Backport [from commit 4cf42fc89ccdbcecdcd30b32a7ca8040be55c253]
+---
+ Android.mk                 |   4 +-
+ Makefile.am                |   5 +-
+ src/thd_engine.cpp         | 125 +++----------------
+ src/thd_engine.h           |   6 -
+ src/thd_engine_default.cpp |  79 ++----------
+ src/thd_platform.cpp       | 109 +++++++++++++++++
+ src/thd_platform.h         |  58 +++++++++
+ src/thd_platform_intel.cpp | 238 +++++++++++++++++++++++++++++++++++++
+ src/thd_platform_intel.h   |  38 ++++++
+ 9 files changed, 476 insertions(+), 186 deletions(-)
+ create mode 100644 src/thd_platform.cpp
+ create mode 100644 src/thd_platform.h
+ create mode 100644 src/thd_platform_intel.cpp
+ create mode 100644 src/thd_platform_intel.h
+
+diff --git a/Android.mk b/Android.mk
+index 0b279f4..c14fa4a 100644
+--- a/Android.mk
++++ b/Android.mk
+@@ -43,7 +43,9 @@ LOCAL_SRC_FILES := \
+ 		src/thd_engine_adaptive.cpp \
+ 		src/thd_lzma_dec.cpp \
+ 		src/LzmaDec.c \
+-		src/thd_gddv.cpp
++		src/thd_gddv.cpp \
++		src/thd_platform.cpp \
++		src/thd_platform_intel.cpp
+ 
+ LOCAL_C_INCLUDES += external/libxml2/include
+ 
+diff --git a/Makefile.am b/Makefile.am
+index dbf86db..2e76187 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -75,8 +75,9 @@ thermald_SOURCES = \
+ 	src/thd_gddv.cpp \
+ 	thermald-resource.c \
+ 	src/thd_lzma_dec.cpp \
+-	src/LzmaDec.c
+-
++	src/LzmaDec.c \
++	src/thd_platform.cpp \
++	src/thd_platform_intel.cpp
+ 
+ man5_MANS = man/thermal-conf.xml.5
+ man8_MANS = man/thermald.8
+diff --git a/src/thd_engine.cpp b/src/thd_engine.cpp
+index d2028c6..319f50b 100644
+--- a/src/thd_engine.cpp
++++ b/src/thd_engine.cpp
+@@ -35,7 +35,6 @@
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <sys/utsname.h>
+-#include <cpuid.h>
+ #include <locale>
+ #include <memory>
+ #include "thd_engine.h"
+@@ -44,6 +43,8 @@
+ #include "thd_zone_dynamic.h"
+ #include "thd_cdev_gen_sysfs.h"
+ #include "thd_int3400.h"
++#include "thd_platform.h"
++#include "thd_platform_intel.h"
+ 
+ static void *cthd_engine_thread(void *arg);
+ 
+@@ -53,11 +54,10 @@ cthd_engine::cthd_engine(std::string _uuid) :
+ 				false), adaptive_mode(false), poll_timeout_msec(-1), wakeup_fd(
+ 				-1), uevent_fd(-1), control_mode(COMPLEMENTRY), write_pipe_fd(
+ 				0), preference(0), status(true), thz_last_uevent_time(0), thz_last_temp_ind_time(
+-				0), thz_last_update_event_time(0), terminate(false), genuine_intel(
+-				0), has_invariant_tsc(0), has_aperf(0), proc_list_matched(
+-				false), poll_interval_sec(0), poll_sensor_mask(0), fast_poll_sensor_mask(
+-				0), saved_poll_interval(0), poll_fd_cnt(0), rt_kernel(false), parser_init_done(
+-				false) {
++				0), thz_last_update_event_time(0), terminate(false), has_invariant_tsc(0),
++				has_aperf(0), proc_list_matched(false), poll_interval_sec(0), poll_sensor_mask(0),
++				fast_poll_sensor_mask(0), saved_poll_interval(0), poll_fd_cnt(0), rt_kernel(false),
++				parser_init_done(false) {
+ 	thd_engine = pthread_t();
+ 	thd_attr = pthread_attr_t();
+ 
+@@ -742,112 +742,23 @@ void cthd_engine::thd_engine_reload_zones() {
+ 	}
+ }
+ 
+-// Add any tested platform ids in this table
+-#ifndef ANDROID
+-static const supported_ids_t id_table[] = {
+-		{ 6, 0x2a }, // Sandybridge
+-		{ 6, 0x3a }, // IvyBridge
+-		{ 6, 0x3c }, // Haswell
+-		{ 6, 0x45 }, // Haswell ULT
+-		{ 6, 0x46 }, // Haswell ULT
+-		{ 6, 0x3d }, // Broadwell
+-		{ 6, 0x47 }, // Broadwell-GT3E
+-		{ 6, 0x37 }, // Valleyview BYT
+-		{ 6, 0x4c }, // Brasewell
+-		{ 6, 0x4e }, // skylake
+-		{ 6, 0x5e }, // skylake
+-		{ 6, 0x5c }, // Broxton
+-		{ 6, 0x7a }, // Gemini Lake
+-		{ 6, 0x8e }, // kabylake
+-		{ 6, 0x9e }, // kabylake
+-		{ 6, 0x66 }, // Cannonlake
+-		{ 6, 0x7e }, // Icelake
+-		{ 6, 0x8c }, // Tigerlake_L
+-		{ 6, 0x8d }, // Tigerlake
+-		{ 6, 0xa5 }, // Cometlake
+-		{ 6, 0xa6 }, // Cometlake_L
+-		{ 6, 0xa7 }, // Rocketlake
+-		{ 6, 0x9c }, // Jasper Lake
+-		{ 6, 0x97 }, // Alderlake
+-		{ 6, 0x9a }, // Alderlake
+-		{ 6, 0xb7 }, // Raptorlake
+-		{ 6, 0xba }, // Raptorlake
+-		{ 6, 0xbe }, // Alderlake N
+-		{ 6, 0xbf }, // Raptorlake S
+-		{ 6, 0xaa }, // Mateor Lake L
+-		{ 6, 0xbd }, // Lunar Lake M
+-		{ 6, 0xc6 }, // Arrow Lake
+-		{ 6, 0xc5 }, // Arrow Lake H
+-		{ 6, 0xb5 }, // Arrow Lake U
+-		{ 6, 0xcc }, // Panther Lake L
+-		{ 6, 0xd5 }, // Wildcat Lake L
+-		{ 0, 0 } // Last Invalid entry
+-};
+-
+-const char * const blocklist_paths[] {
+-	/* Some Lenovo machines have in-firmware thermal management,
+-	 * avoid having two entities trying to manage things.
+-	 * We may want to change this to dytc_perfmode once that is
+-	 * widely available. */
+-	"/sys/devices/platform/thinkpad_acpi/dytc_lapmode",
+-};
+-#endif
+-
+ int cthd_engine::check_cpu_id() {
+-#ifndef ANDROID
+-	// Copied from turbostat program
+-	unsigned int ebx, ecx, edx, max_level;
+-	unsigned int fms, family, model, stepping;
+-	genuine_intel = 0;
+-	int i = 0;
+-	bool valid = false;
+-
+-	proc_list_matched = false;
+-	ebx = ecx = edx = 0;
+-
+-	__cpuid(0, max_level, ebx, ecx, edx);
+-	if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
+-		genuine_intel = 1;
+-	if (genuine_intel == 0) {
+-		// Simply return without further capability check
+-		return THD_SUCCESS;
+-	}
+-	__cpuid(1, fms, ebx, ecx, edx);
+-	family = (fms >> 8) & 0xf;
+-	model = (fms >> 4) & 0xf;
+-	stepping = fms & 0xf;
+-	if (family == 6 || family == 0xf)
+-		model += ((fms >> 16) & 0xf) << 4;
+-
+-	thd_log_msg(
+-			"%u CPUID levels; family:model:stepping 0x%x:%x:%x (%u:%u:%u)\n",
+-			max_level, family, model, stepping, family, model, stepping);
+-
+-	while (id_table[i].family) {
+-		if (id_table[i].family == family && id_table[i].model == model) {
+-			proc_list_matched = true;
+-			valid = true;
+-			break;
+-		}
+-		i++;
+-	}
+-	if (!valid) {
+-		thd_log_msg(" Need Linux PowerCap sysfs\n");
++	// Create platform instance using factory method
++	cthd_platform *platform = cthd_platform::create_platform();
++	if (!platform) {
++		thd_log_error("Failed to create platform instance\n");
++		proc_list_matched = false;
++		return THD_ERROR;
+ 	}
+ 
++	// Dump platform information
++	platform->dump_platform_info();
+ 
+-	for (const char *path : blocklist_paths) {
+-		struct stat s;
++	// Call platform-specific CPU ID check
++	int ret = platform->check_cpu_id(proc_list_matched);
+ 
+-		if (!stat(path, &s)) {
+-			proc_list_matched = false;
+-			thd_log_warn("[%s] present: Thermald can't run on this platform\n", path);
+-			break;
+-		}
+-	}
+-
+-#endif
+-	return THD_SUCCESS;
++	delete platform;
++	return ret;
+ }
+ 
+ void cthd_engine::thd_read_default_thermal_sensors() {
+diff --git a/src/thd_engine.h b/src/thd_engine.h
+index f6c9edf..2e024ca 100644
+--- a/src/thd_engine.h
++++ b/src/thd_engine.h
+@@ -67,11 +67,6 @@ typedef struct {
+ 	unsigned long msg[MAX_MSG_SIZE];
+ } message_capsul_t;
+ 
+-typedef struct {
+-	unsigned int family;
+-	unsigned int model;
+-} supported_ids_t;
+-
+ class cthd_engine {
+ 
+ protected:
+@@ -100,7 +95,6 @@ private:
+ 	time_t thz_last_temp_ind_time;
+ 	time_t thz_last_update_event_time;
+ 	bool terminate;
+-	int genuine_intel;
+ 	int has_invariant_tsc;
+ 	int has_aperf;
+ 	bool proc_list_matched;
+diff --git a/src/thd_engine_default.cpp b/src/thd_engine_default.cpp
+index 0e2a35c..62c2e67 100644
+--- a/src/thd_engine_default.cpp
++++ b/src/thd_engine_default.cpp
+@@ -40,6 +40,8 @@
+ #include "thd_int3400.h"
+ #include "thd_sensor_rapl_power.h"
+ #include "thd_zone_rapl_power.h"
++#include "thd_platform.h"
++#include "thd_platform_intel.h"
+ 
+ 
+ // Default CPU cooling devices, which are not part of thermal sysfs
+@@ -795,7 +797,13 @@ void cthd_engine_default::workarounds()
+ {
+ 	// Every 30 seconds repeat
+ 	if (!disable_active_power && !workaround_interval) {
+-		workaround_rapl_mmio_power();
++		// Create platform instance and call workaround
++		cthd_platform *platform = cthd_platform::create_platform();
++		if (platform) {
++			platform->workaround_rapl_mmio_power();
++			delete platform;
++		}
++
+ 		workaround_tcc_offset();
+ 		workaround_interval = 7;
+ 	} else {
+@@ -803,75 +811,6 @@ void cthd_engine_default::workarounds()
+ 	}
+ }
+ 
+-#ifndef ANDROID
+-#include <cpuid.h>
+-#include <sys/mman.h>
+-#define BIT_ULL(nr)	(1ULL << (nr))
+-#endif
+-
+-void cthd_engine_default::workaround_rapl_mmio_power(void)
+-{
+-	if (!workaround_enabled)
+-		return;
+-
+-	cthd_cdev *cdev = search_cdev("rapl_controller_mmio");
+-	if (cdev) {
+-		/* RAPL MMIO is enabled and getting used. No need to disable */
+-		return;
+-	} else {
+-		csys_fs _sysfs("/sys/devices/virtual/powercap/intel-rapl-mmio/intel-rapl-mmio:0/");
+-
+-		if (_sysfs.exists()) {
+-			std::ostringstream temp_str;
+-
+-			temp_str << "enabled";
+-			if (_sysfs.write(temp_str.str(), 0) > 0)
+-				return;
+-
+-			thd_log_debug("Failed to write to RAPL MMIO\n");
+-		}
+-	}
+-
+-#ifndef ANDROID
+-	int map_fd;
+-	void *rapl_mem;
+-	unsigned char *rapl_pkg_pwr_addr;
+-	unsigned long long pkg_power_limit;
+-
+-	unsigned int ebx, ecx, edx;
+-	unsigned int fms, family, model;
+-
+-	ecx = edx = 0;
+-	__cpuid(1, fms, ebx, ecx, edx);
+-	family = (fms >> 8) & 0xf;
+-	model = (fms >> 4) & 0xf;
+-	if (family == 6 || family == 0xf)
+-		model += ((fms >> 16) & 0xf) << 4;
+-
+-	// Apply for KabyLake only
+-	if (model != 0x8e && model != 0x9e)
+-		return;
+-
+-	map_fd = open("/dev/mem", O_RDWR, 0);
+-	if (map_fd < 0)
+-		return;
+-
+-	rapl_mem = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd,
+-			0xfed15000);
+-	if (!rapl_mem || rapl_mem == MAP_FAILED) {
+-		close(map_fd);
+-		return;
+-	}
+-
+-	rapl_pkg_pwr_addr = ((unsigned char *)rapl_mem + 0x9a0);
+-	pkg_power_limit = *(unsigned long long *)rapl_pkg_pwr_addr;
+-	*(unsigned long long *)rapl_pkg_pwr_addr = pkg_power_limit
+-			& ~BIT_ULL(15);
+-
+-	munmap(rapl_mem, 4096);
+-	close(map_fd);
+-#endif
+-}
+ 
+ void cthd_engine_default::workaround_tcc_offset(void)
+ {
+diff --git a/src/thd_platform.cpp b/src/thd_platform.cpp
+new file mode 100644
+index 0000000..25ce094
+--- /dev/null
++++ b/src/thd_platform.cpp
+@@ -0,0 +1,109 @@
++/*
++ * thd_platform.cpp: Platform detection and abstraction layer implementation
++ *
++ * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version
++ * 2 or later as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ * 02110-1301, USA.
++ *
++ * Author Name <priyansh.jain@oss.qualcomm.com>
++ */
++
++#include "thd_platform.h"
++#include "thd_platform_intel.h"
++#include "thd_common.h"
++#include <cstring>
++#include <iostream>
++
++cthd_platform::cthd_platform() : detected_platform(PLATFORM_UNKNOWN), machine_type("") {
++}
++
++cthd_platform::~cthd_platform() {
++}
++
++void cthd_platform::detect_platform() {
++    struct utsname sysinfo;
++    if (uname(&sysinfo) != 0) {
++        thd_log_error("Failed to get system information\n");
++        detected_platform = PLATFORM_UNKNOWN;
++        return;
++    }
++
++    machine_type = std::string(sysinfo.machine);
++    thd_log_info("Detected machine architecture: %s\n", machine_type.c_str());
++
++    if (strcmp(sysinfo.machine, "x86_64") == 0) {
++        detected_platform = PLATFORM_INTEL_X86;
++    } else {
++        detected_platform = PLATFORM_OTHER;
++    }
++}
++
++platform_type_t cthd_platform::get_platform() {
++    return detected_platform;
++}
++
++std::string cthd_platform::get_machine_type() {
++    return machine_type;
++}
++
++int cthd_platform::check_cpu_id(bool &proc_list_matched) {
++    // Base implementation - to be overridden by derived classes
++    proc_list_matched = false;
++    return THD_SUCCESS;
++}
++
++void cthd_platform::workaround_rapl_mmio_power() {
++    // Base implementation - to be overridden by derived classes
++    // No workaround needed for generic platform
++}
++
++void cthd_platform::dump_platform_info() {
++    platform_type_t platform = get_platform();
++
++    thd_log_info("=== Platform Information ===\n");
++    thd_log_info("Machine Type: %s\n", get_machine_type().c_str());
++
++    switch (platform) {
++        case PLATFORM_INTEL_X86:
++            thd_log_info("Platform: Intel x86/x86_64\n");
++            break;
++        case PLATFORM_OTHER:
++            thd_log_info("Platform: Other (%s)\n", get_machine_type().c_str());
++            break;
++        case PLATFORM_UNKNOWN:
++        default:
++            thd_log_info("Platform: Unknown\n");
++            break;
++    }
++    thd_log_info("============================\n");
++}
++
++cthd_platform* cthd_platform::create_platform() {
++    // Detect platform architecture using uname
++    struct utsname sysinfo;
++    if (uname(&sysinfo) != 0) {
++        thd_log_error("Failed to get system information\n");
++        return new cthd_platform();
++    }
++
++    // Create appropriate platform instance based on architecture
++    if (strcmp(sysinfo.machine, "x86_64") == 0) {
++        thd_log_info("Creating Intel platform instance\n");
++        return new intel_platform();
++    } else {
++        thd_log_info("Creating generic platform instance for %s\n", sysinfo.machine);
++        return new cthd_platform();
++    }
++}
+diff --git a/src/thd_platform.h b/src/thd_platform.h
+new file mode 100644
+index 0000000..25746c3
+--- /dev/null
++++ b/src/thd_platform.h
+@@ -0,0 +1,58 @@
++/*
++ * thd_platform.h: Platform detection and abstraction layer
++ *
++ * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version
++ * 2 or later as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ * 02110-1301, USA.
++ *
++ * Author Name <priyansh.jain@oss.qualcomm.com>
++ */
++
++#ifndef THD_PLATFORM_H_
++#define THD_PLATFORM_H_
++
++#include <string>
++#include <sys/utsname.h>
++
++typedef enum {
++    PLATFORM_UNKNOWN = 0,
++    PLATFORM_INTEL_X86,
++    PLATFORM_OTHER
++} platform_type_t;
++
++class cthd_platform {
++protected:
++    platform_type_t detected_platform;
++    std::string machine_type;
++
++public:
++    cthd_platform();
++    virtual ~cthd_platform();
++
++    // Virtual methods to be overridden by derived classes
++    virtual void detect_platform();
++    virtual int check_cpu_id(bool &proc_list_matched);
++    virtual void workaround_rapl_mmio_power();
++    virtual void dump_platform_info();
++
++    // Common methods
++    platform_type_t get_platform();
++    std::string get_machine_type();
++
++    // Factory method to create appropriate platform instance
++    static cthd_platform* create_platform();
++};
++
++#endif /* THD_PLATFORM_H_ */
+diff --git a/src/thd_platform_intel.cpp b/src/thd_platform_intel.cpp
+new file mode 100644
+index 0000000..622a9ad
+--- /dev/null
++++ b/src/thd_platform_intel.cpp
+@@ -0,0 +1,238 @@
++/*
++ * thd_platform_intel.cpp: Intel platform-specific functionality implementation
++ *
++ * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version
++ * 2 or later as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ * 02110-1301, USA.
++ *
++ */
++
++#include "thd_platform_intel.h"
++#include "thd_common.h"
++#include "thd_engine.h"
++#include <vector>
++#include <string>
++#include <fstream>
++#include <algorithm>
++
++#ifndef ANDROID
++#ifdef __x86_64__
++#include <cpuid.h>
++#include <sys/mman.h>
++#endif
++#include <sys/stat.h>
++#endif
++
++#define BIT_ULL(nr)	(1ULL << (nr))
++
++#ifndef ANDROID
++#ifdef __x86_64__
++typedef struct {
++	unsigned int family;
++	unsigned int model;
++} supported_ids_t;
++
++static supported_ids_t intel_id_table[] = {
++    { 6, 0x2a }, // Sandybridge
++    { 6, 0x3a }, // IvyBridge
++    { 6, 0x3c }, // Haswell
++    { 6, 0x45 }, // Haswell ULT
++    { 6, 0x46 }, // Haswell ULT
++    { 6, 0x3d }, // Broadwell
++    { 6, 0x47 }, // Broadwell-GT3E
++    { 6, 0x37 }, // Valleyview BYT
++    { 6, 0x4c }, // Brasewell
++    { 6, 0x4e }, // skylake
++    { 6, 0x5e }, // skylake
++    { 6, 0x5c }, // Broxton
++    { 6, 0x7a }, // Gemini Lake
++    { 6, 0x8e }, // kabylake
++    { 6, 0x9e }, // kabylake
++    { 6, 0x66 }, // Cannonlake
++    { 6, 0x7e }, // Icelake
++    { 6, 0x8c }, // Tigerlake_L
++    { 6, 0x8d }, // Tigerlake
++    { 6, 0xa5 }, // Cometlake
++    { 6, 0xa6 }, // Cometlake_L
++    { 6, 0xa7 }, // Rocketlake
++    { 6, 0x9c }, // Jasper Lake
++    { 6, 0x97 }, // Alderlake
++    { 6, 0x9a }, // Alderlake
++    { 6, 0xb7 }, // Raptorlake
++    { 6, 0xba }, // Raptorlake
++    { 6, 0xbe }, // Alderlake N
++    { 6, 0xbf }, // Raptorlake S
++    { 6, 0xaa }, // Mateor Lake L
++    { 6, 0xbd }, // Lunar Lake M
++    { 6, 0xc6 }, // Arrow Lake
++    { 6, 0xc5 }, // Arrow Lake H
++    { 6, 0xb5 }, // Arrow Lake U
++    { 6, 0xcc }, // Panther Lake L
++    { 0, 0 } // Last Invalid entry
++};
++
++std::vector<std::string> blocklist_paths {
++    /* Some Lenovo machines have in-firmware thermal management,
++     * avoid having two entities trying to manage things.
++     * We may want to change this to dytc_perfmode once that is
++     * widely available. */
++    "/sys/devices/platform/thinkpad_acpi/dytc_lapmode",
++};
++#endif // __x86_64__
++#endif
++
++intel_platform::intel_platform() : cthd_platform() {
++    // Intel platform specific initialization
++    detect_platform();
++}
++
++intel_platform::~intel_platform() {
++}
++
++void intel_platform::detect_platform() {
++    // Call base class detection first
++    cthd_platform::detect_platform();
++
++    thd_log_info("Intel platform detected\n");
++}
++
++int intel_platform::check_cpu_id(bool &proc_list_matched) {
++#ifndef ANDROID
++#ifdef __x86_64__
++    unsigned int ebx, ecx, edx, max_level;
++    unsigned int fms, family, model, stepping;
++	unsigned int genuine_intel = 0;
++    int i = 0;
++    bool valid = false;
++
++	proc_list_matched = false;
++    ebx = ecx = edx = 0;
++
++    __cpuid(0, max_level, ebx, ecx, edx);
++    if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
++        genuine_intel = 1;
++    if (genuine_intel == 0) {
++        // Simply return without further capability check
++        return THD_SUCCESS;
++    }
++    __cpuid(1, fms, ebx, ecx, edx);
++    family = (fms >> 8) & 0xf;
++    model = (fms >> 4) & 0xf;
++    stepping = fms & 0xf;
++    if (family == 6 || family == 0xf)
++        model += ((fms >> 16) & 0xf) << 4;
++
++    thd_log_msg(
++            "%u CPUID levels; family:model:stepping 0x%x:%x:%x (%u:%u:%u)\n",
++            max_level, family, model, stepping, family, model, stepping);
++
++    while (intel_id_table[i].family) {
++        if (intel_id_table[i].family == family && intel_id_table[i].model == model) {
++            proc_list_matched = true;
++            valid = true;
++            break;
++        }
++        i++;
++    }
++    if (!valid) {
++        thd_log_msg(" Need Linux PowerCap sysfs\n");
++    }
++
++    for (std::string path : blocklist_paths) {
++        struct stat s;
++
++        if (!stat(path.c_str(), &s)) {
++            proc_list_matched = false;
++            thd_log_warn("[%s] present: Thermald can't run on this platform\n", path.c_str());
++            break;
++        }
++    }
++#else
++    thd_log_info("Non-x86_64 platform detected in Intel check - skipping CPUID\n");
++#endif // __x86_64__
++#endif // ANDROID
++    return THD_SUCCESS;
++}
++
++void intel_platform::workaround_rapl_mmio_power(void) {
++    // First check if workaround is enabled and needed
++    extern bool workaround_enabled;
++    if (!workaround_enabled)
++        return;
++
++    // Check if RAPL MMIO controller is already being used
++    extern cthd_engine *thd_engine;
++    if (thd_engine) {
++        cthd_cdev *cdev = thd_engine->search_cdev("rapl_controller_mmio");
++        if (cdev) {
++            /* RAPL MMIO is enabled and getting used. No need to disable */
++            return;
++        } else {
++            csys_fs _sysfs("/sys/devices/virtual/powercap/intel-rapl-mmio/intel-rapl-mmio:0/");
++
++            if (_sysfs.exists()) {
++                std::stringstream temp_str;
++
++                temp_str << "enabled";
++                if (_sysfs.write(temp_str.str(), 0) > 0)
++                    return;
++
++                thd_log_debug("Failed to write to RAPL MMIO\n");
++            }
++        }
++    }
++
++#ifndef ANDROID
++#ifdef __x86_64__
++    int map_fd;
++    void *rapl_mem;
++    unsigned char *rapl_pkg_pwr_addr;
++    unsigned long long pkg_power_limit;
++
++    unsigned int ebx, ecx, edx;
++    unsigned int fms, family, model;
++
++    ecx = edx = 0;
++    __cpuid(1, fms, ebx, ecx, edx);
++    family = (fms >> 8) & 0xf;
++    model = (fms >> 4) & 0xf;
++    if (family == 6 || family == 0xf)
++        model += ((fms >> 16) & 0xf) << 4;
++
++    // Apply for KabyLake only
++    if (model != 0x8e && model != 0x9e)
++        return;
++
++    map_fd = open("/dev/mem", O_RDWR, 0);
++    if (map_fd < 0)
++        return;
++
++    rapl_mem = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd,
++            0xfed15000);
++    if (!rapl_mem || rapl_mem == MAP_FAILED) {
++        close(map_fd);
++        return;
++    }
++
++    rapl_pkg_pwr_addr = ((unsigned char *)rapl_mem + 0x9a0);
++    pkg_power_limit = *(unsigned long long *)rapl_pkg_pwr_addr;
++    *(unsigned long long *)rapl_pkg_pwr_addr = pkg_power_limit
++            & ~BIT_ULL(15);
++
++    munmap(rapl_mem, 4096);
++    close(map_fd);
++#endif // __x86_64__
++#endif // ANDROID
++}
+diff --git a/src/thd_platform_intel.h b/src/thd_platform_intel.h
+new file mode 100644
+index 0000000..5753afe
+--- /dev/null
++++ b/src/thd_platform_intel.h
+@@ -0,0 +1,38 @@
++/*
++ * thd_platform_intel.h: Intel platform-specific functionality
++ *
++ * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version
++ * 2 or later as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ * 02110-1301, USA.
++ *
++ */
++
++#ifndef THD_PLATFORM_INTEL_H_
++#define THD_PLATFORM_INTEL_H_
++
++#include "thd_platform.h"
++
++class intel_platform : public cthd_platform {
++public:
++    intel_platform();
++    virtual ~intel_platform();
++
++    // Override virtual methods from base class
++    void detect_platform() override;
++    int check_cpu_id(bool &proc_list_matched) override;
++    void workaround_rapl_mmio_power() override;
++};
++
++#endif /* THD_PLATFORM_INTEL_H_ */
+-- 
+2.25.1
+
diff --git a/meta-oe/recipes-bsp/thermald/thermald/0002-Invoke-parser_init-before-platform_match.patch b/meta-oe/recipes-bsp/thermald/thermald/0002-Invoke-parser_init-before-platform_match.patch
new file mode 100644
index 0000000000..6f72d0cc01
--- /dev/null
+++ b/meta-oe/recipes-bsp/thermald/thermald/0002-Invoke-parser_init-before-platform_match.patch
@@ -0,0 +1,41 @@ 
+From 857fbdf3e9079cec04bfa5fe7a93a432485b5cab Mon Sep 17 00:00:00 2001
+From: Priyansh Jain <priyansh.jain@oss.qualcomm.com>
+Date: Tue, 27 Jan 2026 15:26:24 +0530
+Subject: [PATCH 2/3] Invoke parser_init before platform_match
+
+The initialization flow currently invokes platform_match without
+calling parser_init first. As a result, the platform matching
+logic runs with no parsed configuration data available. This
+can cause incorrect platform detection, or failure to load
+the expected thermal configurations.
+
+This patch adds the missing parser_init() call before
+platform_match(), ensuring that configuration files are properly
+parsed and populated before any platform-specific matching occurs.
+This makes initialization reliable and aligns with the intended
+dependency order.
+
+Suggested-by: Amit Kucheria <amit.kucheria@oss.qualcomm.com>
+Signed-off-by: Priyansh Jain <priyansh.jain@oss.qualcomm.com>
+
+Upstream-Status: Backport [from commit 857fbdf3e9079cec04bfa5fe7a93a432485b5cab]
+---
+ src/thd_engine.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/thd_engine.cpp b/src/thd_engine.cpp
+index 319f50b..da52a5b 100644
+--- a/src/thd_engine.cpp
++++ b/src/thd_engine.cpp
+@@ -318,7 +318,7 @@ int cthd_engine::thd_engine_start() {
+ 		poll_timeout_msec = poll_interval_sec * 1000;
+ 	}
+ 
+-	if (parser.platform_matched()) {
++	if (!parser_init() && parser.platform_matched()) {
+ 		parser.set_default_preference();
+ 		int poll_secs = parser.get_polling_interval();
+ 		if (poll_secs) {
+-- 
+2.25.1
+
diff --git a/meta-oe/recipes-bsp/thermald/thermald/0003-Add-ARM-backend-and-enable-ARM-platform-detection.patch b/meta-oe/recipes-bsp/thermald/thermald/0003-Add-ARM-backend-and-enable-ARM-platform-detection.patch
new file mode 100644
index 0000000000..a444c585ab
--- /dev/null
+++ b/meta-oe/recipes-bsp/thermald/thermald/0003-Add-ARM-backend-and-enable-ARM-platform-detection.patch
@@ -0,0 +1,234 @@ 
+From 1931a12e7e44b6b85a02a5d8158829eff4b9cc92 Mon Sep 17 00:00:00 2001
+From: Priyansh Jain <priyansh.jain@oss.qualcomm.com>
+Date: Mon, 9 Feb 2026 16:11:31 +0530
+Subject: [PATCH 3/3] Add ARM backend and enable ARM platform detection
+
+thermald historically supported only Intel platforms. As the
+codebase is being refactored to allow multi-platform support,
+ARM platforms require their own backend implementation to
+handle platform-specific thermal controls, capabilities, and
+configuration rules.
+
+This patch adds the initial ARM-specific backend files and
+integrates ARM selection into the newly introduced platform
+detection mechanism. With this change, thermald can correctly
+identify ARM systems and route thermal management operations
+to the appropriate backend. This establishes the foundation
+needed for future ARM thermal features and expands thermald's
+usefulness beyond Intel-based platforms.
+
+Suggested-by: Amit Kucheria <amit.kucheria@oss.qualcomm.com>
+Signed-off-by: Priyansh Jain <priyansh.jain@oss.qualcomm.com>
+
+Upstream-Status: Backport [from commit 1931a12e7e44b6b85a02a5d8158829eff4b9cc92]
+---
+ Android.mk               |  3 ++-
+ Makefile.am              |  3 ++-
+ src/thd_engine.cpp       |  1 +
+ src/thd_platform.cpp     | 14 ++++++++++++
+ src/thd_platform.h       |  2 ++
+ src/thd_platform_arm.cpp | 47 ++++++++++++++++++++++++++++++++++++++++
+ src/thd_platform_arm.h   | 38 ++++++++++++++++++++++++++++++++
+ 7 files changed, 106 insertions(+), 2 deletions(-)
+ create mode 100644 src/thd_platform_arm.cpp
+ create mode 100644 src/thd_platform_arm.h
+
+diff --git a/Android.mk b/Android.mk
+index c14fa4a..5d38c35 100644
+--- a/Android.mk
++++ b/Android.mk
+@@ -45,7 +45,8 @@ LOCAL_SRC_FILES := \
+ 		src/LzmaDec.c \
+ 		src/thd_gddv.cpp \
+ 		src/thd_platform.cpp \
+-		src/thd_platform_intel.cpp
++		src/thd_platform_intel.cpp \
++		src/thd_platform_arm.cpp
+ 
+ LOCAL_C_INCLUDES += external/libxml2/include
+ 
+diff --git a/Makefile.am b/Makefile.am
+index 2e76187..61741ba 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -77,7 +77,8 @@ thermald_SOURCES = \
+ 	src/thd_lzma_dec.cpp \
+ 	src/LzmaDec.c \
+ 	src/thd_platform.cpp \
+-	src/thd_platform_intel.cpp
++	src/thd_platform_intel.cpp \
++	src/thd_platform_arm.cpp
+ 
+ man5_MANS = man/thermal-conf.xml.5
+ man8_MANS = man/thermald.8
+diff --git a/src/thd_engine.cpp b/src/thd_engine.cpp
+index da52a5b..9024650 100644
+--- a/src/thd_engine.cpp
++++ b/src/thd_engine.cpp
+@@ -45,6 +45,7 @@
+ #include "thd_int3400.h"
+ #include "thd_platform.h"
+ #include "thd_platform_intel.h"
++#include "thd_platform_arm.h"
+ 
+ static void *cthd_engine_thread(void *arg);
+ 
+diff --git a/src/thd_platform.cpp b/src/thd_platform.cpp
+index 25ce094..647b079 100644
+--- a/src/thd_platform.cpp
++++ b/src/thd_platform.cpp
+@@ -22,6 +22,7 @@
+ 
+ #include "thd_platform.h"
+ #include "thd_platform_intel.h"
++#include "thd_platform_arm.h"
+ #include "thd_common.h"
+ #include <cstring>
+ #include <iostream>
+@@ -45,6 +46,10 @@ void cthd_platform::detect_platform() {
+ 
+     if (strcmp(sysinfo.machine, "x86_64") == 0) {
+         detected_platform = PLATFORM_INTEL_X86;
++    } else if (strcmp(sysinfo.machine, "aarch64") == 0) {
++        detected_platform = PLATFORM_ARM64;
++    } else if (strcmp(sysinfo.machine, "arm") == 0) {
++        detected_platform = PLATFORM_ARM32;
+     } else {
+         detected_platform = PLATFORM_OTHER;
+     }
+@@ -79,6 +84,12 @@ void cthd_platform::dump_platform_info() {
+         case PLATFORM_INTEL_X86:
+             thd_log_info("Platform: Intel x86/x86_64\n");
+             break;
++        case PLATFORM_ARM64:
++            thd_log_info("Platform: ARM64 (aarch64)\n");
++            break;
++        case PLATFORM_ARM32:
++            thd_log_info("Platform: ARM32\n");
++            break;
+         case PLATFORM_OTHER:
+             thd_log_info("Platform: Other (%s)\n", get_machine_type().c_str());
+             break;
+@@ -102,6 +113,9 @@ cthd_platform* cthd_platform::create_platform() {
+     if (strcmp(sysinfo.machine, "x86_64") == 0) {
+         thd_log_info("Creating Intel platform instance\n");
+         return new intel_platform();
++    } else if (strcmp(sysinfo.machine, "aarch64") == 0 || strcmp(sysinfo.machine, "arm") == 0) {
++        thd_log_info("Creating ARM platform instance\n");
++        return new arm_platform();
+     } else {
+         thd_log_info("Creating generic platform instance for %s\n", sysinfo.machine);
+         return new cthd_platform();
+diff --git a/src/thd_platform.h b/src/thd_platform.h
+index 25746c3..096a55e 100644
+--- a/src/thd_platform.h
++++ b/src/thd_platform.h
+@@ -29,6 +29,8 @@
+ typedef enum {
+     PLATFORM_UNKNOWN = 0,
+     PLATFORM_INTEL_X86,
++    PLATFORM_ARM64,
++    PLATFORM_ARM32,
+     PLATFORM_OTHER
+ } platform_type_t;
+ 
+diff --git a/src/thd_platform_arm.cpp b/src/thd_platform_arm.cpp
+new file mode 100644
+index 0000000..a43ef9f
+--- /dev/null
++++ b/src/thd_platform_arm.cpp
+@@ -0,0 +1,47 @@
++/*
++ * thd_platform_arm.cpp: ARM platform-specific functionality implementation
++ *
++ * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version
++ * 2 or later as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ * 02110-1301, USA.
++ *
++ * Author Name <priyansh.jain@oss.qualcomm.com>
++ */
++
++#include "thd_platform_arm.h"
++#include "thd_common.h"
++
++arm_platform::arm_platform() : cthd_platform() {
++    // ARM platform specific initialization
++    detect_platform();
++}
++
++arm_platform::~arm_platform() {
++}
++
++void arm_platform::detect_platform() {
++    // Call base class detection first
++    cthd_platform::detect_platform();
++
++    // ARM-specific platform detection can be added here if needed
++    thd_log_info("ARM platform detected\n");
++}
++
++int arm_platform::check_cpu_id(bool &proc_list_matched) {
++    // For ARM, we assume the platform is supported
++    proc_list_matched = true;
++
++    return THD_SUCCESS;
++}
+diff --git a/src/thd_platform_arm.h b/src/thd_platform_arm.h
+new file mode 100644
+index 0000000..e970803
+--- /dev/null
++++ b/src/thd_platform_arm.h
+@@ -0,0 +1,38 @@
++/*
++ * thd_platform_arm.h: ARM platform-specific functionality
++ *
++ * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version
++ * 2 or later as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ * 02110-1301, USA.
++ *
++ * Author Name <priyansh.jain@oss.qualcomm.com>
++ */
++
++#ifndef THD_PLATFORM_ARM_H_
++#define THD_PLATFORM_ARM_H_
++
++#include "thd_platform.h"
++
++class arm_platform : public cthd_platform {
++public:
++    arm_platform();
++    virtual ~arm_platform();
++
++    // Override virtual methods from base class
++    void detect_platform() override;
++    int check_cpu_id(bool &proc_list_matched) override;
++};
++
++#endif /* THD_PLATFORM_ARM_H_ */
+-- 
+2.25.1
+
diff --git a/meta-oe/recipes-bsp/thermald/thermald_2.5.11.bb b/meta-oe/recipes-bsp/thermald/thermald_2.5.11.bb
index caec3d5610..0425d1c575 100644
--- a/meta-oe/recipes-bsp/thermald/thermald_2.5.11.bb
+++ b/meta-oe/recipes-bsp/thermald/thermald_2.5.11.bb
@@ -13,6 +13,9 @@  LICENSE = "GPL-2.0-only"
 LIC_FILES_CHKSUM = "file://COPYING;md5=ea8831610e926e2e469075b52bf08848"
 
 SRC_URI = "git://github.com/intel/thermal_daemon/;branch=master;protocol=https \
+           file://0001-Refactor-Intel-specific-logic-into-separate-files.patch \
+           file://0002-Invoke-parser_init-before-platform_match.patch \
+           file://0003-Add-ARM-backend-and-enable-ARM-platform-detection.patch \
            "
 
 SRCREV = "5269afcf3e021e4e1b672b4640a0358f4ae5821b"
@@ -33,7 +36,7 @@  FILES:${PN} += "${datadir}/dbus-1"
 
 SYSTEMD_SERVICE:${PN} = "thermald.service"
 
-COMPATIBLE_HOST = '(i.86|x86_64).*-linux'
+COMPATIBLE_HOST = '(i.86|x86_64|aarch64|arm).*-linux'
 
 CONFFILES:${PN} = " \
                    ${sysconfdir}/thermald/thermal-conf.xml \