mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
drivers: thermal: qmi_sensor: Add snapshot of QMI sensor V2 driver
This is a snapshot of the thermal framework from msm-5.10 as of
commit f5a9cf8e4b17 ("drivers: qmi_sensor: Re-configure qmi sensor
trip on subsystem restart").
Updates:
- Change GPL v2 license to GPL
Change-Id: If2681995379274a5d9d641d0dce2b4f9ec07edb6
Signed-off-by: Manaf Meethalavalappu Pallikunhi <quic_manafm@quicinc.com>
Signed-off-by: Rashid Zafar <quic_rzafar@quicinc.com>
This commit is contained in:
parent
c9b2831279
commit
ec5bc9a94b
|
|
@ -82,3 +82,13 @@ config QTI_POLICY_ENGINE_SENSOR
|
|||
a sensor. This will enable to provide configuration to mitigate
|
||||
cooling devices when a recommendation is sent from hardware.
|
||||
|
||||
config QTI_QMI_SENSOR_V2
|
||||
tristate "QTI QMI TS V2 sensor driver"
|
||||
depends on THERMAL_OF
|
||||
select QCOM_QMI_HELPERS
|
||||
help
|
||||
This enables to list the QTI remote subsystem temperature sensors
|
||||
with QMI TS V2 interface. This driver can read the temperature of
|
||||
the remote sensor. These sensors can take thresholds and notify the
|
||||
thermal framework when the threshold is reached.
|
||||
|
||||
|
|
|
|||
|
|
@ -10,3 +10,6 @@ obj-$(CONFIG_QTI_CPU_PAUSE_COOLING_DEVICE) += thermal_pause.o
|
|||
obj-$(CONFIG_QTI_BCL_PMIC5) += bcl_pmic5.o
|
||||
obj-$(CONFIG_QTI_BCL_SOC_DRIVER) += bcl_soc.o
|
||||
obj-$(CONFIG_QTI_POLICY_ENGINE_SENSOR) += policy_engine.o
|
||||
|
||||
obj-$(CONFIG_QTI_QMI_SENSOR_V2) += qti_qmi_sensor_v2.o
|
||||
qti_qmi_sensor_v2-y += thermal_sensor_service_v02.o qmi_sensors_v2.o
|
||||
|
|
|
|||
147
drivers/thermal/qcom/qmi_sensors.h
Normal file
147
drivers/thermal/qcom/qmi_sensors.h
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __QMI_SENSORS_H__
|
||||
#define __QMI_SENSORS_H__
|
||||
|
||||
#define QMI_CLIENT_NAME_LENGTH 40
|
||||
|
||||
enum qmi_ts_sensor {
|
||||
QMI_TS_PA,
|
||||
QMI_TS_PA_1,
|
||||
QMI_TS_PA_2,
|
||||
QMI_TS_QFE_PA_0,
|
||||
QMI_TS_QFE_WTR_0,
|
||||
QMI_TS_MODEM_MODEM,
|
||||
QMI_TS_MMW_0,
|
||||
QMI_TS_MMW_1,
|
||||
QMI_TS_MMW_2,
|
||||
QMI_TS_MMW_3,
|
||||
QMI_TS_MODEM_SKIN,
|
||||
QMI_TS_QFE_PA_MDM,
|
||||
QMI_TS_QFE_PA_WTR,
|
||||
QMI_TS_STREAMER_0,
|
||||
QMI_TS_MOD_MMW_0,
|
||||
QMI_TS_MOD_MMW_1,
|
||||
QMI_TS_MOD_MMW_2,
|
||||
QMI_TS_MOD_MMW_3,
|
||||
QMI_TS_RET_PA_0,
|
||||
QMI_TS_WTR_PA_0,
|
||||
QMI_TS_WTR_PA_1,
|
||||
QMI_TS_WTR_PA_2,
|
||||
QMI_TS_WTR_PA_3,
|
||||
QMI_SYS_THERM1,
|
||||
QMI_SYS_THERM2,
|
||||
QMI_TS_TSENS_1,
|
||||
QMI_TS_MMW_PA1,
|
||||
QMI_TS_MMW_PA2,
|
||||
QMI_TS_MMW_PA3,
|
||||
QMI_TS_SDR_MMW,
|
||||
QMI_TS_QTM_THERM,
|
||||
QMI_TS_BCL_WARN,
|
||||
QMI_TS_SDR0_PA0,
|
||||
QMI_TS_SDR0_PA1,
|
||||
QMI_TS_SDR0_PA2,
|
||||
QMI_TS_SDR0_PA3,
|
||||
QMI_TS_SDR0_PA4,
|
||||
QMI_TS_SDR0_PA5,
|
||||
QMI_TS_SDR0,
|
||||
QMI_TS_SDR1_PA0,
|
||||
QMI_TS_SDR1_PA1,
|
||||
QMI_TS_SDR1_PA2,
|
||||
QMI_TS_SDR1_PA3,
|
||||
QMI_TS_SDR1_PA4,
|
||||
QMI_TS_SDR1_PA5,
|
||||
QMI_TS_SDR1,
|
||||
QMI_TS_MMW0,
|
||||
QMI_TS_MMW1,
|
||||
QMI_TS_MMW2,
|
||||
QMI_TS_MMW3,
|
||||
QMI_TS_MMW_IFIC0,
|
||||
QMI_TS_SUB1_MODEM_CFG,
|
||||
QMI_TS_SUB1_LTE_CC,
|
||||
QMI_TS_SUB1_MCG_FR1_CC,
|
||||
QMI_TS_SUB1_MCG_FR2_CC,
|
||||
QMI_TS_SUB1_SCG_FR1_CC,
|
||||
QMI_TS_SUB1_SCG_FR2_CC,
|
||||
QMI_TS_SUB2_MODEM_CFG,
|
||||
QMI_TS_SUB2_LTE_CC,
|
||||
QMI_TS_SUB2_MCG_FR1_CC,
|
||||
QMI_TS_SUB2_MCG_FR2_CC,
|
||||
QMI_TS_SUB2_SCG_FR1_CC,
|
||||
QMI_TS_SUB2_SCG_FR2_CC,
|
||||
QMI_TS_NSP_ISENSE_TRIM,
|
||||
QMI_TS_MAX_NR
|
||||
};
|
||||
|
||||
static char sensor_clients[QMI_TS_MAX_NR][QMI_CLIENT_NAME_LENGTH] = {
|
||||
{"pa"},
|
||||
{"pa_1"},
|
||||
{"pa_2"},
|
||||
{"qfe_pa0"},
|
||||
{"qfe_wtr0"},
|
||||
{"modem_tsens"},
|
||||
{"qfe_mmw0"},
|
||||
{"qfe_mmw1"},
|
||||
{"qfe_mmw2"},
|
||||
{"qfe_mmw3"},
|
||||
{"xo_therm"},
|
||||
{"qfe_pa_mdm"},
|
||||
{"qfe_pa_wtr"},
|
||||
{"qfe_mmw_streamer0"},
|
||||
{"qfe_mmw0_mod"},
|
||||
{"qfe_mmw1_mod"},
|
||||
{"qfe_mmw2_mod"},
|
||||
{"qfe_mmw3_mod"},
|
||||
{"qfe_ret_pa0"},
|
||||
{"qfe_wtr_pa0"},
|
||||
{"qfe_wtr_pa1"},
|
||||
{"qfe_wtr_pa2"},
|
||||
{"qfe_wtr_pa3"},
|
||||
{"sys_therm1"},
|
||||
{"sys_therm2"},
|
||||
{"modem_tsens1"},
|
||||
{"mmw_pa1"},
|
||||
{"mmw_pa2"},
|
||||
{"mmw_pa3"},
|
||||
{"sdr_mmw_therm"},
|
||||
{"qtm_therm"},
|
||||
{"modem_bcl_warn"},
|
||||
{"sdr0_pa0"},
|
||||
{"sdr0_pa1"},
|
||||
{"sdr0_pa2"},
|
||||
{"sdr0_pa3"},
|
||||
{"sdr0_pa4"},
|
||||
{"sdr0_pa5"},
|
||||
{"sdr0"},
|
||||
{"sdr1_pa0"},
|
||||
{"sdr1_pa1"},
|
||||
{"sdr1_pa2"},
|
||||
{"sdr1_pa3"},
|
||||
{"sdr1_pa4"},
|
||||
{"sdr1_pa5"},
|
||||
{"sdr1"},
|
||||
{"mmw0"},
|
||||
{"mmw1"},
|
||||
{"mmw2"},
|
||||
{"mmw3"},
|
||||
{"mmw_ific0"},
|
||||
{"sub1_modem_cfg"},
|
||||
{"sub1_lte_cc"},
|
||||
{"sub1_mcg_fr1_cc"},
|
||||
{"sub1_mcg_fr2_cc"},
|
||||
{"sub1_scg_fr1_cc"},
|
||||
{"sub1_scg_fr2_cc"},
|
||||
{"sub2_modem_cfg"},
|
||||
{"sub2_lte_cc"},
|
||||
{"sub2_mcg_fr1_cc"},
|
||||
{"sub2_mcg_fr2_cc"},
|
||||
{"sub2_scg_fr1_cc"},
|
||||
{"sub2_scg_fr2_cc"},
|
||||
{"isense_trim"},
|
||||
};
|
||||
|
||||
#endif /* __QMI_SENSORS_H__ */
|
||||
654
drivers/thermal/qcom/qmi_sensors_v2.c
Normal file
654
drivers/thermal/qcom/qmi_sensors_v2.c
Normal file
|
|
@ -0,0 +1,654 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/qcom/qmi.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#include "thermal_sensor_service_v02.h"
|
||||
#include "qmi_sensors.h"
|
||||
|
||||
#define QMI_SENS_DRIVER "qmi-therm-sensors-v2"
|
||||
#define QMI_TS_RESP_TOUT msecs_to_jiffies(100)
|
||||
|
||||
struct qmi_sensor {
|
||||
struct device *dev;
|
||||
char qmi_name[QMI_CLIENT_NAME_LENGTH];
|
||||
bool connection_active;
|
||||
struct list_head ts_node;
|
||||
struct thermal_zone_device *tz_dev;
|
||||
int32_t last_reading;
|
||||
int32_t high_thresh;
|
||||
int32_t low_thresh;
|
||||
struct qmi_ts_instance *ts;
|
||||
enum qmi_ts_sensor sens_type;
|
||||
struct work_struct therm_notify_work;
|
||||
};
|
||||
|
||||
struct qmi_ts_instance {
|
||||
struct device *dev;
|
||||
struct qmi_handle handle;
|
||||
struct mutex mutex;
|
||||
uint32_t inst_id;
|
||||
struct list_head ts_sensor_list;
|
||||
struct work_struct svc_arrive_work;
|
||||
};
|
||||
|
||||
static struct qmi_ts_instance *ts_instances;
|
||||
static int ts_inst_cnt;
|
||||
static atomic_t in_suspend;
|
||||
|
||||
static int qmi_sensor_pm_notify(struct notifier_block *nb,
|
||||
unsigned long mode, void *_unused)
|
||||
{
|
||||
switch (mode) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
case PM_RESTORE_PREPARE:
|
||||
case PM_SUSPEND_PREPARE:
|
||||
atomic_set(&in_suspend, 1);
|
||||
break;
|
||||
case PM_POST_HIBERNATION:
|
||||
case PM_POST_RESTORE:
|
||||
case PM_POST_SUSPEND:
|
||||
atomic_set(&in_suspend, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block qmi_sensor_pm_nb = {
|
||||
.notifier_call = qmi_sensor_pm_notify,
|
||||
};
|
||||
|
||||
static void qmi_ts_thresh_notify(struct work_struct *work)
|
||||
{
|
||||
struct qmi_sensor *qmi_sens = container_of(work,
|
||||
struct qmi_sensor,
|
||||
therm_notify_work);
|
||||
|
||||
thermal_zone_device_update(qmi_sens->tz_dev, THERMAL_TRIP_VIOLATED);
|
||||
};
|
||||
|
||||
static void qmi_ts_update_temperature(struct qmi_ts_instance *ts,
|
||||
const struct ts_temp_report_ind_msg_v02 *ind_msg,
|
||||
uint8_t notify)
|
||||
{
|
||||
struct qmi_sensor *qmi_sens;
|
||||
|
||||
list_for_each_entry(qmi_sens, &ts->ts_sensor_list,
|
||||
ts_node) {
|
||||
if ((strncasecmp(qmi_sens->qmi_name,
|
||||
ind_msg->sensor_id.sensor_id,
|
||||
QMI_TS_SENSOR_ID_LENGTH_MAX_V02)))
|
||||
continue;
|
||||
|
||||
qmi_sens->last_reading = ind_msg->temp;
|
||||
|
||||
pr_debug("sensor:%s temperature:%d\n",
|
||||
qmi_sens->qmi_name, qmi_sens->last_reading);
|
||||
if (!qmi_sens->tz_dev)
|
||||
return;
|
||||
if (notify &&
|
||||
(qmi_sens->last_reading >= qmi_sens->high_thresh ||
|
||||
qmi_sens->last_reading <= qmi_sens->low_thresh)) {
|
||||
pr_debug("Sensor:%s Notify. temp:%d\n",
|
||||
ind_msg->sensor_id.sensor_id,
|
||||
qmi_sens->last_reading);
|
||||
queue_work(system_highpri_wq,
|
||||
&qmi_sens->therm_notify_work);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void qmi_ts_ind_cb_v02(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn, const void *decoded)
|
||||
{
|
||||
const struct ts_temp_report_ind_msg_v02 *ind_msg = decoded;
|
||||
uint8_t notify = 0;
|
||||
struct qmi_ts_instance *ts = container_of(qmi, struct qmi_ts_instance,
|
||||
handle);
|
||||
|
||||
if (!txn) {
|
||||
pr_err("Invalid transaction\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ind_msg->report_type != QMI_TS_TEMP_REPORT_CURRENT_TEMP_V02) ||
|
||||
ind_msg->seq_num_valid)
|
||||
notify = 1;
|
||||
|
||||
if (ind_msg->temp_valid)
|
||||
qmi_ts_update_temperature(ts, ind_msg, notify);
|
||||
else
|
||||
pr_err("Error invalid temperature field.\n");
|
||||
}
|
||||
|
||||
static int qmi_ts_send_request(struct qmi_ts_instance *ts, int msg_id,
|
||||
size_t len, struct qmi_elem_info *req_ei,
|
||||
struct qmi_elem_info *resp_ei,
|
||||
void *req, void *resp,
|
||||
struct qmi_response_type_v01 *resp_data)
|
||||
{
|
||||
int ret = 0;
|
||||
struct qmi_txn txn;
|
||||
|
||||
mutex_lock(&ts->mutex);
|
||||
ret = qmi_txn_init(&ts->handle, &txn, resp_ei, resp);
|
||||
if (ret < 0) {
|
||||
pr_err("qmi txn init failed for msg id:0x%x ret:%d\n",
|
||||
msg_id, ret);
|
||||
goto qmi_ts_send_exit;
|
||||
}
|
||||
|
||||
ret = qmi_send_request(&ts->handle, NULL, &txn, msg_id, len,
|
||||
req_ei, req);
|
||||
if (ret < 0) {
|
||||
pr_err("qmi txn send failed for msg id:0x%x ret:%d\n",
|
||||
msg_id, ret);
|
||||
qmi_txn_cancel(&txn);
|
||||
goto qmi_ts_send_exit;
|
||||
}
|
||||
|
||||
ret = qmi_txn_wait(&txn, QMI_TS_RESP_TOUT);
|
||||
if (ret < 0) {
|
||||
pr_err("qmi txn wait failed for msg id:0x%x ret:%d\n",
|
||||
msg_id, ret);
|
||||
goto qmi_ts_send_exit;
|
||||
}
|
||||
if (resp_data->result != QMI_RESULT_SUCCESS_V01) {
|
||||
ret = resp_data->result;
|
||||
pr_err("qmi NOT success for msg id:0x%x ret:%d\n",
|
||||
msg_id, ret);
|
||||
goto qmi_ts_send_exit;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
qmi_ts_send_exit:
|
||||
mutex_unlock(&ts->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qmi_ts_request(struct qmi_sensor *qmi_sens,
|
||||
bool send_current_temp_report)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ts_register_notification_temp_resp_msg_v02 resp;
|
||||
struct ts_register_notification_temp_req_msg_v02 req;
|
||||
struct qmi_ts_instance *ts = qmi_sens->ts;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
strscpy(req.sensor_id.sensor_id, qmi_sens->qmi_name,
|
||||
QMI_TS_SENSOR_ID_LENGTH_MAX_V02);
|
||||
req.seq_num = 0;
|
||||
if (send_current_temp_report) {
|
||||
req.send_current_temp_report = 1;
|
||||
req.seq_num_valid = true;
|
||||
} else {
|
||||
req.seq_num_valid = false;
|
||||
req.temp_threshold_high_valid =
|
||||
qmi_sens->high_thresh != INT_MAX;
|
||||
req.temp_threshold_high = qmi_sens->high_thresh;
|
||||
req.temp_threshold_low_valid =
|
||||
qmi_sens->low_thresh != (-INT_MAX);
|
||||
req.temp_threshold_low = qmi_sens->low_thresh;
|
||||
pr_debug("sensor:%s high_valid:%d high:%d low_valid:%d low:%d\n",
|
||||
req.sensor_id.sensor_id, req.temp_threshold_high_valid,
|
||||
req.temp_threshold_high, req.temp_threshold_low_valid,
|
||||
req.temp_threshold_low);
|
||||
}
|
||||
|
||||
ret = qmi_ts_send_request(ts, QMI_TS_REGISTER_NOTIFICATION_TEMP_REQ_V02,
|
||||
TS_REGISTER_NOTIFICATION_TEMP_REQ_MSG_V02_MAX_MSG_LEN,
|
||||
ts_register_notification_temp_req_msg_v02_ei,
|
||||
ts_register_notification_temp_resp_msg_v02_ei,
|
||||
&req, &resp, &resp.resp);
|
||||
if (ret < 0)
|
||||
pr_err("qmi ts txn failed for %s ret:%d\n",
|
||||
qmi_sens->qmi_name, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qmi_sensor_read(void *data, int *temp)
|
||||
{
|
||||
struct qmi_sensor *qmi_sens = (struct qmi_sensor *)data;
|
||||
|
||||
if (qmi_sens->connection_active && !atomic_read(&in_suspend))
|
||||
qmi_ts_request(qmi_sens, true);
|
||||
*temp = qmi_sens->last_reading;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qmi_sensor_set_trips(void *data, int low, int high)
|
||||
{
|
||||
struct qmi_sensor *qmi_sens = (struct qmi_sensor *)data;
|
||||
int ret = 0;
|
||||
|
||||
if (qmi_sens->high_thresh == high &&
|
||||
qmi_sens->low_thresh == low)
|
||||
return ret;
|
||||
qmi_sens->high_thresh = high;
|
||||
qmi_sens->low_thresh = low;
|
||||
if (!qmi_sens->connection_active)
|
||||
return ret;
|
||||
ret = qmi_ts_request(qmi_sens, false);
|
||||
if (ret < 0)
|
||||
pr_err("Sensor:%s set high trip:%d low trip:%d error%d\n",
|
||||
qmi_sens->qmi_name,
|
||||
qmi_sens->high_thresh,
|
||||
qmi_sens->low_thresh,
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct thermal_zone_of_device_ops qmi_sensor_ops = {
|
||||
.get_temp = qmi_sensor_read,
|
||||
.set_trips = qmi_sensor_set_trips,
|
||||
};
|
||||
|
||||
static struct qmi_msg_handler handlers[] = {
|
||||
{
|
||||
.type = QMI_INDICATION,
|
||||
.msg_id = QMI_TS_TEMP_REPORT_IND_V02,
|
||||
.ei = ts_temp_report_ind_msg_v02_ei,
|
||||
.decoded_size = sizeof(struct ts_temp_report_ind_msg_v02),
|
||||
.fn = qmi_ts_ind_cb_v02
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static int qmi_register_sensor_device(struct qmi_sensor *qmi_sens)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
qmi_sens->tz_dev = thermal_zone_of_sensor_register(
|
||||
qmi_sens->dev,
|
||||
qmi_sens->sens_type + qmi_sens->ts->inst_id,
|
||||
qmi_sens, &qmi_sensor_ops);
|
||||
if (IS_ERR(qmi_sens->tz_dev)) {
|
||||
ret = PTR_ERR(qmi_sens->tz_dev);
|
||||
if (ret != -ENODEV)
|
||||
pr_err("sensor register failed for %s, ret:%d\n",
|
||||
qmi_sens->qmi_name, ret);
|
||||
qmi_sens->tz_dev = NULL;
|
||||
return ret;
|
||||
}
|
||||
pr_debug("Sensor register success for %s\n", qmi_sens->qmi_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verify_sensor_and_register(struct qmi_ts_instance *ts)
|
||||
{
|
||||
struct ts_get_sensor_list_req_msg_v02 list_req;
|
||||
struct ts_get_sensor_list_resp_msg_v02 *list_resp;
|
||||
struct ts_get_total_num_of_sensors_req_msg_v02 tot_req;
|
||||
struct ts_get_total_num_of_sensors_resp_msg_v02 tot_resp;
|
||||
int ret = 0, i, j, sensor_list_itr;
|
||||
|
||||
memset(&tot_resp, 0, sizeof(tot_resp));
|
||||
memset(&tot_req, 0, sizeof(tot_req));
|
||||
/* size of list_resp is very high, use heap memory rather than stack */
|
||||
list_resp = kzalloc(sizeof(*list_resp), GFP_KERNEL);
|
||||
if (!list_resp)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = qmi_ts_send_request(ts, QMI_TS_GET_TOTAL_NUM_OF_SENSORS_REQ_V02,
|
||||
TS_GET_TOTAL_NUM_OF_SENSORS_REQ_MSG_V02_MAX_MSG_LEN,
|
||||
ts_get_total_num_of_sensors_req_msg_v02_ei,
|
||||
ts_get_total_num_of_sensors_resp_msg_v02_ei,
|
||||
&tot_req, &tot_resp, &tot_resp.resp);
|
||||
if (ret < 0) {
|
||||
pr_err("qmi ts txn failed, inst_id:%d ret:%d\n",
|
||||
ts->inst_id, ret);
|
||||
goto reg_exit;
|
||||
}
|
||||
|
||||
sensor_list_itr = (tot_resp.total_num_sensors /
|
||||
QMI_TS_SENSOR_LIST_MAX_V02 +
|
||||
(tot_resp.total_num_sensors %
|
||||
QMI_TS_SENSOR_LIST_MAX_V02 ? 1 : 0));
|
||||
|
||||
pr_debug("Total QMI sensors cnt:%d list iteration cnt:%d inst_id:%d\n",
|
||||
tot_resp.total_num_sensors, sensor_list_itr, ts->inst_id);
|
||||
|
||||
for (i = 0; i < sensor_list_itr; i++) {
|
||||
memset(&list_req, 0, sizeof(list_req));
|
||||
memset(list_resp, 0, sizeof(*list_resp));
|
||||
|
||||
list_req.list_index = i;
|
||||
|
||||
ret = qmi_ts_send_request(ts, QMI_TS_GET_SENSOR_LIST_REQ_V02,
|
||||
TS_GET_SENSOR_LIST_REQ_MSG_V02_MAX_MSG_LEN,
|
||||
ts_get_sensor_list_req_msg_v02_ei,
|
||||
ts_get_sensor_list_resp_msg_v02_ei,
|
||||
&list_req, list_resp, &list_resp->resp);
|
||||
if (ret < 0) {
|
||||
pr_err("qmi ts txn failed, inst_id:%d itr:%d ret:%d\n",
|
||||
ts->inst_id, i, ret);
|
||||
goto reg_exit;
|
||||
}
|
||||
|
||||
for (j = 0; j < list_resp->sensor_list_len; j++) {
|
||||
struct qmi_sensor *qmi_sens = NULL;
|
||||
|
||||
pr_debug("QMI TS sensor[%d][%d]: %s\n", i, j,
|
||||
list_resp->sensor_list[j].sensor_id);
|
||||
|
||||
list_for_each_entry(qmi_sens, &ts->ts_sensor_list,
|
||||
ts_node) {
|
||||
if ((strncasecmp(qmi_sens->qmi_name,
|
||||
list_resp->sensor_list[j].sensor_id,
|
||||
QMI_TS_SENSOR_ID_LENGTH_MAX_V02)))
|
||||
continue;
|
||||
|
||||
qmi_sens->connection_active = true;
|
||||
/*
|
||||
* Send a temperature request notification.
|
||||
*/
|
||||
qmi_ts_request(qmi_sens, true);
|
||||
if (!qmi_sens->tz_dev) {
|
||||
ret = qmi_register_sensor_device(qmi_sens);
|
||||
} else {
|
||||
ret = qmi_ts_request(qmi_sens, false);
|
||||
if (ret)
|
||||
pr_err(
|
||||
"sensor:%s trips:%d %d err%d\n",
|
||||
qmi_sens->tz_dev->type,
|
||||
qmi_sens->high_thresh,
|
||||
qmi_sens->low_thresh,
|
||||
ret);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reg_exit:
|
||||
kfree(list_resp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qmi_ts_svc_arrive(struct work_struct *work)
|
||||
{
|
||||
struct qmi_ts_instance *ts = container_of(work,
|
||||
struct qmi_ts_instance,
|
||||
svc_arrive_work);
|
||||
|
||||
verify_sensor_and_register(ts);
|
||||
}
|
||||
|
||||
static void thermal_qmi_net_reset(struct qmi_handle *qmi)
|
||||
{
|
||||
struct qmi_ts_instance *ts = container_of(qmi,
|
||||
struct qmi_ts_instance,
|
||||
handle);
|
||||
struct qmi_sensor *qmi_sens = NULL;
|
||||
int ret;
|
||||
|
||||
pr_debug("reset QMI server\n");
|
||||
list_for_each_entry(qmi_sens, &ts->ts_sensor_list,
|
||||
ts_node) {
|
||||
if (!qmi_sens->connection_active)
|
||||
continue;
|
||||
qmi_ts_request(qmi_sens, true);
|
||||
ret = qmi_ts_request(qmi_sens, false);
|
||||
if (ret)
|
||||
pr_err("Sensor:%s set high trip:%d low trip:%d err%d\n",
|
||||
qmi_sens->tz_dev->type,
|
||||
qmi_sens->high_thresh,
|
||||
qmi_sens->low_thresh,
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void thermal_qmi_del_server(struct qmi_handle *qmi,
|
||||
struct qmi_service *service)
|
||||
{
|
||||
struct qmi_ts_instance *ts = container_of(qmi,
|
||||
struct qmi_ts_instance,
|
||||
handle);
|
||||
struct qmi_sensor *qmi_sens = NULL;
|
||||
|
||||
pr_debug("QMI server deleted\n");
|
||||
list_for_each_entry(qmi_sens, &ts->ts_sensor_list, ts_node)
|
||||
qmi_sens->connection_active = false;
|
||||
}
|
||||
|
||||
static int thermal_qmi_new_server(struct qmi_handle *qmi,
|
||||
struct qmi_service *service)
|
||||
{
|
||||
struct qmi_ts_instance *ts = container_of(qmi,
|
||||
struct qmi_ts_instance,
|
||||
handle);
|
||||
struct sockaddr_qrtr sq = {AF_QIPCRTR, service->node, service->port};
|
||||
|
||||
mutex_lock(&ts->mutex);
|
||||
pr_debug("new QMI server is up, connecting..\n");
|
||||
kernel_connect(qmi->sock, (struct sockaddr *)&sq, sizeof(sq), 0);
|
||||
mutex_unlock(&ts->mutex);
|
||||
queue_work(system_highpri_wq, &ts->svc_arrive_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct qmi_ops thermal_qmi_event_ops = {
|
||||
.new_server = thermal_qmi_new_server,
|
||||
.del_server = thermal_qmi_del_server,
|
||||
.net_reset = thermal_qmi_net_reset,
|
||||
};
|
||||
|
||||
static void qmi_ts_cleanup(void)
|
||||
{
|
||||
struct qmi_ts_instance *ts;
|
||||
struct qmi_sensor *qmi_sens, *c_next;
|
||||
int idx = 0;
|
||||
|
||||
for (; idx < ts_inst_cnt; idx++) {
|
||||
ts = &ts_instances[idx];
|
||||
mutex_lock(&ts->mutex);
|
||||
list_for_each_entry_safe(qmi_sens, c_next,
|
||||
&ts->ts_sensor_list, ts_node) {
|
||||
qmi_sens->connection_active = false;
|
||||
if (qmi_sens->tz_dev) {
|
||||
thermal_zone_of_sensor_unregister(
|
||||
qmi_sens->dev, qmi_sens->tz_dev);
|
||||
qmi_sens->tz_dev = NULL;
|
||||
}
|
||||
|
||||
list_del(&qmi_sens->ts_node);
|
||||
}
|
||||
qmi_handle_release(&ts->handle);
|
||||
|
||||
mutex_unlock(&ts->mutex);
|
||||
}
|
||||
ts_inst_cnt = 0;
|
||||
}
|
||||
|
||||
static int of_get_qmi_ts_platform_data(struct device *dev)
|
||||
{
|
||||
int ret = 0, i = 0, idx = 0;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *subsys_np = NULL;
|
||||
struct qmi_ts_instance *ts;
|
||||
struct qmi_sensor *qmi_sens;
|
||||
int sens_name_max = 0, sens_idx = 0, subsys_cnt = 0;
|
||||
|
||||
subsys_cnt = of_get_available_child_count(np);
|
||||
if (!subsys_cnt) {
|
||||
dev_err(dev, "No child node to process\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ts = devm_kcalloc(dev, subsys_cnt, sizeof(*ts), GFP_KERNEL);
|
||||
if (!ts)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_available_child_of_node(np, subsys_np) {
|
||||
if (idx >= subsys_cnt)
|
||||
break;
|
||||
|
||||
ret = of_property_read_u32(subsys_np, "qcom,instance-id",
|
||||
&ts[idx].inst_id);
|
||||
if (ret) {
|
||||
dev_err(dev, "error reading qcom,insance-id. ret:%d\n",
|
||||
ret);
|
||||
goto data_fetch_err;
|
||||
}
|
||||
|
||||
ts[idx].dev = dev;
|
||||
mutex_init(&ts[idx].mutex);
|
||||
INIT_LIST_HEAD(&ts[idx].ts_sensor_list);
|
||||
INIT_WORK(&ts[idx].svc_arrive_work, qmi_ts_svc_arrive);
|
||||
|
||||
sens_name_max = of_property_count_strings(subsys_np,
|
||||
"qcom,qmi-sensor-names");
|
||||
if (sens_name_max <= 0) {
|
||||
dev_err(dev, "Invalid or no sensor. err:%d\n",
|
||||
sens_name_max);
|
||||
ret = -EINVAL;
|
||||
goto data_fetch_err;
|
||||
}
|
||||
|
||||
for (sens_idx = 0; sens_idx < sens_name_max; sens_idx++) {
|
||||
const char *qmi_name;
|
||||
|
||||
qmi_sens = devm_kzalloc(dev, sizeof(*qmi_sens),
|
||||
GFP_KERNEL);
|
||||
if (!qmi_sens) {
|
||||
ret = -ENOMEM;
|
||||
goto data_fetch_err;
|
||||
}
|
||||
|
||||
of_property_read_string_index(subsys_np,
|
||||
"qcom,qmi-sensor-names", sens_idx,
|
||||
&qmi_name);
|
||||
strscpy(qmi_sens->qmi_name, qmi_name,
|
||||
QMI_CLIENT_NAME_LENGTH);
|
||||
/* Check for supported qmi sensors */
|
||||
for (i = 0; i < QMI_TS_MAX_NR; i++) {
|
||||
if (!strcmp(sensor_clients[i],
|
||||
qmi_sens->qmi_name))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= QMI_TS_MAX_NR) {
|
||||
dev_err(dev, "Unknown sensor:%s\n",
|
||||
qmi_sens->qmi_name);
|
||||
ret = -EINVAL;
|
||||
goto data_fetch_err;
|
||||
}
|
||||
dev_dbg(dev, "QMI sensor:%s available\n", qmi_name);
|
||||
qmi_sens->sens_type = i;
|
||||
qmi_sens->ts = &ts[idx];
|
||||
qmi_sens->dev = dev;
|
||||
qmi_sens->last_reading = 0;
|
||||
qmi_sens->high_thresh = INT_MAX;
|
||||
qmi_sens->low_thresh = -INT_MAX;
|
||||
INIT_WORK(&qmi_sens->therm_notify_work,
|
||||
qmi_ts_thresh_notify);
|
||||
list_add(&qmi_sens->ts_node, &ts[idx].ts_sensor_list);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
ts_instances = ts;
|
||||
ts_inst_cnt = subsys_cnt;
|
||||
|
||||
return 0;
|
||||
data_fetch_err:
|
||||
of_node_put(subsys_np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qmi_sens_device_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret = 0, idx = 0;
|
||||
struct qmi_ts_instance *ts;
|
||||
|
||||
ret = of_get_qmi_ts_platform_data(dev);
|
||||
if (ret)
|
||||
goto probe_err;
|
||||
|
||||
if (!ts_instances || !ts_inst_cnt) {
|
||||
dev_err(dev, "Empty ts instances\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (; idx < ts_inst_cnt; idx++) {
|
||||
ts = &ts_instances[idx];
|
||||
if (list_empty(&ts->ts_sensor_list)) {
|
||||
ret = -ENODEV;
|
||||
goto probe_err;
|
||||
}
|
||||
ret = qmi_handle_init(&ts->handle,
|
||||
TS_GET_SENSOR_LIST_RESP_MSG_V02_MAX_MSG_LEN,
|
||||
&thermal_qmi_event_ops, handlers);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "QMI[0x%x] handle init failed. err:%d\n",
|
||||
ts->inst_id, ret);
|
||||
ts_inst_cnt = idx;
|
||||
ret = -EPROBE_DEFER;
|
||||
goto probe_err;
|
||||
}
|
||||
ret = qmi_add_lookup(&ts->handle, TS_SERVICE_ID_V02,
|
||||
TS_SERVICE_VERS_V02, ts->inst_id);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "QMI register failed for 0x%x, ret:%d\n",
|
||||
ts->inst_id, ret);
|
||||
ret = -EPROBE_DEFER;
|
||||
goto probe_err;
|
||||
}
|
||||
}
|
||||
atomic_set(&in_suspend, 0);
|
||||
register_pm_notifier(&qmi_sensor_pm_nb);
|
||||
return 0;
|
||||
|
||||
probe_err:
|
||||
qmi_ts_cleanup();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qmi_sens_device_remove(struct platform_device *pdev)
|
||||
{
|
||||
qmi_ts_cleanup();
|
||||
unregister_pm_notifier(&qmi_sensor_pm_nb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qmi_sens_device_match[] = {
|
||||
{.compatible = "qcom,qmi-sensors"},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver qmi_sens_device_driver = {
|
||||
.probe = qmi_sens_device_probe,
|
||||
.remove = qmi_sens_device_remove,
|
||||
.driver = {
|
||||
.name = QMI_SENS_DRIVER,
|
||||
.of_match_table = qmi_sens_device_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(qmi_sens_device_driver);
|
||||
MODULE_LICENSE("GPL");
|
||||
286
drivers/thermal/qcom/thermal_sensor_service_v02.c
Normal file
286
drivers/thermal/qcom/thermal_sensor_service_v02.c
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/soc/qcom/qmi.h>
|
||||
#include "thermal_sensor_service_v02.h"
|
||||
|
||||
static struct qmi_elem_info ts_sensor_type_v02_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = QMI_TS_SENSOR_ID_LENGTH_MAX_V02 + 1,
|
||||
.elem_size = sizeof(char),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct ts_sensor_type_v02,
|
||||
sensor_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info ts_get_total_num_of_sensors_req_msg_v02_ei[] = {
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info ts_get_total_num_of_sensors_resp_msg_v02_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct ts_get_total_num_of_sensors_resp_msg_v02,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x03,
|
||||
.offset = offsetof(struct ts_get_total_num_of_sensors_resp_msg_v02,
|
||||
total_num_sensors),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info ts_get_sensor_list_req_msg_v02_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct ts_get_sensor_list_req_msg_v02,
|
||||
list_index),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info ts_get_sensor_list_resp_msg_v02_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct ts_get_sensor_list_resp_msg_v02,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct ts_get_sensor_list_resp_msg_v02,
|
||||
sensor_list_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_DATA_LEN,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct ts_get_sensor_list_resp_msg_v02,
|
||||
sensor_list_len),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = QMI_TS_SENSOR_LIST_MAX_V02,
|
||||
.elem_size = sizeof(struct ts_sensor_type_v02),
|
||||
.array_type = VAR_LEN_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct ts_get_sensor_list_resp_msg_v02,
|
||||
sensor_list),
|
||||
.ei_array = ts_sensor_type_v02_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info ts_register_notification_temp_req_msg_v02_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct ts_sensor_type_v02),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct ts_register_notification_temp_req_msg_v02,
|
||||
sensor_id),
|
||||
.ei_array = ts_sensor_type_v02_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct ts_register_notification_temp_req_msg_v02,
|
||||
send_current_temp_report),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct ts_register_notification_temp_req_msg_v02,
|
||||
temp_threshold_high_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(int),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct ts_register_notification_temp_req_msg_v02,
|
||||
temp_threshold_high),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct ts_register_notification_temp_req_msg_v02,
|
||||
temp_threshold_low_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(int),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct ts_register_notification_temp_req_msg_v02,
|
||||
temp_threshold_low),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset = offsetof(struct ts_register_notification_temp_req_msg_v02,
|
||||
seq_num_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset = offsetof(struct ts_register_notification_temp_req_msg_v02,
|
||||
seq_num),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info ts_register_notification_temp_resp_msg_v02_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct ts_register_notification_temp_resp_msg_v02,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info ts_temp_report_ind_msg_v02_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct ts_sensor_type_v02),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct ts_temp_report_ind_msg_v02,
|
||||
sensor_id),
|
||||
.ei_array = ts_sensor_type_v02_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(enum ts_temp_report_type_enum_v02),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct ts_temp_report_ind_msg_v02,
|
||||
report_type),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct ts_temp_report_ind_msg_v02,
|
||||
temp_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(int),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct ts_temp_report_ind_msg_v02,
|
||||
temp),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct ts_temp_report_ind_msg_v02,
|
||||
seq_num_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct ts_temp_report_ind_msg_v02,
|
||||
seq_num),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
98
drivers/thermal/qcom/thermal_sensor_service_v02.h
Normal file
98
drivers/thermal/qcom/thermal_sensor_service_v02.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef THERMAL_SENSOR_SERVICE_V02_H
|
||||
#define THERMAL_SENSOR_SERVICE_V02_H
|
||||
|
||||
#define TS_SERVICE_ID_V02 0x17
|
||||
#define TS_SERVICE_VERS_V02 0x02
|
||||
|
||||
#define QMI_TS_GET_SUPPORTED_MSGS_RESP_V02 0x001E
|
||||
#define QMI_TS_GET_SENSOR_LIST_RESP_V02 0x0031
|
||||
#define QMI_TS_GET_SUPPORTED_MSGS_REQ_V02 0x001E
|
||||
#define QMI_TS_GET_TOTAL_NUM_OF_SENSORS_RESP_V02 0x0030
|
||||
#define QMI_TS_REGISTER_NOTIFICATION_TEMP_REQ_V02 0x0032
|
||||
#define QMI_TS_REGISTER_NOTIFICATION_TEMP_RESP_V02 0x0032
|
||||
#define QMI_TS_GET_TOTAL_NUM_OF_SENSORS_REQ_V02 0x0030
|
||||
#define QMI_TS_GET_SUPPORTED_FIELDS_RESP_V02 0x001F
|
||||
#define QMI_TS_GET_SENSOR_LIST_REQ_V02 0x0031
|
||||
#define QMI_TS_TEMP_REPORT_IND_V02 0x0033
|
||||
#define QMI_TS_GET_SUPPORTED_FIELDS_REQ_V02 0x001F
|
||||
|
||||
#define QMI_TS_SENSOR_ID_LENGTH_MAX_V02 32
|
||||
#define QMI_TS_SENSOR_LIST_MAX_V02 96
|
||||
|
||||
struct ts_sensor_type_v02 {
|
||||
char sensor_id[QMI_TS_SENSOR_ID_LENGTH_MAX_V02 + 1];
|
||||
};
|
||||
|
||||
struct ts_get_total_num_of_sensors_req_msg_v02 {
|
||||
char placeholder;
|
||||
};
|
||||
#define TS_GET_TOTAL_NUM_OF_SENSORS_REQ_MSG_V02_MAX_MSG_LEN 0
|
||||
extern struct qmi_elem_info ts_get_total_num_of_sensors_req_msg_v02_ei[];
|
||||
|
||||
struct ts_get_total_num_of_sensors_resp_msg_v02 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
u32 total_num_sensors;
|
||||
};
|
||||
#define TS_GET_TOTAL_NUM_OF_SENSORS_RESP_MSG_V02_MAX_MSG_LEN 14
|
||||
extern struct qmi_elem_info ts_get_total_num_of_sensors_resp_msg_v02_ei[];
|
||||
|
||||
struct ts_get_sensor_list_req_msg_v02 {
|
||||
u32 list_index;
|
||||
};
|
||||
#define TS_GET_SENSOR_LIST_REQ_MSG_V02_MAX_MSG_LEN 7
|
||||
extern struct qmi_elem_info ts_get_sensor_list_req_msg_v02_ei[];
|
||||
|
||||
struct ts_get_sensor_list_resp_msg_v02 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
u8 sensor_list_valid;
|
||||
u32 sensor_list_len;
|
||||
struct ts_sensor_type_v02 sensor_list[QMI_TS_SENSOR_LIST_MAX_V02];
|
||||
};
|
||||
#define TS_GET_SENSOR_LIST_RESP_MSG_V02_MAX_MSG_LEN 3179
|
||||
extern struct qmi_elem_info ts_get_sensor_list_resp_msg_v02_ei[];
|
||||
|
||||
struct ts_register_notification_temp_req_msg_v02 {
|
||||
struct ts_sensor_type_v02 sensor_id;
|
||||
u8 send_current_temp_report;
|
||||
u8 temp_threshold_high_valid;
|
||||
int temp_threshold_high;
|
||||
u8 temp_threshold_low_valid;
|
||||
int temp_threshold_low;
|
||||
u8 seq_num_valid;
|
||||
u32 seq_num;
|
||||
};
|
||||
#define TS_REGISTER_NOTIFICATION_TEMP_REQ_MSG_V02_MAX_MSG_LEN 61
|
||||
extern struct qmi_elem_info ts_register_notification_temp_req_msg_v02_ei[];
|
||||
|
||||
struct ts_register_notification_temp_resp_msg_v02 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
#define TS_REGISTER_NOTIFICATION_TEMP_RESP_MSG_V02_MAX_MSG_LEN 7
|
||||
extern struct qmi_elem_info ts_register_notification_temp_resp_msg_v02_ei[];
|
||||
|
||||
enum ts_temp_report_type_enum_v02 {
|
||||
TS_TEMP_REPORT_TYPE_ENUM_MIN_VAL_V02 = INT_MIN,
|
||||
QMI_TS_TEMP_REPORT_CURRENT_TEMP_V02 = 0,
|
||||
QMI_TS_TEMP_REPORT_THRESHOLD_HIGH_V02 = 1,
|
||||
QMI_TS_TEMP_REPORT_THRESHOLD_LOW_V02 = 2,
|
||||
TS_TEMP_REPORT_TYPE_ENUM_MAX_VAL_V02 = INT_MAX,
|
||||
};
|
||||
|
||||
struct ts_temp_report_ind_msg_v02 {
|
||||
struct ts_sensor_type_v02 sensor_id;
|
||||
enum ts_temp_report_type_enum_v02 report_type;
|
||||
u8 temp_valid;
|
||||
int temp;
|
||||
u8 seq_num_valid;
|
||||
u32 seq_num;
|
||||
};
|
||||
#define TS_TEMP_REPORT_IND_MSG_V02_MAX_MSG_LEN 57
|
||||
extern struct qmi_elem_info ts_temp_report_ind_msg_v02_ei[];
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user