Merge "drivers: thermal: qcom: Add tsens driver changes for hibernation mode"

This commit is contained in:
qctecmdr 2024-05-11 00:14:09 -07:00 committed by Gerrit - the friendly Code Review server
commit 41e8b85288
3 changed files with 143 additions and 11 deletions

View File

@ -2,7 +2,7 @@
/*
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
* Copyright (c) 2018, Linaro Limited
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/bitops.h>
@ -97,6 +97,10 @@ static const struct tsens_ops ops_generic_v2 = {
.init = init_common,
.get_temp = get_temp_tsens_valid,
.get_cold_status = get_cold_int_status,
.suspend = tsens_v2_tsens_suspend,
.resume = tsens_v2_tsens_resume,
.freeze = tsens_v2_tsens_freeze,
.restore = tsens_v2_tsens_restore,
};
struct tsens_plat_data data_tsens_v2 = {

View File

@ -2,7 +2,7 @@
/*
* Copyright (c) 2015, 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2019, 2020, Linaro Ltd.
* Copyright (c) 2021, 2022, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021, 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/debugfs.h>
@ -18,6 +18,7 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/thermal.h>
#include <linux/suspend.h>
#include "tsens.h"
#include "thermal_zone_internal.h"
@ -1015,7 +1016,25 @@ static int __maybe_unused tsens_resume(struct device *dev)
return 0;
}
static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume);
static int __maybe_unused tsens_freeze(struct device *dev)
{
struct tsens_priv *priv = dev_get_drvdata(dev);
if (priv->ops && priv->ops->freeze)
return priv->ops->freeze(priv);
return 0;
}
static int __maybe_unused tsens_restore(struct device *dev)
{
struct tsens_priv *priv = dev_get_drvdata(dev);
if (priv->ops && priv->ops->restore)
return priv->ops->restore(priv);
return 0;
}
static const struct of_device_id tsens_table[] = {
{
@ -1062,7 +1081,7 @@ static const struct thermal_zone_of_device_ops tsens_cold_of_ops = {
static int tsens_register_irq(struct tsens_priv *priv, char *irqname,
irq_handler_t thread_fn)
irq_handler_t thread_fn, int *irq_num)
{
struct platform_device *pdev;
int ret, irq;
@ -1072,6 +1091,7 @@ static int tsens_register_irq(struct tsens_priv *priv, char *irqname,
return -ENODEV;
irq = platform_get_irq_byname(pdev, irqname);
*irq_num = irq;
if (irq < 0) {
ret = irq;
/* For old DTs with no IRQ defined */
@ -1093,6 +1113,90 @@ static int tsens_register_irq(struct tsens_priv *priv, char *irqname,
return ret;
}
static int tsens_reinit(struct tsens_priv *priv)
{
unsigned long flags;
spin_lock_irqsave(&priv->ul_lock, flags);
if (priv->feat->has_watchdog) {
regmap_field_write(priv->rf[WDOG_BARK_MASK], 0);
regmap_field_write(priv->rf[CC_MON_MASK], 1);
}
if (tsens_version(priv) >= VER_0_1)
tsens_enable_irq(priv);
spin_unlock_irqrestore(&priv->ul_lock, flags);
return 0;
}
int tsens_v2_tsens_suspend(struct tsens_priv *priv)
{
if (!priv->tm_disable_on_suspend)
return 0;
if (priv->uplow_irq > 0) {
disable_irq_nosync(priv->uplow_irq);
disable_irq_wake(priv->uplow_irq);
}
if (priv->feat->crit_int && priv->crit_irq > 0) {
disable_irq_nosync(priv->crit_irq);
disable_irq_wake(priv->crit_irq);
}
if (priv->cold_irq > 0) {
disable_irq_nosync(priv->cold_irq);
disable_irq_wake(priv->cold_irq);
}
return 0;
}
int tsens_v2_tsens_resume(struct tsens_priv *priv)
{
if (!priv->tm_disable_on_suspend)
return 0;
tsens_reinit(priv);
if (priv->uplow_irq > 0) {
enable_irq(priv->uplow_irq);
enable_irq_wake(priv->uplow_irq);
}
if (priv->feat->crit_int && priv->crit_irq > 0) {
enable_irq(priv->crit_irq);
enable_irq_wake(priv->crit_irq);
}
if (priv->cold_irq > 0) {
enable_irq(priv->cold_irq);
enable_irq_wake(priv->cold_irq);
}
return 0;
}
int tsens_v2_tsens_freeze(struct tsens_priv *priv)
{
if (priv->ops && priv->ops->suspend)
return priv->ops->suspend(priv);
return 0;
}
int tsens_v2_tsens_restore(struct tsens_priv *priv)
{
if (priv->ops && priv->ops->resume)
return priv->ops->resume(priv);
return 0;
}
static int tsens_register(struct tsens_priv *priv)
{
int i, temp, ret;
@ -1122,14 +1226,15 @@ static int tsens_register(struct tsens_priv *priv)
priv->ops->enable(priv, i);
}
ret = tsens_register_irq(priv, "uplow", tsens_irq_thread);
ret = tsens_register_irq(priv, "uplow",
tsens_irq_thread, &priv->uplow_irq);
if (ret < 0)
return ret;
if (priv->feat->crit_int)
ret = tsens_register_irq(priv, "critical",
tsens_critical_irq_thread);
tsens_critical_irq_thread, &priv->crit_irq);
if (priv->feat->cold_int) {
priv->cold_sensor = devm_kzalloc(priv->dev,
@ -1144,13 +1249,14 @@ static int tsens_register(struct tsens_priv *priv)
priv->cold_sensor->hw_id,
priv->cold_sensor,
&tsens_cold_of_ops);
if (IS_ERR(tzd)) {
ret = 0;
return ret;
if (!IS_ERR_OR_NULL(tzd)) {
priv->cold_sensor->tzd = tzd;
ret = tsens_register_irq(priv, "cold",
tsens_cold_irq_thread, &priv->cold_irq);
}
priv->cold_sensor->tzd = tzd;
ret = tsens_register_irq(priv, "cold", tsens_cold_irq_thread);
ret = tsens_register_irq(priv, "cold", tsens_cold_irq_thread, &priv->cold_irq);
}
return ret;
}
@ -1227,6 +1333,9 @@ static int tsens_probe(struct platform_device *pdev)
}
}
priv->tm_disable_on_suspend =
of_property_read_bool(np, "tm-disable-on-suspend");
return tsens_register(priv);
}
@ -1242,6 +1351,11 @@ static int tsens_remove(struct platform_device *pdev)
return 0;
}
static const struct dev_pm_ops tsens_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(tsens_suspend, tsens_resume)
SET_SYSTEM_SLEEP_PM_OPS(tsens_freeze, tsens_restore)
};
static struct platform_driver tsens_driver = {
.probe = tsens_probe,
.remove = tsens_remove,

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2015, 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2021, 2022, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021, 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef __QCOM_TSENS_H__
@ -83,6 +83,8 @@ struct tsens_ops {
int (*resume)(struct tsens_priv *priv);
int (*get_trend)(struct tsens_sensor *s, enum thermal_trend *trend);
int (*get_cold_status)(const struct tsens_sensor *s, bool *cold_status);
int (*freeze)(struct tsens_priv *priv);
int (*restore)(struct tsens_priv *priv);
};
#define REG_FIELD_FOR_EACH_SENSOR11(_name, _offset, _startbit, _stopbit) \
@ -610,6 +612,13 @@ struct tsens_priv {
const struct reg_field *fields;
const struct tsens_ops *ops;
/* add to save irq number to re-use it at runtime */
int uplow_irq;
int crit_irq;
int cold_irq;
bool tm_disable_on_suspend;
struct dentry *debug_root;
struct dentry *debug;
struct tsens_sensor *cold_sensor;
@ -626,6 +635,11 @@ int init_common(struct tsens_priv *priv);
int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp);
int get_temp_common(const struct tsens_sensor *s, int *temp);
int get_cold_int_status(const struct tsens_sensor *s, bool *cold_status);
int tsens_v2_tsens_suspend(struct tsens_priv *priv);
int tsens_v2_tsens_resume(struct tsens_priv *priv);
int tsens_v2_tsens_freeze(struct tsens_priv *priv);
int tsens_v2_tsens_restore(struct tsens_priv *priv);
/* TSENS target */
extern struct tsens_plat_data data_8960;