* [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes
@ 2025-03-20 20:24 Anjelique Melendez
2025-03-20 20:24 ` [PATCH v3 1/5 RESEND] thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required Anjelique Melendez
` (5 more replies)
0 siblings, 6 replies; 17+ messages in thread
From: Anjelique Melendez @ 2025-03-20 20:24 UTC (permalink / raw)
To: amitk, thara.gopinath, rafael, daniel.lezcano
Cc: rui.zhang, lukasz.luba, david.collins, srinivas.kandagatla,
stefan.schmidt, quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
Add support in the qcom-spmi-temp-alarm driver for the new PMIC
TEMP_ALARM peripheral subtypes: GEN2 rev 2 and LITE. The GEN2 rev 2
subtype provides greater flexibility in temperature threshold
specification by using an independent register value to configure
each of the three thresholds. The LITE subtype utilizes a simplified
set of control registers to configure two thresholds: warning and
shutdown. While at it refactor the qcom-spmi-temp-alarm driver to limit
code reuse and if/else statements when deciphering between TEMP_ALARM
peripheral subtypes.
Also add support to avoid a potential issue on certain versions of
the TEMP_ALARM GEN2 subtype when automatic stage 2 partial shutdown
is disabled.
This patch series is a continuation of older series from 7/2024
(https://lore.kernel.org/all/20240729231259.2122976-1-quic_amelende@quicinc.com/)
but current series has been reworked to address the change in thermal framework to
update .set_trip_temp() callback function variables
(https://lore.kernel.org/all/8392906.T7Z3S40VBb@rjwysocki.net/)
Changes since v2:
- Updated function name to include "gen1" in patch 2/5
- Added Dmitry's reviewed-by tag in patch 2/5
- link: https://lore.kernel.org/all/20250225192429.2328092-1-anjelique.melendez@oss.qualcomm.com/
Changes since v1:
- Remove unnecessary moving of code
- Added new v2 patch 3/5 add a preparation patch to v1 patch 2/5
- Updated temp alarm data function names to be consistently named
- link: https://lore.kernel.org/all/20250213210403.3396392-1-anjelique.melendez@oss.qualcomm.com/
Anjelique Melendez (4):
thermal: qcom-spmi-temp-alarm: Add temp alarm data struct based on HW
subtype
thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp
Alarm subtypes
thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC
peripherals
thermal: qcom-spmi-temp-alarm: add support for LITE PMIC peripherals
David Collins (1):
thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required
drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 515 ++++++++++++++++++--
1 file changed, 464 insertions(+), 51 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v3 1/5 RESEND] thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required
2025-03-20 20:24 [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes Anjelique Melendez
@ 2025-03-20 20:24 ` Anjelique Melendez
2025-04-10 21:01 ` Dmitry Baryshkov
2025-04-18 10:54 ` Daniel Lezcano
2025-03-20 20:24 ` [PATCH v3 2/5 RESEND] thermal: qcom-spmi-temp-alarm: Add temp alarm data struct based on HW subtype Anjelique Melendez
` (4 subsequent siblings)
5 siblings, 2 replies; 17+ messages in thread
From: Anjelique Melendez @ 2025-03-20 20:24 UTC (permalink / raw)
To: amitk, thara.gopinath, rafael, daniel.lezcano
Cc: rui.zhang, lukasz.luba, david.collins, srinivas.kandagatla,
stefan.schmidt, quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
From: David Collins <david.collins@oss.qualcomm.com>
Certain TEMP_ALARM GEN2 PMIC peripherals need over-temperature
stage 2 automatic PMIC partial shutdown to be enabled in order to
avoid repeated faults in the event of reaching over-temperature
stage 3. Modify the stage 2 shutdown control logic to ensure that
stage 2 shutdown is enabled on all affected PMICs. Read the
digital major and minor revision registers to identify these
PMICs.
Signed-off-by: David Collins <david.collins@oss.qualcomm.com>
Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
---
drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 32 +++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
index c2d59cbfaea9..b2077ff9fe73 100644
--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2011-2015, 2017, 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/bitops.h>
@@ -16,6 +17,7 @@
#include "../thermal_hwmon.h"
+#define QPNP_TM_REG_DIG_MINOR 0x00
#define QPNP_TM_REG_DIG_MAJOR 0x01
#define QPNP_TM_REG_TYPE 0x04
#define QPNP_TM_REG_SUBTYPE 0x05
@@ -71,6 +73,7 @@ struct qpnp_tm_chip {
struct device *dev;
struct thermal_zone_device *tz_dev;
unsigned int subtype;
+ unsigned int dig_revision;
long temp;
unsigned int thresh;
unsigned int stage;
@@ -78,6 +81,7 @@ struct qpnp_tm_chip {
/* protects .thresh, .stage and chip registers */
struct mutex lock;
bool initialized;
+ bool require_s2_shutdown;
struct iio_channel *adc;
const long (*temp_map)[THRESH_COUNT][STAGE_COUNT];
@@ -255,7 +259,7 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip,
skip:
reg |= chip->thresh;
- if (disable_s2_shutdown)
+ if (disable_s2_shutdown && !chip->require_s2_shutdown)
reg |= SHUTDOWN_CTRL1_OVERRIDE_S2;
return qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg);
@@ -350,7 +354,7 @@ static int qpnp_tm_probe(struct platform_device *pdev)
{
struct qpnp_tm_chip *chip;
struct device_node *node;
- u8 type, subtype, dig_major;
+ u8 type, subtype, dig_major, dig_minor;
u32 res;
int ret, irq;
@@ -403,6 +407,30 @@ static int qpnp_tm_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, ret,
"could not read dig_major\n");
+ ret = qpnp_tm_read(chip, QPNP_TM_REG_DIG_MINOR, &dig_minor);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "could not read dig_minor\n");
+ return ret;
+ }
+
+ chip->dig_revision = (dig_major << 8) | dig_minor;
+
+ if (chip->subtype == QPNP_TM_SUBTYPE_GEN2) {
+ /*
+ * Check if stage 2 automatic partial shutdown must remain
+ * enabled to avoid potential repeated faults upon reaching
+ * over-temperature stage 3.
+ */
+ switch (chip->dig_revision) {
+ case 0x0001:
+ case 0x0002:
+ case 0x0100:
+ case 0x0101:
+ chip->require_s2_shutdown = true;
+ break;
+ }
+ }
+
if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1
&& subtype != QPNP_TM_SUBTYPE_GEN2)) {
dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n",
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v3 2/5 RESEND] thermal: qcom-spmi-temp-alarm: Add temp alarm data struct based on HW subtype
2025-03-20 20:24 [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes Anjelique Melendez
2025-03-20 20:24 ` [PATCH v3 1/5 RESEND] thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required Anjelique Melendez
@ 2025-03-20 20:24 ` Anjelique Melendez
2025-03-20 20:24 ` [PATCH v3 3/5 RESEND] thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp Alarm subtypes Anjelique Melendez
` (3 subsequent siblings)
5 siblings, 0 replies; 17+ messages in thread
From: Anjelique Melendez @ 2025-03-20 20:24 UTC (permalink / raw)
To: amitk, thara.gopinath, rafael, daniel.lezcano
Cc: rui.zhang, lukasz.luba, david.collins, srinivas.kandagatla,
stefan.schmidt, quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
Currently multiple if/else statements are used in functions to decipher
between SPMI temp alarm Gen 1, Gen 2 and Gen 2 Rev 1 functionality. Instead
refactor the driver so that SPMI temp alarm chips will have reference to a
spmi_temp_alarm_data struct which defines data and function callbacks
based on the HW subtype.
Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 107 +++++++++++++-------
1 file changed, 70 insertions(+), 37 deletions(-)
diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
index b2077ff9fe73..1cc9369ca9e1 100644
--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
@@ -4,6 +4,7 @@
* Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
@@ -31,7 +32,6 @@
#define STATUS_GEN1_STAGE_MASK GENMASK(1, 0)
#define STATUS_GEN2_STATE_MASK GENMASK(6, 4)
-#define STATUS_GEN2_STATE_SHIFT 4
#define SHUTDOWN_CTRL1_OVERRIDE_S2 BIT(6)
#define SHUTDOWN_CTRL1_THRESHOLD_MASK GENMASK(1, 0)
@@ -68,10 +68,18 @@ static const long temp_map_gen2_v1[THRESH_COUNT][STAGE_COUNT] = {
/* Temperature in Milli Celsius reported during stage 0 if no ADC is present */
#define DEFAULT_TEMP 37000
+struct qpnp_tm_chip;
+
+struct spmi_temp_alarm_data {
+ const long (*temp_map)[THRESH_COUNT][STAGE_COUNT];
+ int (*get_temp_stage)(struct qpnp_tm_chip *chip);
+};
+
struct qpnp_tm_chip {
struct regmap *map;
struct device *dev;
struct thermal_zone_device *tz_dev;
+ const struct spmi_temp_alarm_data *data;
unsigned int subtype;
unsigned int dig_revision;
long temp;
@@ -82,9 +90,9 @@ struct qpnp_tm_chip {
struct mutex lock;
bool initialized;
bool require_s2_shutdown;
+ long temp_thresh_map[STAGE_COUNT];
struct iio_channel *adc;
- const long (*temp_map)[THRESH_COUNT][STAGE_COUNT];
};
/* This array maps from GEN2 alarm state to GEN1 alarm stage */
@@ -118,20 +126,19 @@ static int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 data)
*/
static long qpnp_tm_decode_temp(struct qpnp_tm_chip *chip, unsigned int stage)
{
- if (!chip->temp_map || chip->thresh >= THRESH_COUNT || stage == 0 ||
- stage > STAGE_COUNT)
+ if (stage == 0 || stage > STAGE_COUNT)
return 0;
- return (*chip->temp_map)[chip->thresh][stage - 1];
+ return chip->temp_thresh_map[stage - 1];
}
/**
- * qpnp_tm_get_temp_stage() - return over-temperature stage
+ * qpnp_tm_gen1_get_temp_stage() - return over-temperature stage
* @chip: Pointer to the qpnp_tm chip
*
- * Return: stage (GEN1) or state (GEN2) on success, or errno on failure.
+ * Return: stage on success, or errno on failure.
*/
-static int qpnp_tm_get_temp_stage(struct qpnp_tm_chip *chip)
+static int qpnp_tm_gen1_get_temp_stage(struct qpnp_tm_chip *chip)
{
int ret;
u8 reg = 0;
@@ -140,12 +147,27 @@ static int qpnp_tm_get_temp_stage(struct qpnp_tm_chip *chip)
if (ret < 0)
return ret;
- if (chip->subtype == QPNP_TM_SUBTYPE_GEN1)
- ret = reg & STATUS_GEN1_STAGE_MASK;
- else
- ret = (reg & STATUS_GEN2_STATE_MASK) >> STATUS_GEN2_STATE_SHIFT;
+ return FIELD_GET(STATUS_GEN1_STAGE_MASK, reg);
+}
- return ret;
+/**
+ * qpnp_tm_gen2_get_temp_stage() - return over-temperature stage
+ * @chip: Pointer to the qpnp_tm chip
+ *
+ * Return: stage on success, or errno on failure.
+ */
+static int qpnp_tm_gen2_get_temp_stage(struct qpnp_tm_chip *chip)
+{
+ u8 reg = 0;
+ int ret;
+
+ ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, ®);
+ if (ret < 0)
+ return ret;
+
+ ret = FIELD_GET(STATUS_GEN2_STATE_MASK, reg);
+
+ return alarm_state_map[ret];
}
/*
@@ -154,23 +176,16 @@ static int qpnp_tm_get_temp_stage(struct qpnp_tm_chip *chip)
*/
static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
{
- unsigned int stage, stage_new, stage_old;
+ unsigned int stage_new, stage_old;
int ret;
WARN_ON(!mutex_is_locked(&chip->lock));
- ret = qpnp_tm_get_temp_stage(chip);
+ ret = chip->data->get_temp_stage(chip);
if (ret < 0)
return ret;
- stage = ret;
-
- if (chip->subtype == QPNP_TM_SUBTYPE_GEN1) {
- stage_new = stage;
- stage_old = chip->stage;
- } else {
- stage_new = alarm_state_map[stage];
- stage_old = alarm_state_map[chip->stage];
- }
+ stage_new = ret;
+ stage_old = chip->stage;
if (stage_new > stage_old) {
/* increasing stage, use lower bound */
@@ -182,7 +197,7 @@ static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
- TEMP_STAGE_HYSTERESIS;
}
- chip->stage = stage;
+ chip->stage = stage_new;
return 0;
}
@@ -222,8 +237,8 @@ static int qpnp_tm_get_temp(struct thermal_zone_device *tz, int *temp)
static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip,
int temp)
{
- long stage2_threshold_min = (*chip->temp_map)[THRESH_MIN][1];
- long stage2_threshold_max = (*chip->temp_map)[THRESH_MAX][1];
+ long stage2_threshold_min = (*chip->data->temp_map)[THRESH_MIN][1];
+ long stage2_threshold_max = (*chip->data->temp_map)[THRESH_MAX][1];
bool disable_s2_shutdown = false;
u8 reg;
@@ -258,6 +273,8 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip,
}
skip:
+ memcpy(chip->temp_thresh_map, chip->data->temp_map[chip->thresh],
+ sizeof(chip->temp_thresh_map));
reg |= chip->thresh;
if (disable_s2_shutdown && !chip->require_s2_shutdown)
reg |= SHUTDOWN_CTRL1_OVERRIDE_S2;
@@ -295,6 +312,21 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
return IRQ_HANDLED;
}
+static const struct spmi_temp_alarm_data spmi_temp_alarm_data = {
+ .temp_map = &temp_map_gen1,
+ .get_temp_stage = qpnp_tm_gen1_get_temp_stage,
+};
+
+static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_data = {
+ .temp_map = &temp_map_gen1,
+ .get_temp_stage = qpnp_tm_gen2_get_temp_stage,
+};
+
+static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_rev1_data = {
+ .temp_map = &temp_map_gen2_v1,
+ .get_temp_stage = qpnp_tm_gen2_get_temp_stage,
+};
+
/*
* This function initializes the internal temp value based on only the
* current thermal stage and threshold. Setup threshold control and
@@ -302,7 +334,6 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
*/
static int qpnp_tm_init(struct qpnp_tm_chip *chip)
{
- unsigned int stage;
int ret;
u8 reg = 0;
int crit_temp;
@@ -316,16 +347,13 @@ static int qpnp_tm_init(struct qpnp_tm_chip *chip)
chip->thresh = reg & SHUTDOWN_CTRL1_THRESHOLD_MASK;
chip->temp = DEFAULT_TEMP;
- ret = qpnp_tm_get_temp_stage(chip);
+ ret = chip->data->get_temp_stage(chip);
if (ret < 0)
goto out;
chip->stage = ret;
- stage = chip->subtype == QPNP_TM_SUBTYPE_GEN1
- ? chip->stage : alarm_state_map[chip->stage];
-
- if (stage)
- chip->temp = qpnp_tm_decode_temp(chip, stage);
+ if (chip->stage)
+ chip->temp = qpnp_tm_decode_temp(chip, chip->stage);
mutex_unlock(&chip->lock);
@@ -439,10 +467,15 @@ static int qpnp_tm_probe(struct platform_device *pdev)
}
chip->subtype = subtype;
- if (subtype == QPNP_TM_SUBTYPE_GEN2 && dig_major >= 1)
- chip->temp_map = &temp_map_gen2_v1;
+
+ if (subtype == QPNP_TM_SUBTYPE_GEN1)
+ chip->data = &spmi_temp_alarm_data;
+ else if (subtype == QPNP_TM_SUBTYPE_GEN2 && dig_major >= 1)
+ chip->data = &spmi_temp_alarm_gen2_rev1_data;
+ else if (subtype == QPNP_TM_SUBTYPE_GEN2)
+ chip->data = &spmi_temp_alarm_gen2_data;
else
- chip->temp_map = &temp_map_gen1;
+ return -ENODEV;
/*
* Register the sensor before initializing the hardware to be able to
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v3 3/5 RESEND] thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp Alarm subtypes
2025-03-20 20:24 [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes Anjelique Melendez
2025-03-20 20:24 ` [PATCH v3 1/5 RESEND] thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required Anjelique Melendez
2025-03-20 20:24 ` [PATCH v3 2/5 RESEND] thermal: qcom-spmi-temp-alarm: Add temp alarm data struct based on HW subtype Anjelique Melendez
@ 2025-03-20 20:24 ` Anjelique Melendez
2025-04-10 21:01 ` Dmitry Baryshkov
2025-04-18 11:15 ` Daniel Lezcano
2025-03-20 20:24 ` [PATCH v3 4/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC peripherals Anjelique Melendez
` (2 subsequent siblings)
5 siblings, 2 replies; 17+ messages in thread
From: Anjelique Melendez @ 2025-03-20 20:24 UTC (permalink / raw)
To: amitk, thara.gopinath, rafael, daniel.lezcano
Cc: rui.zhang, lukasz.luba, david.collins, srinivas.kandagatla,
stefan.schmidt, quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
In preparation to support newer temp alarm subtypes, add the "ops" and
"configure_trip_temps" references to spmi_temp_alarm_data. This will
allow for each Temp Alarm subtype to define its own
thermal_zone_device_ops and properly configure thermal trip temperature.
Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
---
drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 38 ++++++++++++++-------
1 file changed, 26 insertions(+), 12 deletions(-)
diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
index 1cc9369ca9e1..514772e94a28 100644
--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2011-2015, 2017, 2020, The Linux Foundation. All rights reserved.
- * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2024-2025, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/bitfield.h>
@@ -71,8 +71,10 @@ static const long temp_map_gen2_v1[THRESH_COUNT][STAGE_COUNT] = {
struct qpnp_tm_chip;
struct spmi_temp_alarm_data {
+ const struct thermal_zone_device_ops *ops;
const long (*temp_map)[THRESH_COUNT][STAGE_COUNT];
int (*get_temp_stage)(struct qpnp_tm_chip *chip);
+ int (*configure_trip_temps)(struct qpnp_tm_chip *chip);
};
struct qpnp_tm_chip {
@@ -312,18 +314,39 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
return IRQ_HANDLED;
}
+static int qpnp_tm_configure_trip_temp(struct qpnp_tm_chip *chip)
+{
+ int crit_temp, ret;
+
+ mutex_unlock(&chip->lock);
+
+ ret = thermal_zone_get_crit_temp(chip->tz_dev, &crit_temp);
+ if (ret)
+ crit_temp = THERMAL_TEMP_INVALID;
+
+ mutex_lock(&chip->lock);
+
+ return qpnp_tm_update_critical_trip_temp(chip, crit_temp);
+}
+
static const struct spmi_temp_alarm_data spmi_temp_alarm_data = {
+ .ops = &qpnp_tm_sensor_ops,
.temp_map = &temp_map_gen1,
+ .configure_trip_temps = qpnp_tm_configure_trip_temp,
.get_temp_stage = qpnp_tm_gen1_get_temp_stage,
};
static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_data = {
+ .ops = &qpnp_tm_sensor_ops,
.temp_map = &temp_map_gen1,
+ .configure_trip_temps = qpnp_tm_configure_trip_temp,
.get_temp_stage = qpnp_tm_gen2_get_temp_stage,
};
static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_rev1_data = {
+ .ops = &qpnp_tm_sensor_ops,
.temp_map = &temp_map_gen2_v1,
+ .configure_trip_temps = qpnp_tm_configure_trip_temp,
.get_temp_stage = qpnp_tm_gen2_get_temp_stage,
};
@@ -336,7 +359,6 @@ static int qpnp_tm_init(struct qpnp_tm_chip *chip)
{
int ret;
u8 reg = 0;
- int crit_temp;
mutex_lock(&chip->lock);
@@ -355,15 +377,7 @@ static int qpnp_tm_init(struct qpnp_tm_chip *chip)
if (chip->stage)
chip->temp = qpnp_tm_decode_temp(chip, chip->stage);
- mutex_unlock(&chip->lock);
-
- ret = thermal_zone_get_crit_temp(chip->tz_dev, &crit_temp);
- if (ret)
- crit_temp = THERMAL_TEMP_INVALID;
-
- mutex_lock(&chip->lock);
-
- ret = qpnp_tm_update_critical_trip_temp(chip, crit_temp);
+ ret = chip->data->configure_trip_temps(chip);
if (ret < 0)
goto out;
@@ -483,7 +497,7 @@ static int qpnp_tm_probe(struct platform_device *pdev)
* before the hardware initialization is completed.
*/
chip->tz_dev = devm_thermal_of_zone_register(
- &pdev->dev, 0, chip, &qpnp_tm_sensor_ops);
+ &pdev->dev, 0, chip, chip->data->ops);
if (IS_ERR(chip->tz_dev))
return dev_err_probe(&pdev->dev, PTR_ERR(chip->tz_dev),
"failed to register sensor\n");
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v3 4/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC peripherals
2025-03-20 20:24 [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes Anjelique Melendez
` (2 preceding siblings ...)
2025-03-20 20:24 ` [PATCH v3 3/5 RESEND] thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp Alarm subtypes Anjelique Melendez
@ 2025-03-20 20:24 ` Anjelique Melendez
2025-04-10 21:03 ` Dmitry Baryshkov
2025-04-18 11:19 ` Daniel Lezcano
2025-03-20 20:24 ` [PATCH v3 5/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for LITE " Anjelique Melendez
2025-04-08 21:51 ` [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes Anjelique Melendez
5 siblings, 2 replies; 17+ messages in thread
From: Anjelique Melendez @ 2025-03-20 20:24 UTC (permalink / raw)
To: amitk, thara.gopinath, rafael, daniel.lezcano
Cc: rui.zhang, lukasz.luba, david.collins, srinivas.kandagatla,
stefan.schmidt, quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
Add support for TEMP_ALARM GEN2 PMIC peripherals with digital major
revision 2. This revision utilizes individual temp DAC registers
to set the threshold temperature for over-temperature stages 1,
2, and 3 instead of a single register to specify a set of
thresholds.
Signed-off-by: David Collins <david.collins@oss.qualcomm.com>
Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
---
drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 136 ++++++++++++++++++++
1 file changed, 136 insertions(+)
diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
index 514772e94a28..efd2b6534127 100644
--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
@@ -26,6 +26,11 @@
#define QPNP_TM_REG_SHUTDOWN_CTRL1 0x40
#define QPNP_TM_REG_ALARM_CTRL 0x46
+/* TEMP_DAC_STGx registers are only present for TEMP_GEN2 v2.0 */
+#define QPNP_TM_REG_TEMP_DAC_STG1 0x47
+#define QPNP_TM_REG_TEMP_DAC_STG2 0x48
+#define QPNP_TM_REG_TEMP_DAC_STG3 0x49
+
#define QPNP_TM_TYPE 0x09
#define QPNP_TM_SUBTYPE_GEN1 0x08
#define QPNP_TM_SUBTYPE_GEN2 0x09
@@ -65,6 +70,25 @@ static const long temp_map_gen2_v1[THRESH_COUNT][STAGE_COUNT] = {
#define TEMP_STAGE_HYSTERESIS 2000
+/*
+ * For TEMP_GEN2 v2.0, TEMP_DAC_STG1/2/3 registers are used to set the threshold
+ * for each stage independently.
+ * TEMP_DAC_STG* = 0 --> 80 C
+ * Each 8 step increase in TEMP_DAC_STG* value corresponds to 5 C (5000 mC).
+ */
+#define TEMP_DAC_MIN 80000
+#define TEMP_DAC_SCALE_NUM 8
+#define TEMP_DAC_SCALE_DEN 5000
+
+#define TEMP_DAC_TEMP_TO_REG(temp) \
+ (((temp) - TEMP_DAC_MIN) * TEMP_DAC_SCALE_NUM / TEMP_DAC_SCALE_DEN)
+#define TEMP_DAC_REG_TO_TEMP(reg) \
+ (TEMP_DAC_MIN + (reg) * TEMP_DAC_SCALE_DEN / TEMP_DAC_SCALE_NUM)
+
+static const long temp_dac_max[STAGE_COUNT] = {
+ 119375, 159375, 159375
+};
+
/* Temperature in Milli Celsius reported during stage 0 if no ADC is present */
#define DEFAULT_TEMP 37000
@@ -73,6 +97,7 @@ struct qpnp_tm_chip;
struct spmi_temp_alarm_data {
const struct thermal_zone_device_ops *ops;
const long (*temp_map)[THRESH_COUNT][STAGE_COUNT];
+ int (*setup)(struct qpnp_tm_chip *chip);
int (*get_temp_stage)(struct qpnp_tm_chip *chip);
int (*configure_trip_temps)(struct qpnp_tm_chip *chip);
};
@@ -88,6 +113,7 @@ struct qpnp_tm_chip {
unsigned int thresh;
unsigned int stage;
unsigned int base;
+ unsigned int ntrips;
/* protects .thresh, .stage and chip registers */
struct mutex lock;
bool initialized;
@@ -305,6 +331,52 @@ static const struct thermal_zone_device_ops qpnp_tm_sensor_ops = {
.set_trip_temp = qpnp_tm_set_trip_temp,
};
+static int qpnp_tm_gen2_rev2_set_temp_thresh(struct qpnp_tm_chip *chip, int trip, int temp)
+{
+ int ret, temp_cfg;
+ u8 reg;
+
+ if (trip < 0 || trip >= STAGE_COUNT) {
+ dev_err(chip->dev, "invalid TEMP_DAC trip = %d\n", trip);
+ return -EINVAL;
+ } else if (temp < TEMP_DAC_MIN || temp > temp_dac_max[trip]) {
+ dev_err(chip->dev, "invalid TEMP_DAC temp = %d\n", temp);
+ return -EINVAL;
+ }
+
+ reg = TEMP_DAC_TEMP_TO_REG(temp);
+ temp_cfg = TEMP_DAC_REG_TO_TEMP(reg);
+
+ ret = qpnp_tm_write(chip, QPNP_TM_REG_TEMP_DAC_STG1 + trip, reg);
+ if (ret < 0) {
+ dev_err(chip->dev, "TEMP_DAC_STG write failed, ret=%d\n", ret);
+ return ret;
+ }
+
+ chip->temp_thresh_map[trip] = temp_cfg;
+
+ return 0;
+}
+
+static int qpnp_tm_gen2_rev2_set_trip_temp(struct thermal_zone_device *tz,
+ const struct thermal_trip *trip, int temp)
+{
+ unsigned int trip_index = THERMAL_TRIP_PRIV_TO_INT(trip->priv);
+ struct qpnp_tm_chip *chip = thermal_zone_device_priv(tz);
+ int ret;
+
+ mutex_lock(&chip->lock);
+ ret = qpnp_tm_gen2_rev2_set_temp_thresh(chip, trip_index, temp);
+ mutex_unlock(&chip->lock);
+
+ return ret;
+}
+
+static const struct thermal_zone_device_ops qpnp_tm_gen2_rev2_sensor_ops = {
+ .get_temp = qpnp_tm_get_temp,
+ .set_trip_temp = qpnp_tm_gen2_rev2_set_trip_temp,
+};
+
static irqreturn_t qpnp_tm_isr(int irq, void *data)
{
struct qpnp_tm_chip *chip = data;
@@ -329,6 +401,58 @@ static int qpnp_tm_configure_trip_temp(struct qpnp_tm_chip *chip)
return qpnp_tm_update_critical_trip_temp(chip, crit_temp);
}
+/* Configure TEMP_DAC registers based on DT thermal_zone trips */
+static int qpnp_tm_gen2_rev2_configure_trip_temps_cb(struct thermal_trip *trip, void *data)
+{
+ struct qpnp_tm_chip *chip = data;
+ int ret;
+
+ trip->priv = THERMAL_INT_TO_TRIP_PRIV(chip->ntrips);
+ ret = qpnp_tm_gen2_rev2_set_temp_thresh(chip, chip->ntrips, trip->temperature);
+ chip->ntrips++;
+
+ return ret;
+}
+
+static int qpnp_tm_gen2_rev2_configure_trip_temps(struct qpnp_tm_chip *chip)
+{
+ int ret, i;
+
+ ret = thermal_zone_for_each_trip(chip->tz_dev,
+ qpnp_tm_gen2_rev2_configure_trip_temps_cb, chip);
+ if (ret < 0)
+ return ret;
+
+ /* Verify that trips are strictly increasing. */
+ for (i = 1; i < STAGE_COUNT; i++) {
+ if (chip->temp_thresh_map[i] <= chip->temp_thresh_map[i - 1]) {
+ dev_err(chip->dev, "Threshold %d=%ld <= threshold %d=%ld\n",
+ i, chip->temp_thresh_map[i], i - 1,
+ chip->temp_thresh_map[i - 1]);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+/* Read the hardware default TEMP_DAC stage threshold temperatures */
+static int qpnp_tm_gen2_rev2_setup(struct qpnp_tm_chip *chip)
+{
+ int ret, i;
+ u8 reg = 0;
+
+ for (i = 0; i < STAGE_COUNT; i++) {
+ ret = qpnp_tm_read(chip, QPNP_TM_REG_TEMP_DAC_STG1 + i, ®);
+ if (ret < 0)
+ return ret;
+
+ chip->temp_thresh_map[i] = TEMP_DAC_REG_TO_TEMP(reg);
+ }
+
+ return 0;
+}
+
static const struct spmi_temp_alarm_data spmi_temp_alarm_data = {
.ops = &qpnp_tm_sensor_ops,
.temp_map = &temp_map_gen1,
@@ -350,6 +474,13 @@ static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_rev1_data = {
.get_temp_stage = qpnp_tm_gen2_get_temp_stage,
};
+static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_rev2_data = {
+ .ops = &qpnp_tm_gen2_rev2_sensor_ops,
+ .setup = qpnp_tm_gen2_rev2_setup,
+ .configure_trip_temps = qpnp_tm_gen2_rev2_configure_trip_temps,
+ .get_temp_stage = qpnp_tm_gen2_get_temp_stage,
+};
+
/*
* This function initializes the internal temp value based on only the
* current thermal stage and threshold. Setup threshold control and
@@ -484,6 +615,8 @@ static int qpnp_tm_probe(struct platform_device *pdev)
if (subtype == QPNP_TM_SUBTYPE_GEN1)
chip->data = &spmi_temp_alarm_data;
+ else if (subtype == QPNP_TM_SUBTYPE_GEN2 && dig_major >= 2)
+ chip->data = &spmi_temp_alarm_gen2_rev2_data;
else if (subtype == QPNP_TM_SUBTYPE_GEN2 && dig_major >= 1)
chip->data = &spmi_temp_alarm_gen2_rev1_data;
else if (subtype == QPNP_TM_SUBTYPE_GEN2)
@@ -491,6 +624,9 @@ static int qpnp_tm_probe(struct platform_device *pdev)
else
return -ENODEV;
+ if (chip->data->setup)
+ chip->data->setup(chip);
+
/*
* Register the sensor before initializing the hardware to be able to
* read the trip points. get_temp() returns the default temperature
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v3 5/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for LITE PMIC peripherals
2025-03-20 20:24 [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes Anjelique Melendez
` (3 preceding siblings ...)
2025-03-20 20:24 ` [PATCH v3 4/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC peripherals Anjelique Melendez
@ 2025-03-20 20:24 ` Anjelique Melendez
2025-04-10 21:04 ` Dmitry Baryshkov
2025-04-08 21:51 ` [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes Anjelique Melendez
5 siblings, 1 reply; 17+ messages in thread
From: Anjelique Melendez @ 2025-03-20 20:24 UTC (permalink / raw)
To: amitk, thara.gopinath, rafael, daniel.lezcano
Cc: rui.zhang, lukasz.luba, david.collins, srinivas.kandagatla,
stefan.schmidt, quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
Add support for TEMP_ALARM LITE PMIC peripherals. This subtype
utilizes a pair of registers to configure a warning interrupt
threshold temperature and an automatic hardware shutdown
threshold temperature.
Signed-off-by: David Collins <david.collins@oss.qualcomm.com>
Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
---
drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 204 +++++++++++++++++++-
1 file changed, 203 insertions(+), 1 deletion(-)
diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
index efd2b6534127..2547a69dbd07 100644
--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
@@ -23,6 +23,7 @@
#define QPNP_TM_REG_TYPE 0x04
#define QPNP_TM_REG_SUBTYPE 0x05
#define QPNP_TM_REG_STATUS 0x08
+#define QPNP_TM_REG_IRQ_STATUS 0x10
#define QPNP_TM_REG_SHUTDOWN_CTRL1 0x40
#define QPNP_TM_REG_ALARM_CTRL 0x46
@@ -30,14 +31,20 @@
#define QPNP_TM_REG_TEMP_DAC_STG1 0x47
#define QPNP_TM_REG_TEMP_DAC_STG2 0x48
#define QPNP_TM_REG_TEMP_DAC_STG3 0x49
+#define QPNP_TM_REG_LITE_TEMP_CFG1 0x50
+#define QPNP_TM_REG_LITE_TEMP_CFG2 0x51
#define QPNP_TM_TYPE 0x09
#define QPNP_TM_SUBTYPE_GEN1 0x08
#define QPNP_TM_SUBTYPE_GEN2 0x09
+#define QPNP_TM_SUBTYPE_LITE 0xC0
#define STATUS_GEN1_STAGE_MASK GENMASK(1, 0)
#define STATUS_GEN2_STATE_MASK GENMASK(6, 4)
+/* IRQ status only needed for TEMP_ALARM_LITE */
+#define IRQ_STATUS_MASK BIT(0)
+
#define SHUTDOWN_CTRL1_OVERRIDE_S2 BIT(6)
#define SHUTDOWN_CTRL1_THRESHOLD_MASK GENMASK(1, 0)
@@ -45,6 +52,8 @@
#define ALARM_CTRL_FORCE_ENABLE BIT(7)
+#define LITE_TEMP_CFG_THRESHOLD_MASK GENMASK(3, 2)
+
#define THRESH_COUNT 4
#define STAGE_COUNT 3
@@ -89,6 +98,19 @@ static const long temp_dac_max[STAGE_COUNT] = {
119375, 159375, 159375
};
+/*
+ * TEMP_ALARM_LITE has two stages: warning and shutdown with independently
+ * configured threshold temperatures.
+ */
+
+static const long temp_lite_warning_map[THRESH_COUNT] = {
+ 115000, 125000, 135000, 145000
+};
+
+static const long temp_lite_shutdown_map[THRESH_COUNT] = {
+ 135000, 145000, 160000, 175000
+};
+
/* Temperature in Milli Celsius reported during stage 0 if no ADC is present */
#define DEFAULT_TEMP 37000
@@ -198,6 +220,24 @@ static int qpnp_tm_gen2_get_temp_stage(struct qpnp_tm_chip *chip)
return alarm_state_map[ret];
}
+/**
+ * qpnp_tm_lite_get_temp_stage() - return over-temperature stage
+ * @chip: Pointer to the qpnp_tm chip
+ *
+ * Return: alarm interrupt state on success, or errno on failure.
+ */
+static int qpnp_tm_lite_get_temp_stage(struct qpnp_tm_chip *chip)
+{
+ u8 reg = 0;
+ int ret;
+
+ ret = qpnp_tm_read(chip, QPNP_TM_REG_IRQ_STATUS, ®);
+ if (ret < 0)
+ return ret;
+
+ return reg & IRQ_STATUS_MASK;
+}
+
/*
* This function updates the internal temp value based on the
* current thermal stage and threshold as well as the previous stage
@@ -377,6 +417,96 @@ static const struct thermal_zone_device_ops qpnp_tm_gen2_rev2_sensor_ops = {
.set_trip_temp = qpnp_tm_gen2_rev2_set_trip_temp,
};
+static int qpnp_tm_lite_set_temp_thresh(struct qpnp_tm_chip *chip, int trip, int temp)
+{
+ int ret, temp_cfg, i;
+ const long *temp_map;
+ u16 addr;
+ u8 reg, thresh;
+
+ if (trip < 0 || trip >= STAGE_COUNT) {
+ dev_err(chip->dev, "invalid TEMP_LITE trip = %d\n", trip);
+ return -EINVAL;
+ }
+
+ switch (trip) {
+ case 0:
+ temp_map = temp_lite_warning_map;
+ addr = QPNP_TM_REG_LITE_TEMP_CFG1;
+ break;
+ case 1:
+ /*
+ * The second trip point is purely in software to facilitate
+ * a controlled shutdown after the warning threshold is crossed
+ * but before the automatic hardware shutdown threshold is
+ * crossed.
+ */
+ return 0;
+ case 2:
+ temp_map = temp_lite_shutdown_map;
+ addr = QPNP_TM_REG_LITE_TEMP_CFG2;
+ break;
+ default:
+ return 0;
+ }
+
+ if (temp < temp_map[THRESH_MIN] || temp > temp_map[THRESH_MAX]) {
+ dev_err(chip->dev, "invalid TEMP_LITE temp = %d\n", temp);
+ return -EINVAL;
+ }
+
+ thresh = 0;
+ temp_cfg = temp_map[thresh];
+ for (i = THRESH_MAX; i >= THRESH_MIN; i--) {
+ if (temp >= temp_map[i]) {
+ thresh = i;
+ temp_cfg = temp_map[i];
+ break;
+ }
+ }
+
+ if (temp_cfg == chip->temp_thresh_map[trip])
+ return 0;
+
+ ret = qpnp_tm_read(chip, addr, ®);
+ if (ret < 0) {
+ dev_err(chip->dev, "LITE_TEMP_CFG read failed, ret=%d\n", ret);
+ return ret;
+ }
+
+ reg &= ~LITE_TEMP_CFG_THRESHOLD_MASK;
+ reg |= FIELD_PREP(LITE_TEMP_CFG_THRESHOLD_MASK, thresh);
+
+ ret = qpnp_tm_write(chip, addr, reg);
+ if (ret < 0) {
+ dev_err(chip->dev, "LITE_TEMP_CFG write failed, ret=%d\n", ret);
+ return ret;
+ }
+
+ chip->temp_thresh_map[trip] = temp_cfg;
+
+ return 0;
+}
+
+static int qpnp_tm_lite_set_trip_temp(struct thermal_zone_device *tz,
+ const struct thermal_trip *trip, int temp)
+{
+ unsigned int trip_index = THERMAL_TRIP_PRIV_TO_INT(trip->priv);
+ struct qpnp_tm_chip *chip = thermal_zone_device_priv(tz);
+ int ret;
+
+ mutex_lock(&chip->lock);
+ ret = qpnp_tm_lite_set_temp_thresh(chip, trip_index, temp);
+ mutex_unlock(&chip->lock);
+
+ return ret;
+}
+
+static const struct thermal_zone_device_ops qpnp_tm_lite_sensor_ops = {
+ .get_temp = qpnp_tm_get_temp,
+ .set_trip_temp = qpnp_tm_lite_set_trip_temp,
+};
+
static irqreturn_t qpnp_tm_isr(int irq, void *data)
{
struct qpnp_tm_chip *chip = data;
@@ -453,6 +583,68 @@ static int qpnp_tm_gen2_rev2_setup(struct qpnp_tm_chip *chip)
return 0;
}
+/* Configure TEMP_LITE registers based on DT thermal_zone trips */
+static int qpnp_tm_lite_configure_trip_temps_cb(struct thermal_trip *trip, void *data)
+{
+ struct qpnp_tm_chip *chip = data;
+ int ret;
+
+ trip->priv = THERMAL_INT_TO_TRIP_PRIV(chip->ntrips);
+ ret = qpnp_tm_lite_set_temp_thresh(chip, chip->ntrips, trip->temperature);
+ chip->ntrips++;
+
+ return ret;
+}
+
+static int qpnp_tm_lite_configure_trip_temps(struct qpnp_tm_chip *chip)
+{
+ int ret;
+
+ ret = thermal_zone_for_each_trip(chip->tz_dev, qpnp_tm_lite_configure_trip_temps_cb, chip);
+ if (ret < 0)
+ return ret;
+
+ /* Verify that trips are strictly increasing. */
+ if (chip->temp_thresh_map[2] <= chip->temp_thresh_map[0]) {
+ dev_err(chip->dev, "Threshold 2=%ld <= threshold 0=%ld\n",
+ chip->temp_thresh_map[2], chip->temp_thresh_map[0]);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Read the hardware default TEMP_LITE stage threshold temperatures */
+static int qpnp_tm_lite_setup(struct qpnp_tm_chip *chip)
+{
+ int ret, thresh;
+ u8 reg = 0;
+
+ /*
+ * Store the warning trip temp in temp_thresh_map[0] and the shutdown trip
+ * temp in temp_thresh_map[2]. The second trip point is purely in software
+ * to facilitate a controlled shutdown after the warning threshold is
+ * crossed but before the automatic hardware shutdown threshold is
+ * crossed. Thus, there is no register to read for the second trip
+ * point.
+ */
+ ret = qpnp_tm_read(chip, QPNP_TM_REG_LITE_TEMP_CFG1, ®);
+ if (ret < 0)
+ return ret;
+
+ thresh = FIELD_GET(LITE_TEMP_CFG_THRESHOLD_MASK, reg);
+ chip->temp_thresh_map[0] = temp_lite_warning_map[thresh];
+
+ ret = qpnp_tm_read(chip, QPNP_TM_REG_LITE_TEMP_CFG2, ®);
+ if (ret < 0)
+ return ret;
+
+ thresh = FIELD_GET(LITE_TEMP_CFG_THRESHOLD_MASK, reg);
+ chip->temp_thresh_map[2] = temp_lite_shutdown_map[thresh];
+
+ return 0;
+}
+
static const struct spmi_temp_alarm_data spmi_temp_alarm_data = {
.ops = &qpnp_tm_sensor_ops,
.temp_map = &temp_map_gen1,
@@ -481,6 +673,13 @@ static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_rev2_data = {
.get_temp_stage = qpnp_tm_gen2_get_temp_stage,
};
+static const struct spmi_temp_alarm_data spmi_temp_alarm_lite_data = {
+ .ops = &qpnp_tm_lite_sensor_ops,
+ .setup = qpnp_tm_lite_setup,
+ .configure_trip_temps = qpnp_tm_lite_configure_trip_temps,
+ .get_temp_stage = qpnp_tm_lite_get_temp_stage,
+};
+
/*
* This function initializes the internal temp value based on only the
* current thermal stage and threshold. Setup threshold control and
@@ -605,7 +804,8 @@ static int qpnp_tm_probe(struct platform_device *pdev)
}
if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1
- && subtype != QPNP_TM_SUBTYPE_GEN2)) {
+ && subtype != QPNP_TM_SUBTYPE_GEN2
+ && subtype != QPNP_TM_SUBTYPE_LITE)) {
dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n",
type, subtype);
return -ENODEV;
@@ -621,6 +821,8 @@ static int qpnp_tm_probe(struct platform_device *pdev)
chip->data = &spmi_temp_alarm_gen2_rev1_data;
else if (subtype == QPNP_TM_SUBTYPE_GEN2)
chip->data = &spmi_temp_alarm_gen2_data;
+ else if (subtype == QPNP_TM_SUBTYPE_LITE)
+ chip->data = &spmi_temp_alarm_lite_data;
else
return -ENODEV;
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes
2025-03-20 20:24 [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes Anjelique Melendez
` (4 preceding siblings ...)
2025-03-20 20:24 ` [PATCH v3 5/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for LITE " Anjelique Melendez
@ 2025-04-08 21:51 ` Anjelique Melendez
5 siblings, 0 replies; 17+ messages in thread
From: Anjelique Melendez @ 2025-04-08 21:51 UTC (permalink / raw)
To: amitk, thara.gopinath, rafael, daniel.lezcano
Cc: rui.zhang, lukasz.luba, david.collins, srinivas.kandagatla,
stefan.schmidt, quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
On 3/20/2025 1:24 PM, Anjelique Melendez wrote:
> Add support in the qcom-spmi-temp-alarm driver for the new PMIC
> TEMP_ALARM peripheral subtypes: GEN2 rev 2 and LITE. The GEN2 rev 2
> subtype provides greater flexibility in temperature threshold
> specification by using an independent register value to configure
> each of the three thresholds. The LITE subtype utilizes a simplified
> set of control registers to configure two thresholds: warning and
> shutdown. While at it refactor the qcom-spmi-temp-alarm driver to limit
> code reuse and if/else statements when deciphering between TEMP_ALARM
> peripheral subtypes.
>
> Also add support to avoid a potential issue on certain versions of
> the TEMP_ALARM GEN2 subtype when automatic stage 2 partial shutdown
> is disabled.
>
> This patch series is a continuation of older series from 7/2024
> (https://lore.kernel.org/all/20240729231259.2122976-1-quic_amelende@quicinc.com/)
> but current series has been reworked to address the change in thermal framework to
> update .set_trip_temp() callback function variables
> (https://lore.kernel.org/all/8392906.T7Z3S40VBb@rjwysocki.net/)
>
> Changes since v2:
> - Updated function name to include "gen1" in patch 2/5
> - Added Dmitry's reviewed-by tag in patch 2/5
> - link: https://lore.kernel.org/all/20250225192429.2328092-1-anjelique.melendez@oss.qualcomm.com/
> Changes since v1:
> - Remove unnecessary moving of code
> - Added new v2 patch 3/5 add a preparation patch to v1 patch 2/5
> - Updated temp alarm data function names to be consistently named
> - link: https://lore.kernel.org/all/20250213210403.3396392-1-anjelique.melendez@oss.qualcomm.com/
>
> Anjelique Melendez (4):
> thermal: qcom-spmi-temp-alarm: Add temp alarm data struct based on HW
> subtype
> thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp
> Alarm subtypes
> thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC
> peripherals
> thermal: qcom-spmi-temp-alarm: add support for LITE PMIC peripherals
>
> David Collins (1):
> thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required
>
> drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 515 ++++++++++++++++++--
> 1 file changed, 464 insertions(+), 51 deletions(-)
>
Hi Amit and Thara,
Can you take a look at changes when you have a chance.
Thanks,
Anjelique
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3 1/5 RESEND] thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required
2025-03-20 20:24 ` [PATCH v3 1/5 RESEND] thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required Anjelique Melendez
@ 2025-04-10 21:01 ` Dmitry Baryshkov
2025-04-18 10:54 ` Daniel Lezcano
1 sibling, 0 replies; 17+ messages in thread
From: Dmitry Baryshkov @ 2025-04-10 21:01 UTC (permalink / raw)
To: Anjelique Melendez
Cc: amitk, thara.gopinath, rafael, daniel.lezcano, rui.zhang,
lukasz.luba, david.collins, srinivas.kandagatla, stefan.schmidt,
quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
On Thu, Mar 20, 2025 at 01:24:04PM -0700, Anjelique Melendez wrote:
> From: David Collins <david.collins@oss.qualcomm.com>
>
> Certain TEMP_ALARM GEN2 PMIC peripherals need over-temperature
> stage 2 automatic PMIC partial shutdown to be enabled in order to
> avoid repeated faults in the event of reaching over-temperature
> stage 3. Modify the stage 2 shutdown control logic to ensure that
> stage 2 shutdown is enabled on all affected PMICs. Read the
> digital major and minor revision registers to identify these
> PMICs.
It would be nice to mention affected PMICs (at least thsoe supported
upstream).
>
> Signed-off-by: David Collins <david.collins@oss.qualcomm.com>
> Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
> ---
> drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 32 +++++++++++++++++++--
> 1 file changed, 30 insertions(+), 2 deletions(-)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3 3/5 RESEND] thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp Alarm subtypes
2025-03-20 20:24 ` [PATCH v3 3/5 RESEND] thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp Alarm subtypes Anjelique Melendez
@ 2025-04-10 21:01 ` Dmitry Baryshkov
2025-04-18 11:15 ` Daniel Lezcano
1 sibling, 0 replies; 17+ messages in thread
From: Dmitry Baryshkov @ 2025-04-10 21:01 UTC (permalink / raw)
To: Anjelique Melendez
Cc: amitk, thara.gopinath, rafael, daniel.lezcano, rui.zhang,
lukasz.luba, david.collins, srinivas.kandagatla, stefan.schmidt,
quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
On Thu, Mar 20, 2025 at 01:24:06PM -0700, Anjelique Melendez wrote:
> In preparation to support newer temp alarm subtypes, add the "ops" and
> "configure_trip_temps" references to spmi_temp_alarm_data. This will
> allow for each Temp Alarm subtype to define its own
> thermal_zone_device_ops and properly configure thermal trip temperature.
>
> Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
> ---
> drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 38 ++++++++++++++-------
> 1 file changed, 26 insertions(+), 12 deletions(-)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3 4/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC peripherals
2025-03-20 20:24 ` [PATCH v3 4/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC peripherals Anjelique Melendez
@ 2025-04-10 21:03 ` Dmitry Baryshkov
2025-04-18 11:19 ` Daniel Lezcano
1 sibling, 0 replies; 17+ messages in thread
From: Dmitry Baryshkov @ 2025-04-10 21:03 UTC (permalink / raw)
To: Anjelique Melendez
Cc: amitk, thara.gopinath, rafael, daniel.lezcano, rui.zhang,
lukasz.luba, david.collins, srinivas.kandagatla, stefan.schmidt,
quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
On Thu, Mar 20, 2025 at 01:24:07PM -0700, Anjelique Melendez wrote:
> Add support for TEMP_ALARM GEN2 PMIC peripherals with digital major
> revision 2. This revision utilizes individual temp DAC registers
> to set the threshold temperature for over-temperature stages 1,
> 2, and 3 instead of a single register to specify a set of
> thresholds.
>
> Signed-off-by: David Collins <david.collins@oss.qualcomm.com>
> Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
> ---
> drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 136 ++++++++++++++++++++
> 1 file changed, 136 insertions(+)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3 5/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for LITE PMIC peripherals
2025-03-20 20:24 ` [PATCH v3 5/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for LITE " Anjelique Melendez
@ 2025-04-10 21:04 ` Dmitry Baryshkov
0 siblings, 0 replies; 17+ messages in thread
From: Dmitry Baryshkov @ 2025-04-10 21:04 UTC (permalink / raw)
To: Anjelique Melendez
Cc: amitk, thara.gopinath, rafael, daniel.lezcano, rui.zhang,
lukasz.luba, david.collins, srinivas.kandagatla, stefan.schmidt,
quic_tsoni, linux-arm-msm, linux-pm, linux-kernel,
dmitry.baryshkov
On Thu, Mar 20, 2025 at 01:24:08PM -0700, Anjelique Melendez wrote:
> Add support for TEMP_ALARM LITE PMIC peripherals. This subtype
> utilizes a pair of registers to configure a warning interrupt
> threshold temperature and an automatic hardware shutdown
> threshold temperature.
>
> Signed-off-by: David Collins <david.collins@oss.qualcomm.com>
> Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
> ---
> drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 204 +++++++++++++++++++-
> 1 file changed, 203 insertions(+), 1 deletion(-)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3 1/5 RESEND] thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required
2025-03-20 20:24 ` [PATCH v3 1/5 RESEND] thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required Anjelique Melendez
2025-04-10 21:01 ` Dmitry Baryshkov
@ 2025-04-18 10:54 ` Daniel Lezcano
1 sibling, 0 replies; 17+ messages in thread
From: Daniel Lezcano @ 2025-04-18 10:54 UTC (permalink / raw)
To: Anjelique Melendez
Cc: amitk, thara.gopinath, rafael, rui.zhang, lukasz.luba,
david.collins, srinivas.kandagatla, stefan.schmidt, quic_tsoni,
linux-arm-msm, linux-pm, linux-kernel, dmitry.baryshkov
On Thu, Mar 20, 2025 at 01:24:04PM -0700, Anjelique Melendez wrote:
> From: David Collins <david.collins@oss.qualcomm.com>
>
> Certain TEMP_ALARM GEN2 PMIC peripherals need over-temperature
> stage 2 automatic PMIC partial shutdown to be enabled in order to
> avoid repeated faults in the event of reaching over-temperature
> stage 3. Modify the stage 2 shutdown control logic to ensure that
> stage 2 shutdown is enabled on all affected PMICs. Read the
> digital major and minor revision registers to identify these
> PMICs.
>
> Signed-off-by: David Collins <david.collins@oss.qualcomm.com>
> Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
> ---
> drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 32 +++++++++++++++++++--
> 1 file changed, 30 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
> index c2d59cbfaea9..b2077ff9fe73 100644
> --- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
> +++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /*
> * Copyright (c) 2011-2015, 2017, 2020, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
> */
>
> #include <linux/bitops.h>
> @@ -16,6 +17,7 @@
>
> #include "../thermal_hwmon.h"
>
> +#define QPNP_TM_REG_DIG_MINOR 0x00
> #define QPNP_TM_REG_DIG_MAJOR 0x01
> #define QPNP_TM_REG_TYPE 0x04
> #define QPNP_TM_REG_SUBTYPE 0x05
> @@ -71,6 +73,7 @@ struct qpnp_tm_chip {
> struct device *dev;
> struct thermal_zone_device *tz_dev;
> unsigned int subtype;
> + unsigned int dig_revision;
> long temp;
> unsigned int thresh;
> unsigned int stage;
> @@ -78,6 +81,7 @@ struct qpnp_tm_chip {
> /* protects .thresh, .stage and chip registers */
> struct mutex lock;
> bool initialized;
> + bool require_s2_shutdown;
>
> struct iio_channel *adc;
> const long (*temp_map)[THRESH_COUNT][STAGE_COUNT];
> @@ -255,7 +259,7 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip,
>
> skip:
> reg |= chip->thresh;
> - if (disable_s2_shutdown)
> + if (disable_s2_shutdown && !chip->require_s2_shutdown)
> reg |= SHUTDOWN_CTRL1_OVERRIDE_S2;
>
> return qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg);
> @@ -350,7 +354,7 @@ static int qpnp_tm_probe(struct platform_device *pdev)
> {
> struct qpnp_tm_chip *chip;
> struct device_node *node;
> - u8 type, subtype, dig_major;
> + u8 type, subtype, dig_major, dig_minor;
> u32 res;
> int ret, irq;
>
> @@ -403,6 +407,30 @@ static int qpnp_tm_probe(struct platform_device *pdev)
> return dev_err_probe(&pdev->dev, ret,
> "could not read dig_major\n");
>
> + ret = qpnp_tm_read(chip, QPNP_TM_REG_DIG_MINOR, &dig_minor);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "could not read dig_minor\n");
> + return ret;
> + }
> +
> + chip->dig_revision = (dig_major << 8) | dig_minor;
I would move this inside the block below.
> + if (chip->subtype == QPNP_TM_SUBTYPE_GEN2) {
> + /*
> + * Check if stage 2 automatic partial shutdown must remain
> + * enabled to avoid potential repeated faults upon reaching
> + * over-temperature stage 3.
> + */
> + switch (chip->dig_revision) {
> + case 0x0001:
> + case 0x0002:
> + case 0x0100:
> + case 0x0101:
> + chip->require_s2_shutdown = true;
> + break;
> + }
> + }
And move this block after the test below
> +
> if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1
> && subtype != QPNP_TM_SUBTYPE_GEN2)) {
> dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n",
> --
> 2.34.1
>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3 3/5 RESEND] thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp Alarm subtypes
2025-03-20 20:24 ` [PATCH v3 3/5 RESEND] thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp Alarm subtypes Anjelique Melendez
2025-04-10 21:01 ` Dmitry Baryshkov
@ 2025-04-18 11:15 ` Daniel Lezcano
2025-04-23 23:20 ` Anjelique Melendez
1 sibling, 1 reply; 17+ messages in thread
From: Daniel Lezcano @ 2025-04-18 11:15 UTC (permalink / raw)
To: Anjelique Melendez
Cc: amitk, thara.gopinath, rafael, rui.zhang, lukasz.luba,
david.collins, srinivas.kandagatla, stefan.schmidt, quic_tsoni,
linux-arm-msm, linux-pm, linux-kernel, dmitry.baryshkov
On Thu, Mar 20, 2025 at 01:24:06PM -0700, Anjelique Melendez wrote:
> In preparation to support newer temp alarm subtypes, add the "ops" and
> "configure_trip_temps" references to spmi_temp_alarm_data. This will
> allow for each Temp Alarm subtype to define its own
> thermal_zone_device_ops and properly configure thermal trip temperature.
>
> Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
> ---
> drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 38 ++++++++++++++-------
> 1 file changed, 26 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
> index 1cc9369ca9e1..514772e94a28 100644
> --- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
> +++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
> @@ -1,7 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /*
> * Copyright (c) 2011-2015, 2017, 2020, The Linux Foundation. All rights reserved.
> - * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2024-2025, Qualcomm Innovation Center, Inc. All rights reserved.
> */
>
> #include <linux/bitfield.h>
> @@ -71,8 +71,10 @@ static const long temp_map_gen2_v1[THRESH_COUNT][STAGE_COUNT] = {
> struct qpnp_tm_chip;
>
> struct spmi_temp_alarm_data {
> + const struct thermal_zone_device_ops *ops;
> const long (*temp_map)[THRESH_COUNT][STAGE_COUNT];
> int (*get_temp_stage)(struct qpnp_tm_chip *chip);
> + int (*configure_trip_temps)(struct qpnp_tm_chip *chip);
> };
>
> struct qpnp_tm_chip {
> @@ -312,18 +314,39 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
> return IRQ_HANDLED;
> }
>
> +static int qpnp_tm_configure_trip_temp(struct qpnp_tm_chip *chip)
> +{
> + int crit_temp, ret;
> +
> + mutex_unlock(&chip->lock);
> +
> + ret = thermal_zone_get_crit_temp(chip->tz_dev, &crit_temp);
> + if (ret)
> + crit_temp = THERMAL_TEMP_INVALID;
> +
> + mutex_lock(&chip->lock);
> +
> + return qpnp_tm_update_critical_trip_temp(chip, crit_temp);
> +}
The qpnp_tm_configure_trip_temp() is called with the lock held which is really
unusual to have this assymetry when dealing with the locks.
In the other side, this code assume it is ok the userspace can change the
critical temperature of the board. Is it really a good idea ?
> static const struct spmi_temp_alarm_data spmi_temp_alarm_data = {
> + .ops = &qpnp_tm_sensor_ops,
> .temp_map = &temp_map_gen1,
> + .configure_trip_temps = qpnp_tm_configure_trip_temp,
> .get_temp_stage = qpnp_tm_gen1_get_temp_stage,
> };
>
> static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_data = {
> + .ops = &qpnp_tm_sensor_ops,
> .temp_map = &temp_map_gen1,
> + .configure_trip_temps = qpnp_tm_configure_trip_temp,
> .get_temp_stage = qpnp_tm_gen2_get_temp_stage,
> };
>
> static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_rev1_data = {
> + .ops = &qpnp_tm_sensor_ops,
> .temp_map = &temp_map_gen2_v1,
> + .configure_trip_temps = qpnp_tm_configure_trip_temp,
> .get_temp_stage = qpnp_tm_gen2_get_temp_stage,
> };
>
> @@ -336,7 +359,6 @@ static int qpnp_tm_init(struct qpnp_tm_chip *chip)
> {
> int ret;
> u8 reg = 0;
> - int crit_temp;
>
> mutex_lock(&chip->lock);
>
> @@ -355,15 +377,7 @@ static int qpnp_tm_init(struct qpnp_tm_chip *chip)
> if (chip->stage)
> chip->temp = qpnp_tm_decode_temp(chip, chip->stage);
>
> - mutex_unlock(&chip->lock);
> -
> - ret = thermal_zone_get_crit_temp(chip->tz_dev, &crit_temp);
> - if (ret)
> - crit_temp = THERMAL_TEMP_INVALID;
> -
> - mutex_lock(&chip->lock);
> -
> - ret = qpnp_tm_update_critical_trip_temp(chip, crit_temp);
> + ret = chip->data->configure_trip_temps(chip);
> if (ret < 0)
> goto out;
>
> @@ -483,7 +497,7 @@ static int qpnp_tm_probe(struct platform_device *pdev)
> * before the hardware initialization is completed.
> */
> chip->tz_dev = devm_thermal_of_zone_register(
> - &pdev->dev, 0, chip, &qpnp_tm_sensor_ops);
> + &pdev->dev, 0, chip, chip->data->ops);
> if (IS_ERR(chip->tz_dev))
> return dev_err_probe(&pdev->dev, PTR_ERR(chip->tz_dev),
> "failed to register sensor\n");
> --
> 2.34.1
>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3 4/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC peripherals
2025-03-20 20:24 ` [PATCH v3 4/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC peripherals Anjelique Melendez
2025-04-10 21:03 ` Dmitry Baryshkov
@ 2025-04-18 11:19 ` Daniel Lezcano
2025-04-23 23:31 ` Anjelique Melendez
1 sibling, 1 reply; 17+ messages in thread
From: Daniel Lezcano @ 2025-04-18 11:19 UTC (permalink / raw)
To: Anjelique Melendez
Cc: amitk, thara.gopinath, rafael, rui.zhang, lukasz.luba,
david.collins, srinivas.kandagatla, stefan.schmidt, quic_tsoni,
linux-arm-msm, linux-pm, linux-kernel, dmitry.baryshkov
On Thu, Mar 20, 2025 at 01:24:07PM -0700, Anjelique Melendez wrote:
> Add support for TEMP_ALARM GEN2 PMIC peripherals with digital major
> revision 2. This revision utilizes individual temp DAC registers
> to set the threshold temperature for over-temperature stages 1,
> 2, and 3 instead of a single register to specify a set of
> thresholds.
Can you elaborate what are the different stages in the QCom semantic ?
> Signed-off-by: David Collins <david.collins@oss.qualcomm.com>
> Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
> ---
> drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 136 ++++++++++++++++++++
> 1 file changed, 136 insertions(+)
>
> diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
> index 514772e94a28..efd2b6534127 100644
> --- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
> +++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
> @@ -26,6 +26,11 @@
> #define QPNP_TM_REG_SHUTDOWN_CTRL1 0x40
> #define QPNP_TM_REG_ALARM_CTRL 0x46
>
> +/* TEMP_DAC_STGx registers are only present for TEMP_GEN2 v2.0 */
> +#define QPNP_TM_REG_TEMP_DAC_STG1 0x47
> +#define QPNP_TM_REG_TEMP_DAC_STG2 0x48
> +#define QPNP_TM_REG_TEMP_DAC_STG3 0x49
> +
> #define QPNP_TM_TYPE 0x09
> #define QPNP_TM_SUBTYPE_GEN1 0x08
> #define QPNP_TM_SUBTYPE_GEN2 0x09
> @@ -65,6 +70,25 @@ static const long temp_map_gen2_v1[THRESH_COUNT][STAGE_COUNT] = {
>
> #define TEMP_STAGE_HYSTERESIS 2000
>
> +/*
> + * For TEMP_GEN2 v2.0, TEMP_DAC_STG1/2/3 registers are used to set the threshold
> + * for each stage independently.
> + * TEMP_DAC_STG* = 0 --> 80 C
> + * Each 8 step increase in TEMP_DAC_STG* value corresponds to 5 C (5000 mC).
> + */
> +#define TEMP_DAC_MIN 80000
> +#define TEMP_DAC_SCALE_NUM 8
> +#define TEMP_DAC_SCALE_DEN 5000
> +
> +#define TEMP_DAC_TEMP_TO_REG(temp) \
> + (((temp) - TEMP_DAC_MIN) * TEMP_DAC_SCALE_NUM / TEMP_DAC_SCALE_DEN)
> +#define TEMP_DAC_REG_TO_TEMP(reg) \
> + (TEMP_DAC_MIN + (reg) * TEMP_DAC_SCALE_DEN / TEMP_DAC_SCALE_NUM)
> +
> +static const long temp_dac_max[STAGE_COUNT] = {
> + 119375, 159375, 159375
> +};
> +
> /* Temperature in Milli Celsius reported during stage 0 if no ADC is present */
> #define DEFAULT_TEMP 37000
>
> @@ -73,6 +97,7 @@ struct qpnp_tm_chip;
> struct spmi_temp_alarm_data {
> const struct thermal_zone_device_ops *ops;
> const long (*temp_map)[THRESH_COUNT][STAGE_COUNT];
> + int (*setup)(struct qpnp_tm_chip *chip);
> int (*get_temp_stage)(struct qpnp_tm_chip *chip);
> int (*configure_trip_temps)(struct qpnp_tm_chip *chip);
> };
> @@ -88,6 +113,7 @@ struct qpnp_tm_chip {
> unsigned int thresh;
> unsigned int stage;
> unsigned int base;
> + unsigned int ntrips;
> /* protects .thresh, .stage and chip registers */
> struct mutex lock;
> bool initialized;
> @@ -305,6 +331,52 @@ static const struct thermal_zone_device_ops qpnp_tm_sensor_ops = {
> .set_trip_temp = qpnp_tm_set_trip_temp,
> };
>
> +static int qpnp_tm_gen2_rev2_set_temp_thresh(struct qpnp_tm_chip *chip, int trip, int temp)
> +{
> + int ret, temp_cfg;
> + u8 reg;
> +
> + if (trip < 0 || trip >= STAGE_COUNT) {
> + dev_err(chip->dev, "invalid TEMP_DAC trip = %d\n", trip);
> + return -EINVAL;
> + } else if (temp < TEMP_DAC_MIN || temp > temp_dac_max[trip]) {
> + dev_err(chip->dev, "invalid TEMP_DAC temp = %d\n", temp);
> + return -EINVAL;
> + }
> +
> + reg = TEMP_DAC_TEMP_TO_REG(temp);
> + temp_cfg = TEMP_DAC_REG_TO_TEMP(reg);
> +
> + ret = qpnp_tm_write(chip, QPNP_TM_REG_TEMP_DAC_STG1 + trip, reg);
> + if (ret < 0) {
> + dev_err(chip->dev, "TEMP_DAC_STG write failed, ret=%d\n", ret);
> + return ret;
> + }
> +
> + chip->temp_thresh_map[trip] = temp_cfg;
> +
> + return 0;
> +}
> +
> +static int qpnp_tm_gen2_rev2_set_trip_temp(struct thermal_zone_device *tz,
> + const struct thermal_trip *trip, int temp)
> +{
> + unsigned int trip_index = THERMAL_TRIP_PRIV_TO_INT(trip->priv);
> + struct qpnp_tm_chip *chip = thermal_zone_device_priv(tz);
> + int ret;
> +
> + mutex_lock(&chip->lock);
> + ret = qpnp_tm_gen2_rev2_set_temp_thresh(chip, trip_index, temp);
> + mutex_unlock(&chip->lock);
> +
> + return ret;
> +}
> +
> +static const struct thermal_zone_device_ops qpnp_tm_gen2_rev2_sensor_ops = {
> + .get_temp = qpnp_tm_get_temp,
> + .set_trip_temp = qpnp_tm_gen2_rev2_set_trip_temp,
> +};
> +
> static irqreturn_t qpnp_tm_isr(int irq, void *data)
> {
> struct qpnp_tm_chip *chip = data;
> @@ -329,6 +401,58 @@ static int qpnp_tm_configure_trip_temp(struct qpnp_tm_chip *chip)
> return qpnp_tm_update_critical_trip_temp(chip, crit_temp);
> }
>
> +/* Configure TEMP_DAC registers based on DT thermal_zone trips */
> +static int qpnp_tm_gen2_rev2_configure_trip_temps_cb(struct thermal_trip *trip, void *data)
> +{
> + struct qpnp_tm_chip *chip = data;
> + int ret;
> +
> + trip->priv = THERMAL_INT_TO_TRIP_PRIV(chip->ntrips);
> + ret = qpnp_tm_gen2_rev2_set_temp_thresh(chip, chip->ntrips, trip->temperature);
> + chip->ntrips++;
> +
> + return ret;
> +}
> +
> +static int qpnp_tm_gen2_rev2_configure_trip_temps(struct qpnp_tm_chip *chip)
> +{
> + int ret, i;
> +
> + ret = thermal_zone_for_each_trip(chip->tz_dev,
> + qpnp_tm_gen2_rev2_configure_trip_temps_cb, chip);
> + if (ret < 0)
> + return ret;
> +
> + /* Verify that trips are strictly increasing. */
> + for (i = 1; i < STAGE_COUNT; i++) {
> + if (chip->temp_thresh_map[i] <= chip->temp_thresh_map[i - 1]) {
> + dev_err(chip->dev, "Threshold %d=%ld <= threshold %d=%ld\n",
> + i, chip->temp_thresh_map[i], i - 1,
> + chip->temp_thresh_map[i - 1]);
> + return -EINVAL;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/* Read the hardware default TEMP_DAC stage threshold temperatures */
> +static int qpnp_tm_gen2_rev2_setup(struct qpnp_tm_chip *chip)
> +{
> + int ret, i;
> + u8 reg = 0;
> +
> + for (i = 0; i < STAGE_COUNT; i++) {
> + ret = qpnp_tm_read(chip, QPNP_TM_REG_TEMP_DAC_STG1 + i, ®);
> + if (ret < 0)
> + return ret;
> +
> + chip->temp_thresh_map[i] = TEMP_DAC_REG_TO_TEMP(reg);
> + }
> +
> + return 0;
> +}
> +
> static const struct spmi_temp_alarm_data spmi_temp_alarm_data = {
> .ops = &qpnp_tm_sensor_ops,
> .temp_map = &temp_map_gen1,
> @@ -350,6 +474,13 @@ static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_rev1_data = {
> .get_temp_stage = qpnp_tm_gen2_get_temp_stage,
> };
>
> +static const struct spmi_temp_alarm_data spmi_temp_alarm_gen2_rev2_data = {
> + .ops = &qpnp_tm_gen2_rev2_sensor_ops,
> + .setup = qpnp_tm_gen2_rev2_setup,
> + .configure_trip_temps = qpnp_tm_gen2_rev2_configure_trip_temps,
> + .get_temp_stage = qpnp_tm_gen2_get_temp_stage,
> +};
> +
> /*
> * This function initializes the internal temp value based on only the
> * current thermal stage and threshold. Setup threshold control and
> @@ -484,6 +615,8 @@ static int qpnp_tm_probe(struct platform_device *pdev)
>
> if (subtype == QPNP_TM_SUBTYPE_GEN1)
> chip->data = &spmi_temp_alarm_data;
> + else if (subtype == QPNP_TM_SUBTYPE_GEN2 && dig_major >= 2)
> + chip->data = &spmi_temp_alarm_gen2_rev2_data;
> else if (subtype == QPNP_TM_SUBTYPE_GEN2 && dig_major >= 1)
> chip->data = &spmi_temp_alarm_gen2_rev1_data;
> else if (subtype == QPNP_TM_SUBTYPE_GEN2)
> @@ -491,6 +624,9 @@ static int qpnp_tm_probe(struct platform_device *pdev)
> else
> return -ENODEV;
>
> + if (chip->data->setup)
> + chip->data->setup(chip);
> +
> /*
> * Register the sensor before initializing the hardware to be able to
> * read the trip points. get_temp() returns the default temperature
> --
> 2.34.1
>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3 3/5 RESEND] thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp Alarm subtypes
2025-04-18 11:15 ` Daniel Lezcano
@ 2025-04-23 23:20 ` Anjelique Melendez
0 siblings, 0 replies; 17+ messages in thread
From: Anjelique Melendez @ 2025-04-23 23:20 UTC (permalink / raw)
To: Daniel Lezcano
Cc: amitk, thara.gopinath, rafael, rui.zhang, lukasz.luba,
david.collins, srinivas.kandagatla, stefan.schmidt, quic_tsoni,
linux-arm-msm, linux-pm, linux-kernel, dmitry.baryshkov
On 4/18/2025 4:15 AM, Daniel Lezcano wrote:
> On Thu, Mar 20, 2025 at 01:24:06PM -0700, Anjelique Melendez wrote:
>> In preparation to support newer temp alarm subtypes, add the "ops" and
>> "configure_trip_temps" references to spmi_temp_alarm_data. This will
>> allow for each Temp Alarm subtype to define its own
>> thermal_zone_device_ops and properly configure thermal trip temperature.
>>
>> Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
>> ---
>> drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 38 ++++++++++++++-------
>> 1 file changed, 26 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
>> index 1cc9369ca9e1..514772e94a28 100644
>> --- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
>> +++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
>> @@ -1,7 +1,7 @@
>> // SPDX-License-Identifier: GPL-2.0-only
>> /*
>> * Copyright (c) 2011-2015, 2017, 2020, The Linux Foundation. All rights reserved.
>> - * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
>> + * Copyright (c) 2024-2025, Qualcomm Innovation Center, Inc. All rights reserved.
>> */
>>
>> #include <linux/bitfield.h>
>> @@ -71,8 +71,10 @@ static const long temp_map_gen2_v1[THRESH_COUNT][STAGE_COUNT] = {
>> struct qpnp_tm_chip;
>>
>> struct spmi_temp_alarm_data {
>> + const struct thermal_zone_device_ops *ops;
>> const long (*temp_map)[THRESH_COUNT][STAGE_COUNT];
>> int (*get_temp_stage)(struct qpnp_tm_chip *chip);
>> + int (*configure_trip_temps)(struct qpnp_tm_chip *chip);
>> };
>>
>> struct qpnp_tm_chip {
>> @@ -312,18 +314,39 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
>> return IRQ_HANDLED;
>> }
>>
>> +static int qpnp_tm_configure_trip_temp(struct qpnp_tm_chip *chip)
>> +{
>> + int crit_temp, ret;
>> +
>> + mutex_unlock(&chip->lock);
>> +
>> + ret = thermal_zone_get_crit_temp(chip->tz_dev, &crit_temp);
>> + if (ret)
>> + crit_temp = THERMAL_TEMP_INVALID;
>> +
>> + mutex_lock(&chip->lock);
>> +
>> + return qpnp_tm_update_critical_trip_temp(chip, crit_temp);
>> +}
>
> The qpnp_tm_configure_trip_temp() is called with the lock held which is really
> unusual to have this assymetry when dealing with the locks.
>
This change is simply moving these lines from init() into their own
configure_trip_temp() function. configure_trip_temp() is only called
from within init() so functionally this is the same as what the driver
was doing before. As new temp_alarm types are introduced (like in patch
4&5) they may need to configure trip temps differently.
Specifically the mutex_unlock() and mutex_lock() guards were added in
this change:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/thermal/qcom/qcom-spmi-temp-alarm.c?h=v6.15-rc3&id=59edcd91d852f88ef7d208029503f9b5310d0603
> In the other side, this code assume it is ok the userspace can change the
> critical temperature of the board. Is it really a good idea ?
Sorry, I think I might be a little confused on what you mean from this
comment. This driver has supported setting critical temperature from
userspace for many years now..
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/thermal/qcom/qcom-spmi-temp-alarm.c?h=v6.15-rc3#n264.
This patch is just reworking driver, there are no functional/behavioral
changes.
Thanks,
Anjelique
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3 4/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC peripherals
2025-04-18 11:19 ` Daniel Lezcano
@ 2025-04-23 23:31 ` Anjelique Melendez
2025-04-30 16:38 ` Daniel Lezcano
0 siblings, 1 reply; 17+ messages in thread
From: Anjelique Melendez @ 2025-04-23 23:31 UTC (permalink / raw)
To: Daniel Lezcano
Cc: amitk, thara.gopinath, rafael, rui.zhang, lukasz.luba,
david.collins, srinivas.kandagatla, stefan.schmidt, quic_tsoni,
linux-arm-msm, linux-pm, linux-kernel, dmitry.baryshkov
On 4/18/2025 4:19 AM, Daniel Lezcano wrote:
> On Thu, Mar 20, 2025 at 01:24:07PM -0700, Anjelique Melendez wrote:
>> Add support for TEMP_ALARM GEN2 PMIC peripherals with digital major
>> revision 2. This revision utilizes individual temp DAC registers
>> to set the threshold temperature for over-temperature stages 1,
>> 2, and 3 instead of a single register to specify a set of
>> thresholds.
>
> Can you elaborate what are the different stages in the QCom semantic ?
>
Stage 1: warning
Stage 2: system shutdown
Stage 3: emergency shutdown
This is the same as was outlined in original driver documentation:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/drivers/thermal?h=v5.4.281&id=f1599f9e4cd6f1dd0cad202853fb830854f4e944.
Will add this info to commit.
>> Signed-off-by: David Collins <david.collins@oss.qualcomm.com>
>> Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
>> ---
>> drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 136 ++++++++++++++++++++
>> 1 file changed, 136 insertions(+)
>>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3 4/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC peripherals
2025-04-23 23:31 ` Anjelique Melendez
@ 2025-04-30 16:38 ` Daniel Lezcano
0 siblings, 0 replies; 17+ messages in thread
From: Daniel Lezcano @ 2025-04-30 16:38 UTC (permalink / raw)
To: Anjelique Melendez
Cc: amitk, thara.gopinath, rafael, rui.zhang, lukasz.luba,
david.collins, srinivas.kandagatla, stefan.schmidt, quic_tsoni,
linux-arm-msm, linux-pm, linux-kernel, dmitry.baryshkov
On Wed, Apr 23, 2025 at 04:31:18PM -0700, Anjelique Melendez wrote:
>
>
> On 4/18/2025 4:19 AM, Daniel Lezcano wrote:
> > On Thu, Mar 20, 2025 at 01:24:07PM -0700, Anjelique Melendez wrote:
> > > Add support for TEMP_ALARM GEN2 PMIC peripherals with digital major
> > > revision 2. This revision utilizes individual temp DAC registers
> > > to set the threshold temperature for over-temperature stages 1,
> > > 2, and 3 instead of a single register to specify a set of
> > > thresholds.
> >
> > Can you elaborate what are the different stages in the QCom semantic ?
> Stage 1: warning
> Stage 2: system shutdown
> Stage 3: emergency shutdown
>
> This is the same as was outlined in original driver documentation:
> https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/drivers/thermal?h=v5.4.281&id=f1599f9e4cd6f1dd0cad202853fb830854f4e944.
> Will add this info to commit.
Thanks for the pointer and the clarification
> > > Signed-off-by: David Collins <david.collins@oss.qualcomm.com>
> > > Signed-off-by: Anjelique Melendez <anjelique.melendez@oss.qualcomm.com>
> > > ---
> > > drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 136 ++++++++++++++++++++
> > > 1 file changed, 136 insertions(+)
> > >
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2025-04-30 16:38 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-20 20:24 [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes Anjelique Melendez
2025-03-20 20:24 ` [PATCH v3 1/5 RESEND] thermal: qcom-spmi-temp-alarm: enable stage 2 shutdown when required Anjelique Melendez
2025-04-10 21:01 ` Dmitry Baryshkov
2025-04-18 10:54 ` Daniel Lezcano
2025-03-20 20:24 ` [PATCH v3 2/5 RESEND] thermal: qcom-spmi-temp-alarm: Add temp alarm data struct based on HW subtype Anjelique Melendez
2025-03-20 20:24 ` [PATCH v3 3/5 RESEND] thermal: qcom-spmi-temp-alarm: Prepare to support additional Temp Alarm subtypes Anjelique Melendez
2025-04-10 21:01 ` Dmitry Baryshkov
2025-04-18 11:15 ` Daniel Lezcano
2025-04-23 23:20 ` Anjelique Melendez
2025-03-20 20:24 ` [PATCH v3 4/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 2 PMIC peripherals Anjelique Melendez
2025-04-10 21:03 ` Dmitry Baryshkov
2025-04-18 11:19 ` Daniel Lezcano
2025-04-23 23:31 ` Anjelique Melendez
2025-04-30 16:38 ` Daniel Lezcano
2025-03-20 20:24 ` [PATCH v3 5/5 RESEND] thermal: qcom-spmi-temp-alarm: add support for LITE " Anjelique Melendez
2025-04-10 21:04 ` Dmitry Baryshkov
2025-04-08 21:51 ` [PATCH v3 0/5 RESEND] thermal: qcom-spmi-temp-alarm: Add support for new TEMP_ALARM subtypes Anjelique Melendez
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox