305 lines
7.4 KiB
C
305 lines
7.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2021 MediaTek Inc.
|
|
*/
|
|
#include <linux/bits.h>
|
|
#include <linux/device.h>
|
|
#include <linux/io.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_platform.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/thermal.h>
|
|
#include "vtskin_temp.h"
|
|
|
|
static int vtskin_get_temp(void *data, int *temp)
|
|
{
|
|
struct vtskin_temp_tz *skin_tz = (struct vtskin_temp_tz *)data;
|
|
struct vtskin_data *skin_data = skin_tz->skin_data;
|
|
struct vtskin_tz_param *skin_param = skin_data->params;
|
|
struct thermal_zone_device *tzd;
|
|
long long vtskin = 0, coef;
|
|
int tz_temp, i, ret;
|
|
char *sensor_name;
|
|
|
|
if (skin_param[skin_tz->id].ref_num == 0) {
|
|
*temp = THERMAL_TEMP_INVALID;
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; i < skin_param[skin_tz->id].ref_num; i++) {
|
|
sensor_name = skin_param[skin_tz->id].vtskin_ref[i].sensor_name;
|
|
if (!sensor_name) {
|
|
dev_err(skin_data->dev, "get sensor name fail %d\n", i);
|
|
*temp = THERMAL_TEMP_INVALID;
|
|
return -EINVAL;
|
|
}
|
|
|
|
tzd = thermal_zone_get_zone_by_name(sensor_name);
|
|
if (IS_ERR_OR_NULL(tzd) || !tzd->ops->get_temp) {
|
|
dev_err(skin_data->dev, "get %s temp fail\n", sensor_name);
|
|
*temp = THERMAL_TEMP_INVALID;
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = tzd->ops->get_temp(tzd, &tz_temp);
|
|
if (ret < 0) {
|
|
dev_err(skin_data->dev, "%s get_temp fail %d\n", sensor_name, ret);
|
|
*temp = THERMAL_TEMP_INVALID;
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (skin_param[skin_tz->id].operation == OP_MAX) {
|
|
if (i == 0)
|
|
*temp = THERMAL_TEMP_INVALID;
|
|
|
|
if (tz_temp > *temp)
|
|
*temp = tz_temp;
|
|
|
|
} else if (skin_param[skin_tz->id].operation == OP_COEF) {
|
|
coef = skin_param[skin_tz->id].vtskin_ref[i].sensor_coef;
|
|
vtskin += tz_temp * coef;
|
|
if (i == skin_param[skin_tz->id].ref_num - 1)
|
|
*temp = (int)(vtskin / 100000000);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct thermal_zone_of_device_ops vtskin_ops = {
|
|
.get_temp = vtskin_get_temp,
|
|
};
|
|
|
|
static int vtskin_probe(struct platform_device *pdev)
|
|
{
|
|
struct device *dev = &pdev->dev;
|
|
struct vtskin_temp_tz *skin_tz;
|
|
struct vtskin_data *skin_data;
|
|
struct thermal_zone_device *tzdev;
|
|
int i, ret;
|
|
|
|
if (!pdev->dev.of_node) {
|
|
dev_err(dev, "Only DT based supported\n");
|
|
return -ENODEV;
|
|
}
|
|
|
|
skin_data = (struct vtskin_data *)of_device_get_match_data(dev);
|
|
if (!skin_data) {
|
|
dev_err(dev, "Error: Failed to get lvts platform data\n");
|
|
return -ENODATA;
|
|
}
|
|
|
|
skin_data->dev = dev;
|
|
platform_set_drvdata(pdev, skin_data);
|
|
|
|
for (i = 0; i < skin_data->num_sensor; i++) {
|
|
skin_tz = devm_kzalloc(dev, sizeof(*skin_tz), GFP_KERNEL);
|
|
if (!skin_tz)
|
|
return -ENOMEM;
|
|
|
|
skin_tz->id = i;
|
|
skin_tz->skin_data = skin_data;
|
|
|
|
tzdev = devm_thermal_zone_of_sensor_register(dev, skin_tz->id,
|
|
skin_tz, &vtskin_ops);
|
|
|
|
if (IS_ERR(tzdev)) {
|
|
ret = PTR_ERR(tzdev);
|
|
dev_err(dev,
|
|
"Error: Failed to register skin_tz.id %d, ret = %d\n",
|
|
skin_tz->id, ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = snprintf(skin_data->params[i].tz_name, THERMAL_NAME_LENGTH, tzdev->type);
|
|
if (ret < 0)
|
|
dev_notice(dev, "copy tz_name fail %s\n", tzdev->type);
|
|
}
|
|
|
|
plat_vtskin_info = skin_data;
|
|
|
|
return 0;
|
|
}
|
|
|
|
enum mt6983_vtskin_sensor_enum {
|
|
MT6983_VTSKIN_MAX,
|
|
MT6983_VTSKIN_1,
|
|
MT6983_VTSKIN_2,
|
|
MT6983_VTSKIN_3,
|
|
MT6983_VTSKIN_4,
|
|
MT6983_VTSKIN_5,
|
|
MT6983_VTSKIN_6,
|
|
MT6983_VTSKIN_NUM,
|
|
};
|
|
|
|
struct vtskin_tz_param mt6983_vtskin_params[] = {
|
|
[MT6983_VTSKIN_MAX] = {
|
|
.ref_num = 4,
|
|
.operation = OP_MAX,
|
|
.vtskin_ref = {
|
|
{ "vtskin1", 0},
|
|
{ "vtskin2", 0},
|
|
{ "vtskin3", 0},
|
|
{ "vtskin4", 0}},
|
|
},
|
|
[MT6983_VTSKIN_1] = {
|
|
.ref_num = 8,
|
|
.operation = OP_COEF,
|
|
.vtskin_ref = {
|
|
{ "soc_top", 2313635},
|
|
{ "ap_ntc", -17278441},
|
|
{ "nrpa_ntc", 168147662},
|
|
{ "pmic6363_bk3_bk7", 564886},
|
|
{ "pmic6373_bk3_bk7", -490919},
|
|
{ "pmic6338_ts", -40986186},
|
|
{ "consys", 3412150},
|
|
{ "battery", -22576691}},
|
|
},
|
|
[MT6983_VTSKIN_2] = {
|
|
.ref_num = 8,
|
|
.operation = OP_COEF,
|
|
.vtskin_ref = {
|
|
{ "soc_top", 3255065},
|
|
{ "ap_ntc", -62150677},
|
|
{ "nrpa_ntc", 149976078},
|
|
{ "pmic6363_bk3_bk7", 22876394},
|
|
{ "pmic6373_bk3_bk7", -2064824},
|
|
{ "pmic6338_ts", 27027423},
|
|
{ "consys", -15933089},
|
|
{ "battery", -34217383}},
|
|
},
|
|
[MT6983_VTSKIN_3] = {
|
|
.ref_num = 8,
|
|
.operation = OP_COEF,
|
|
.vtskin_ref = {
|
|
{ "soc_top", 574011},
|
|
{ "ap_ntc", -46643505},
|
|
{ "nrpa_ntc", 167793585},
|
|
{ "pmic6363_bk3_bk7", 14117694},
|
|
{ "pmic6373_bk3_bk7", -825852},
|
|
{ "pmic6338_ts", -20259317},
|
|
{ "consys", 2173021},
|
|
{ "battery", -22997333}},
|
|
},
|
|
[MT6983_VTSKIN_4] = {
|
|
.ref_num = 8,
|
|
.operation = OP_COEF,
|
|
.vtskin_ref = {
|
|
{ "soc_top", 1025071},
|
|
{ "ap_ntc", -46468989},
|
|
{ "nrpa_ntc", 163038976},
|
|
{ "pmic6363_bk3_bk7", 13007917},
|
|
{ "pmic6373_bk3_bk7", -575286},
|
|
{ "pmic6338_ts", -14243451},
|
|
{ "consys", 149975},
|
|
{ "battery", -21612202}},
|
|
},
|
|
[MT6983_VTSKIN_5] = {
|
|
.ref_num = 8,
|
|
.operation = OP_COEF,
|
|
.vtskin_ref = {
|
|
{ "soc_top", 2272107},
|
|
{ "ap_ntc", -12028723},
|
|
{ "nrpa_ntc", 167869082},
|
|
{ "pmic6363_bk3_bk7", -1604055},
|
|
{ "pmic6373_bk3_bk7", -339789},
|
|
{ "pmic6338_ts", -46784687},
|
|
{ "consys", 5544910},
|
|
{ "battery", -21683366}},
|
|
},
|
|
[MT6983_VTSKIN_6] = {
|
|
.ref_num = 8,
|
|
.operation = OP_COEF,
|
|
.vtskin_ref = {
|
|
{ "soc_top", 1192347},
|
|
{ "ap_ntc", -26876988},
|
|
{ "nrpa_ntc", 151476705},
|
|
{ "pmic6363_bk3_bk7", 9613622},
|
|
{ "pmic6373_bk3_bk7", -910593},
|
|
{ "pmic6338_ts", -26222648},
|
|
{ "consys", 2997056},
|
|
{ "battery", -19949450}},
|
|
}
|
|
};
|
|
|
|
static struct vtskin_data mt6983_vtskin_data = {
|
|
.num_sensor = MT6983_VTSKIN_NUM,
|
|
.params = mt6983_vtskin_params,
|
|
};
|
|
|
|
enum mt6985_vtskin_sensor_enum {
|
|
MT6985_VTSKIN_MAX,
|
|
MT6985_VTSKIN_1,
|
|
MT6985_VTSKIN_2,
|
|
MT6985_VTSKIN_3,
|
|
MT6985_VTSKIN_4,
|
|
MT6985_VTSKIN_5,
|
|
MT6985_VTSKIN_6,
|
|
MT6985_VTSKIN_NUM,
|
|
};
|
|
|
|
struct vtskin_tz_param mt6985_vtskin_params[] = {
|
|
[MT6985_VTSKIN_MAX] = {
|
|
.ref_num = 0,
|
|
.operation = OP_MAX,
|
|
},
|
|
[MT6985_VTSKIN_1] = {
|
|
.ref_num = 0,
|
|
.operation = OP_COEF,
|
|
},
|
|
[MT6985_VTSKIN_2] = {
|
|
.ref_num = 0,
|
|
.operation = OP_COEF,
|
|
},
|
|
[MT6985_VTSKIN_3] = {
|
|
.ref_num = 0,
|
|
.operation = OP_COEF,
|
|
},
|
|
[MT6985_VTSKIN_4] = {
|
|
.ref_num = 0,
|
|
.operation = OP_COEF,
|
|
},
|
|
[MT6985_VTSKIN_5] = {
|
|
.ref_num = 0,
|
|
.operation = OP_COEF,
|
|
},
|
|
[MT6985_VTSKIN_6] = {
|
|
.ref_num = 0,
|
|
.operation = OP_COEF,
|
|
}
|
|
};
|
|
|
|
static struct vtskin_data mt6985_vtskin_data = {
|
|
.num_sensor = MT6985_VTSKIN_NUM,
|
|
.params = mt6985_vtskin_params,
|
|
};
|
|
|
|
static const struct of_device_id vtskin_of_match[] = {
|
|
{
|
|
.compatible = "mediatek,mt6983-virtual-tskin",
|
|
.data = (void *)&mt6983_vtskin_data,
|
|
},
|
|
{
|
|
.compatible = "mediatek,mt6985-virtual-tskin",
|
|
.data = (void *)&mt6985_vtskin_data,
|
|
},
|
|
{},
|
|
};
|
|
MODULE_DEVICE_TABLE(of, vtskin_of_match);
|
|
|
|
static struct platform_driver vtskin_driver = {
|
|
.probe = vtskin_probe,
|
|
.driver = {
|
|
.name = "mtk-virtual-tskin",
|
|
.of_match_table = vtskin_of_match,
|
|
},
|
|
};
|
|
|
|
module_platform_driver(vtskin_driver);
|
|
|
|
MODULE_AUTHOR("Samuel Hsieh <samuel.hsieh@mediatek.com>");
|
|
MODULE_DESCRIPTION("Mediatek on virtual tskin driver");
|
|
MODULE_LICENSE("GPL v2");
|