soc/qualcomm/common: Add Qualcomm TSENS support
Introduce a generic driver for the Qualcomm Temperature Sensor (TSENS) V2 hardware block. This driver provides the infrastructure to read temperature data from hardware status registers and monitor them against software-defined thresholds. The driver sign-extends the 12-bit raw temperature values and scales the output to millidegrees Celsius for accurate monitoring. TEST=Verify all x1p42100 thermal zones are readable on Google/Quartz. Change-Id: I826df3f86edc30ac57d84f672b487a8b9b51728a Signed-off-by: Kapil Porwal <kapilporwal@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/91609 Reviewed-by: Subrata Banik <subratabanik@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
9e7c787f6d
commit
53529b1d93
3 changed files with 120 additions and 0 deletions
|
|
@ -54,4 +54,11 @@ config SOC_QUALCOMM_QCLIB_SKIP_MMU_TOGGLE
|
|||
flushes and TLB invalidations associated with mmu_disable() and
|
||||
mmu_enable() calls.
|
||||
|
||||
config SOC_QUALCOMM_DEBUG_TSENS
|
||||
bool
|
||||
default n
|
||||
help
|
||||
When enabled, a call to monitor TSENS will dump the sensor data on
|
||||
the debug console.
|
||||
|
||||
endif
|
||||
|
|
|
|||
41
src/soc/qualcomm/common/include/soc/qcom_tsens.h
Normal file
41
src/soc/qualcomm/common/include/soc/qcom_tsens.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _SOC_QUALCOMM_TSENS_H_
|
||||
#define _SOC_QUALCOMM_TSENS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TM_SN_STATUS_OFF 0x00a0
|
||||
#define SN_STATUS_VALID (1 << 21)
|
||||
#define SN_STATUS_TEMP_MASK 0xFFF
|
||||
|
||||
struct tsens_controller {
|
||||
const char *name;
|
||||
uintptr_t tm_base;
|
||||
uintptr_t srot_base;
|
||||
uint32_t sensor_count;
|
||||
};
|
||||
|
||||
enum sensor_type {
|
||||
TYPE_TSENS
|
||||
};
|
||||
|
||||
struct thermal_zone_map {
|
||||
const char *label;
|
||||
enum sensor_type type;
|
||||
const void *ctrl;
|
||||
int hw_id;
|
||||
int threshold;
|
||||
};
|
||||
|
||||
/*
|
||||
* Iterates through all defined zones and checks thresholds.
|
||||
*/
|
||||
void qcom_tsens_monitor_all(bool *has_crossed_threshold);
|
||||
|
||||
/* External Data (Defined in SoC file) */
|
||||
extern const struct thermal_zone_map qcom_thermal_zones[];
|
||||
|
||||
#endif /* _SOC_QUALCOMM_TSENS_H_ */
|
||||
72
src/soc/qualcomm/common/tsens.c
Normal file
72
src/soc/qualcomm/common/tsens.c
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <arch/mmio.h>
|
||||
#include <commonlib/bsd/stdlib.h>
|
||||
#include <device/mmio.h>
|
||||
#include <soc/addressmap.h>
|
||||
#include <soc/qcom_tsens.h>
|
||||
|
||||
#if CONFIG(SOC_QUALCOMM_DEBUG_TSENS)
|
||||
#define thermal_printk(fmt, ...) printk(BIOS_INFO, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define thermal_printk(fmt, ...) do { (void)(fmt); } while (0)
|
||||
#endif
|
||||
|
||||
static int read_tsens(const struct thermal_zone_map *zone, int *out)
|
||||
{
|
||||
if (!zone)
|
||||
return -1;
|
||||
|
||||
const struct tsens_controller *ctrl = (const struct tsens_controller *)zone->ctrl;
|
||||
if (!ctrl || (zone->hw_id >= (int)ctrl->sensor_count))
|
||||
return -1;
|
||||
|
||||
uintptr_t status_addr = ctrl->tm_base + TM_SN_STATUS_OFF + (zone->hw_id * 4);
|
||||
|
||||
uint32_t status = read32p(status_addr);
|
||||
if (!(status & SN_STATUS_VALID))
|
||||
return -2;
|
||||
|
||||
/* Sign extend 12-bit temperature and scale to milli C */
|
||||
*out = ((int32_t)((status & SN_STATUS_TEMP_MASK) << 20) >> 20) * 100;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qcom_tsens_monitor_all(bool *has_crossed_threshold)
|
||||
{
|
||||
if (!has_crossed_threshold)
|
||||
return;
|
||||
|
||||
*has_crossed_threshold = false;
|
||||
|
||||
thermal_printk("\n------------------ Thermal Sensor State --------------------\n");
|
||||
thermal_printk("%-15s | %-10s | %-8s | %-10s\n", "Zone", "Type", "Temp (C)", "Status");
|
||||
thermal_printk("------------------------------------------------------------\n");
|
||||
|
||||
for (const struct thermal_zone_map *zone = qcom_thermal_zones; zone->label != NULL; zone++) {
|
||||
int data = 0, status = -1;
|
||||
const char *type_str = "UNK";
|
||||
(void)type_str;
|
||||
|
||||
if (zone->type == TYPE_TSENS) {
|
||||
type_str = "SoC";
|
||||
status = read_tsens(zone, &data);
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
thermal_printk("%-15s | %-10s | %3d.%1d | ",
|
||||
zone->label, type_str, data / 1000, (data % 1000) / 100);
|
||||
|
||||
if (data >= zone->threshold) {
|
||||
*has_crossed_threshold = true;
|
||||
thermal_printk("EXCEEDED\n");
|
||||
if (!CONFIG(SOC_QUALCOMM_DEBUG_TSENS))
|
||||
return;
|
||||
} else {
|
||||
thermal_printk("OK\n");
|
||||
}
|
||||
} else {
|
||||
thermal_printk("%-15s | %-10s | [ERR %d] | -\n", zone->label, type_str, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue