thermal: qpnp-adc: Add snapshot of qpnp-adc-tm driver
This is snapshot of qpnp-adc-tm driver as of msm-4.9 'commit 7e65e03259909 (Merge "msm: kgsl: Deregister gpu address on memdesc_sg_virt failure")'. Removed support for adc_tm_hc and hkadc_ldo as they are not used for SPF targets. Removed IADC, VADC APIS, structs and enums not needed for ADC_TM. VADC functions required for sake of compilation have been retained, which will be subsequently replaced with IIO functions to suit msm-4.19. Change-Id: If8e4fb03471ec045293659b2404f8be95684f8be Signed-off-by: Manjunatha Madana <mamanj@codeaurora.org> Signed-off-by: Archana Sriram <apsrir@codeaurora.org>
This commit is contained in:
parent
7f766a685e
commit
14595b56e3
5 changed files with 4815 additions and 0 deletions
|
@ -478,6 +478,17 @@ config GENERIC_ADC_THERMAL
|
|||
to this driver. This driver reports the temperature by reading ADC
|
||||
channel and converts it to temperature based on lookup table.
|
||||
|
||||
config THERMAL_QPNP_ADC_TM
|
||||
tristate "Qualcomm Technologies Inc. Thermal Monitor ADC Driver"
|
||||
depends on THERMAL
|
||||
depends on SPMI
|
||||
help
|
||||
This enables the thermal Sysfs driver for the ADC thermal monitoring
|
||||
device. It shows up in Sysfs as a thermal zone with multiple trip points.
|
||||
Disabling the thermal zone device via the mode file results in disabling
|
||||
the sensor. Also able to set threshold temperature for both hot and cold
|
||||
and update when a threshold is reached.
|
||||
|
||||
config THERMAL_TSENS
|
||||
tristate "Qualcomm Technologies Inc. TSENS Temperature driver"
|
||||
depends on THERMAL
|
||||
|
|
|
@ -60,6 +60,7 @@ obj-y += tegra/
|
|||
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
|
||||
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
|
||||
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
|
||||
obj-$(CONFIG_THERMAL_QPNP_ADC_TM) += qpnp-adc-tm.o qpnp-adc-common.o
|
||||
obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
|
||||
obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o
|
||||
obj-$(CONFIG_THERMAL_TSENS) += msm-tsens.o tsens2xxx.o tsens-dbg.o tsens-mtc.o tsens1xxx.o tsens-calib.o
|
||||
|
|
920
drivers/thermal/qpnp-adc-common.c
Normal file
920
drivers/thermal/qpnp-adc-common.c
Normal file
|
@ -0,0 +1,920 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "%s: " fmt, __func__
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/qpnp/qpnp-adc.h>
|
||||
|
||||
#define KELVINMIL_DEGMIL 273160
|
||||
/*
|
||||
* Units for temperature below (on x axis) is in 0.1DegC as
|
||||
* required by the battery driver. Note the resolution used
|
||||
* here to compute the table was done for DegC to milli-volts.
|
||||
* In consideration to limit the size of the table for the given
|
||||
* temperature range below, the result is linearly interpolated
|
||||
* and provided to the battery driver in the units desired for
|
||||
* their framework which is 0.1DegC. True resolution of 0.1DegC
|
||||
* will result in the below table size to increase by 10 times.
|
||||
*/
|
||||
static const struct qpnp_vadc_map_pt adcmap_btm_threshold[] = {
|
||||
{-300, 1642},
|
||||
{-200, 1544},
|
||||
{-100, 1414},
|
||||
{0, 1260},
|
||||
{10, 1244},
|
||||
{20, 1228},
|
||||
{30, 1212},
|
||||
{40, 1195},
|
||||
{50, 1179},
|
||||
{60, 1162},
|
||||
{70, 1146},
|
||||
{80, 1129},
|
||||
{90, 1113},
|
||||
{100, 1097},
|
||||
{110, 1080},
|
||||
{120, 1064},
|
||||
{130, 1048},
|
||||
{140, 1032},
|
||||
{150, 1016},
|
||||
{160, 1000},
|
||||
{170, 985},
|
||||
{180, 969},
|
||||
{190, 954},
|
||||
{200, 939},
|
||||
{210, 924},
|
||||
{220, 909},
|
||||
{230, 894},
|
||||
{240, 880},
|
||||
{250, 866},
|
||||
{260, 852},
|
||||
{270, 838},
|
||||
{280, 824},
|
||||
{290, 811},
|
||||
{300, 798},
|
||||
{310, 785},
|
||||
{320, 773},
|
||||
{330, 760},
|
||||
{340, 748},
|
||||
{350, 736},
|
||||
{360, 725},
|
||||
{370, 713},
|
||||
{380, 702},
|
||||
{390, 691},
|
||||
{400, 681},
|
||||
{410, 670},
|
||||
{420, 660},
|
||||
{430, 650},
|
||||
{440, 640},
|
||||
{450, 631},
|
||||
{460, 622},
|
||||
{470, 613},
|
||||
{480, 604},
|
||||
{490, 595},
|
||||
{500, 587},
|
||||
{510, 579},
|
||||
{520, 571},
|
||||
{530, 563},
|
||||
{540, 556},
|
||||
{550, 548},
|
||||
{560, 541},
|
||||
{570, 534},
|
||||
{580, 527},
|
||||
{590, 521},
|
||||
{600, 514},
|
||||
{610, 508},
|
||||
{620, 502},
|
||||
{630, 496},
|
||||
{640, 490},
|
||||
{650, 485},
|
||||
{660, 281},
|
||||
{670, 274},
|
||||
{680, 267},
|
||||
{690, 260},
|
||||
{700, 254},
|
||||
{710, 247},
|
||||
{720, 241},
|
||||
{730, 235},
|
||||
{740, 229},
|
||||
{750, 224},
|
||||
{760, 218},
|
||||
{770, 213},
|
||||
{780, 208},
|
||||
{790, 203}
|
||||
};
|
||||
|
||||
/* Voltage to temperature */
|
||||
static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb[] = {
|
||||
{1758, -40000},
|
||||
{1742, -35000},
|
||||
{1719, -30000},
|
||||
{1691, -25000},
|
||||
{1654, -20000},
|
||||
{1608, -15000},
|
||||
{1551, -10000},
|
||||
{1483, -5000},
|
||||
{1404, 0},
|
||||
{1315, 5000},
|
||||
{1218, 10000},
|
||||
{1114, 15000},
|
||||
{1007, 20000},
|
||||
{900, 25000},
|
||||
{795, 30000},
|
||||
{696, 35000},
|
||||
{605, 40000},
|
||||
{522, 45000},
|
||||
{448, 50000},
|
||||
{383, 55000},
|
||||
{327, 60000},
|
||||
{278, 65000},
|
||||
{237, 70000},
|
||||
{202, 75000},
|
||||
{172, 80000},
|
||||
{146, 85000},
|
||||
{125, 90000},
|
||||
{107, 95000},
|
||||
{92, 100000},
|
||||
{79, 105000},
|
||||
{68, 110000},
|
||||
{59, 115000},
|
||||
{51, 120000},
|
||||
{44, 125000}
|
||||
};
|
||||
|
||||
static const struct qpnp_vadc_map_pt adcmap_smb_batt_therm[] = {
|
||||
{-300, 1625},
|
||||
{-200, 1515},
|
||||
{-100, 1368},
|
||||
{0, 1192},
|
||||
{10, 1173},
|
||||
{20, 1154},
|
||||
{30, 1135},
|
||||
{40, 1116},
|
||||
{50, 1097},
|
||||
{60, 1078},
|
||||
{70, 1059},
|
||||
{80, 1040},
|
||||
{90, 1020},
|
||||
{100, 1001},
|
||||
{110, 982},
|
||||
{120, 963},
|
||||
{130, 944},
|
||||
{140, 925},
|
||||
{150, 907},
|
||||
{160, 888},
|
||||
{170, 870},
|
||||
{180, 851},
|
||||
{190, 833},
|
||||
{200, 815},
|
||||
{210, 797},
|
||||
{220, 780},
|
||||
{230, 762},
|
||||
{240, 745},
|
||||
{250, 728},
|
||||
{260, 711},
|
||||
{270, 695},
|
||||
{280, 679},
|
||||
{290, 663},
|
||||
{300, 647},
|
||||
{310, 632},
|
||||
{320, 616},
|
||||
{330, 602},
|
||||
{340, 587},
|
||||
{350, 573},
|
||||
{360, 559},
|
||||
{370, 545},
|
||||
{380, 531},
|
||||
{390, 518},
|
||||
{400, 505},
|
||||
{410, 492},
|
||||
{420, 480},
|
||||
{430, 465},
|
||||
{440, 456},
|
||||
{450, 445},
|
||||
{460, 433},
|
||||
{470, 422},
|
||||
{480, 412},
|
||||
{490, 401},
|
||||
{500, 391},
|
||||
{510, 381},
|
||||
{520, 371},
|
||||
{530, 362},
|
||||
{540, 352},
|
||||
{550, 343},
|
||||
{560, 335},
|
||||
{570, 326},
|
||||
{580, 318},
|
||||
{590, 309},
|
||||
{600, 302},
|
||||
{610, 294},
|
||||
{620, 286},
|
||||
{630, 279},
|
||||
{640, 272},
|
||||
{650, 265},
|
||||
{660, 258},
|
||||
{670, 252},
|
||||
{680, 245},
|
||||
{690, 239},
|
||||
{700, 233},
|
||||
{710, 227},
|
||||
{720, 221},
|
||||
{730, 216},
|
||||
{740, 211},
|
||||
{750, 205},
|
||||
{760, 200},
|
||||
{770, 195},
|
||||
{780, 190},
|
||||
{790, 186}
|
||||
};
|
||||
|
||||
/* Voltage to temperature */
|
||||
static const struct qpnp_vadc_map_pt adcmap_batt_therm_qrd_215[] = {
|
||||
{1575, -200},
|
||||
{1549, -180},
|
||||
{1522, -160},
|
||||
{1493, -140},
|
||||
{1463, -120},
|
||||
{1431, -100},
|
||||
{1398, -80},
|
||||
{1364, -60},
|
||||
{1329, -40},
|
||||
{1294, -20},
|
||||
{1258, 0},
|
||||
{1222, 20},
|
||||
{1187, 40},
|
||||
{1151, 60},
|
||||
{1116, 80},
|
||||
{1082, 100},
|
||||
{1049, 120},
|
||||
{1016, 140},
|
||||
{985, 160},
|
||||
{955, 180},
|
||||
{926, 200},
|
||||
{899, 220},
|
||||
{873, 240},
|
||||
{849, 260},
|
||||
{825, 280},
|
||||
{804, 300},
|
||||
{783, 320},
|
||||
{764, 340},
|
||||
{746, 360},
|
||||
{729, 380},
|
||||
{714, 400},
|
||||
{699, 420},
|
||||
{686, 440},
|
||||
{673, 460},
|
||||
{662, 480},
|
||||
{651, 500},
|
||||
{641, 520},
|
||||
{632, 540},
|
||||
{623, 560},
|
||||
{615, 580},
|
||||
{608, 600},
|
||||
{601, 620},
|
||||
{595, 640},
|
||||
{589, 660},
|
||||
{583, 680},
|
||||
{578, 700},
|
||||
{574, 720},
|
||||
{569, 740},
|
||||
{565, 760},
|
||||
{562, 780},
|
||||
{558, 800}
|
||||
};
|
||||
|
||||
/* Added for resolving compilation */
|
||||
struct qpnp_vadc_mode_state {
|
||||
bool meas_int_mode;
|
||||
bool meas_int_request_in_queue;
|
||||
bool vadc_meas_int_enable;
|
||||
struct qpnp_adc_tm_btm_param *param;
|
||||
struct qpnp_adc_amux vadc_meas_amux;
|
||||
};
|
||||
|
||||
struct qpnp_vadc_thermal_data {
|
||||
bool thermal_node;
|
||||
int thermal_chan;
|
||||
enum qpnp_vadc_channels vadc_channel;
|
||||
struct thermal_zone_device *tz_dev;
|
||||
struct qpnp_vadc_chip *vadc_dev;
|
||||
};
|
||||
|
||||
struct qpnp_vadc_chip {
|
||||
struct device *dev;
|
||||
struct qpnp_adc_drv *adc;
|
||||
struct list_head list;
|
||||
struct device *vadc_hwmon;
|
||||
bool vadc_init_calib;
|
||||
int max_channels_available;
|
||||
bool vadc_iadc_sync_lock;
|
||||
u8 id;
|
||||
struct work_struct trigger_completion_work;
|
||||
bool vadc_poll_eoc;
|
||||
bool vadc_recalib_check;
|
||||
u8 revision_ana_minor;
|
||||
u8 revision_dig_major;
|
||||
struct work_struct trigger_high_thr_work;
|
||||
struct work_struct trigger_low_thr_work;
|
||||
struct qpnp_vadc_mode_state *state_copy;
|
||||
struct qpnp_vadc_thermal_data *vadc_therm_chan;
|
||||
struct power_supply *vadc_chg_vote;
|
||||
int vadc_debug_count;
|
||||
struct pmic_revid_data *pmic_rev_id;
|
||||
};
|
||||
/* Added for compilation */
|
||||
|
||||
static int32_t qpnp_adc_map_voltage_temp(const struct qpnp_vadc_map_pt *pts,
|
||||
uint32_t tablesize, int32_t input, int64_t *output)
|
||||
{
|
||||
unsigned int descending = 1;
|
||||
uint32_t i = 0;
|
||||
|
||||
if (pts == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if table is descending or ascending */
|
||||
if (tablesize > 1) {
|
||||
if (pts[0].x < pts[1].x)
|
||||
descending = 0;
|
||||
}
|
||||
|
||||
while (i < tablesize) {
|
||||
if ((descending == 1) && (pts[i].x < input)) {
|
||||
/*
|
||||
* table entry is less than measured
|
||||
* value and table is descending, stop.
|
||||
*/
|
||||
break;
|
||||
} else if ((descending == 0) &&
|
||||
(pts[i].x > input)) {
|
||||
/*
|
||||
* table entry is greater than measured
|
||||
* value and table is ascending, stop.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
*output = pts[0].y;
|
||||
else if (i == tablesize)
|
||||
*output = pts[tablesize-1].y;
|
||||
else {
|
||||
/* result is between search_index and search_index-1 */
|
||||
/* interpolate linearly */
|
||||
*output = (((int32_t) ((pts[i].y - pts[i-1].y)*
|
||||
(input - pts[i-1].x))/
|
||||
(pts[i].x - pts[i-1].x))+
|
||||
pts[i-1].y);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t qpnp_adc_map_temp_voltage(const struct qpnp_vadc_map_pt *pts,
|
||||
uint32_t tablesize, int32_t input, int64_t *output)
|
||||
{
|
||||
unsigned int descending = 1;
|
||||
uint32_t i = 0;
|
||||
|
||||
if (pts == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if table is descending or ascending */
|
||||
if (tablesize > 1) {
|
||||
if (pts[0].y < pts[1].y)
|
||||
descending = 0;
|
||||
}
|
||||
|
||||
while (i < tablesize) {
|
||||
if ((descending == 1) && (pts[i].y < input)) {
|
||||
/* Table entry is less than measured value. */
|
||||
/* Table is descending, stop. */
|
||||
break;
|
||||
} else if ((descending == 0) && (pts[i].y > input)) {
|
||||
/* Table entry is greater than measured value. */
|
||||
/* Table is ascending, stop. */
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
*output = pts[0].x;
|
||||
} else if (i == tablesize) {
|
||||
*output = pts[tablesize-1].x;
|
||||
} else {
|
||||
/* result is between search_index and search_index-1 */
|
||||
/* interpolate linearly */
|
||||
*output = (((int32_t) ((pts[i].x - pts[i-1].x)*
|
||||
(input - pts[i-1].y))/
|
||||
(pts[i].y - pts[i-1].y))+
|
||||
pts[i-1].x);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *chip,
|
||||
const struct qpnp_adc_properties *adc_properties,
|
||||
struct qpnp_adc_tm_config *param)
|
||||
{
|
||||
struct qpnp_vadc_linear_graph param1;
|
||||
int rc;
|
||||
|
||||
/* TODO: modify as per iio functions
|
||||
* qpnp_get_vadc_gain_and_offset(chip, ¶m1, CALIB_RATIOMETRIC);
|
||||
*/
|
||||
|
||||
rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
|
||||
ARRAY_SIZE(adcmap_100k_104ef_104fb),
|
||||
param->low_thr_temp, ¶m->low_thr_voltage);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
param->low_thr_voltage *= param1.dy;
|
||||
param->low_thr_voltage = div64_s64(param->low_thr_voltage,
|
||||
param1.adc_vref);
|
||||
param->low_thr_voltage += param1.adc_gnd;
|
||||
|
||||
rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
|
||||
ARRAY_SIZE(adcmap_100k_104ef_104fb),
|
||||
param->high_thr_temp, ¶m->high_thr_voltage);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
param->high_thr_voltage *= param1.dy;
|
||||
param->high_thr_voltage = div64_s64(param->high_thr_voltage,
|
||||
param1.adc_vref);
|
||||
param->high_thr_voltage += param1.adc_gnd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qpnp_adc_tm_scale_therm_voltage_pu2);
|
||||
|
||||
int32_t qpnp_adc_usb_scaler(struct qpnp_vadc_chip *chip,
|
||||
struct qpnp_adc_tm_btm_param *param,
|
||||
uint32_t *low_threshold, uint32_t *high_threshold)
|
||||
{
|
||||
struct qpnp_vadc_linear_graph usb_param;
|
||||
|
||||
/* TODO:modify to suit iio functions
|
||||
* qpnp_get_vadc_gain_and_offset(chip, &usb_param, CALIB_RATIOMETRIC);
|
||||
*/
|
||||
|
||||
*low_threshold = param->low_thr * usb_param.dy;
|
||||
*low_threshold = div64_s64(*low_threshold, usb_param.adc_vref);
|
||||
*low_threshold += usb_param.adc_gnd;
|
||||
|
||||
*high_threshold = param->high_thr * usb_param.dy;
|
||||
*high_threshold = div64_s64(*high_threshold, usb_param.adc_vref);
|
||||
*high_threshold += usb_param.adc_gnd;
|
||||
|
||||
pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
|
||||
param->low_thr);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qpnp_adc_usb_scaler);
|
||||
|
||||
int32_t qpnp_adc_absolute_rthr(struct qpnp_vadc_chip *chip,
|
||||
struct qpnp_adc_tm_btm_param *param,
|
||||
uint32_t *low_threshold, uint32_t *high_threshold)
|
||||
{
|
||||
struct qpnp_vadc_linear_graph vbatt_param;
|
||||
int rc = 0, sign = 0;
|
||||
int64_t low_thr = 0, high_thr = 0;
|
||||
|
||||
/* TODO:modify to suit iio functions
|
||||
* rc = qpnp_get_vadc_gain_and_offset(chip, &vbatt_param,
|
||||
* CALIB_ABSOLUTE);
|
||||
*/
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
low_thr = (((param->low_thr/param->gain_den) -
|
||||
QPNP_ADC_625_UV) * vbatt_param.dy);
|
||||
if (low_thr < 0) {
|
||||
sign = 1;
|
||||
low_thr = -low_thr;
|
||||
}
|
||||
low_thr = low_thr * param->gain_num;
|
||||
low_thr = div64_s64(low_thr, QPNP_ADC_625_UV);
|
||||
if (sign)
|
||||
low_thr = -low_thr;
|
||||
*low_threshold = low_thr + vbatt_param.adc_gnd;
|
||||
|
||||
sign = 0;
|
||||
high_thr = (((param->high_thr/param->gain_den) -
|
||||
QPNP_ADC_625_UV) * vbatt_param.dy);
|
||||
if (high_thr < 0) {
|
||||
sign = 1;
|
||||
high_thr = -high_thr;
|
||||
}
|
||||
high_thr = high_thr * param->gain_num;
|
||||
high_thr = div64_s64(high_thr, QPNP_ADC_625_UV);
|
||||
if (sign)
|
||||
high_thr = -high_thr;
|
||||
*high_threshold = high_thr + vbatt_param.adc_gnd;
|
||||
|
||||
pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
|
||||
param->low_thr);
|
||||
pr_debug("adc_code_high:%x, adc_code_low:%x\n", *high_threshold,
|
||||
*low_threshold);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qpnp_adc_absolute_rthr);
|
||||
|
||||
int32_t qpnp_adc_vbatt_rscaler(struct qpnp_vadc_chip *chip,
|
||||
struct qpnp_adc_tm_btm_param *param,
|
||||
uint32_t *low_threshold, uint32_t *high_threshold)
|
||||
{
|
||||
return qpnp_adc_absolute_rthr(chip, param, low_threshold,
|
||||
high_threshold);
|
||||
}
|
||||
EXPORT_SYMBOL(qpnp_adc_vbatt_rscaler);
|
||||
|
||||
int32_t qpnp_adc_qrd_215_btm_scaler(struct qpnp_vadc_chip *chip,
|
||||
struct qpnp_adc_tm_btm_param *param,
|
||||
uint32_t *low_threshold, uint32_t *high_threshold)
|
||||
{
|
||||
struct qpnp_vadc_linear_graph btm_param;
|
||||
int64_t low_output = 0, high_output = 0;
|
||||
int rc = 0;
|
||||
|
||||
/* TODO:modify to suit iio function
|
||||
* qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_RATIOMETRIC);
|
||||
*/
|
||||
|
||||
pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
|
||||
param->low_temp);
|
||||
rc = qpnp_adc_map_temp_voltage(
|
||||
adcmap_batt_therm_qrd_215,
|
||||
ARRAY_SIZE(adcmap_batt_therm_qrd_215),
|
||||
(param->low_temp),
|
||||
&low_output);
|
||||
if (rc) {
|
||||
pr_debug("low_temp mapping failed with %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_debug("low_output:%lld\n", low_output);
|
||||
low_output *= btm_param.dy;
|
||||
low_output = div64_s64(low_output, btm_param.adc_vref);
|
||||
low_output += btm_param.adc_gnd;
|
||||
|
||||
rc = qpnp_adc_map_temp_voltage(
|
||||
adcmap_batt_therm_qrd_215,
|
||||
ARRAY_SIZE(adcmap_batt_therm_qrd_215),
|
||||
(param->high_temp),
|
||||
&high_output);
|
||||
if (rc) {
|
||||
pr_debug("high temp mapping failed with %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_debug("high_output:%lld\n", high_output);
|
||||
high_output *= btm_param.dy;
|
||||
high_output = div64_s64(high_output, btm_param.adc_vref);
|
||||
high_output += btm_param.adc_gnd;
|
||||
|
||||
/* btm low temperature correspondes to high voltage threshold */
|
||||
*low_threshold = high_output;
|
||||
/* btm high temperature correspondes to low voltage threshold */
|
||||
*high_threshold = low_output;
|
||||
|
||||
pr_debug("high_volt:%d, low_volt:%d\n", *high_threshold,
|
||||
*low_threshold);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qpnp_adc_qrd_215_btm_scaler);
|
||||
|
||||
int32_t qpnp_adc_smb_btm_rscaler(struct qpnp_vadc_chip *chip,
|
||||
struct qpnp_adc_tm_btm_param *param,
|
||||
uint32_t *low_threshold, uint32_t *high_threshold)
|
||||
{
|
||||
struct qpnp_vadc_linear_graph btm_param;
|
||||
int64_t low_output = 0, high_output = 0;
|
||||
int rc = 0;
|
||||
|
||||
/* TODO:modify as per iio function
|
||||
* qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_RATIOMETRIC);
|
||||
*/
|
||||
|
||||
pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
|
||||
param->low_temp);
|
||||
rc = qpnp_adc_map_voltage_temp(
|
||||
adcmap_smb_batt_therm,
|
||||
ARRAY_SIZE(adcmap_smb_batt_therm),
|
||||
(param->low_temp),
|
||||
&low_output);
|
||||
if (rc) {
|
||||
pr_debug("low_temp mapping failed with %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_debug("low_output:%lld\n", low_output);
|
||||
low_output *= btm_param.dy;
|
||||
low_output = div64_s64(low_output, btm_param.adc_vref);
|
||||
low_output += btm_param.adc_gnd;
|
||||
|
||||
rc = qpnp_adc_map_voltage_temp(
|
||||
adcmap_smb_batt_therm,
|
||||
ARRAY_SIZE(adcmap_smb_batt_therm),
|
||||
(param->high_temp),
|
||||
&high_output);
|
||||
if (rc) {
|
||||
pr_debug("high temp mapping failed with %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_debug("high_output:%lld\n", high_output);
|
||||
high_output *= btm_param.dy;
|
||||
high_output = div64_s64(high_output, btm_param.adc_vref);
|
||||
high_output += btm_param.adc_gnd;
|
||||
|
||||
/* btm low temperature correspondes to high voltage threshold */
|
||||
*low_threshold = high_output;
|
||||
/* btm high temperature correspondes to low voltage threshold */
|
||||
*high_threshold = low_output;
|
||||
|
||||
pr_debug("high_volt:%d, low_volt:%d\n", *high_threshold,
|
||||
*low_threshold);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qpnp_adc_smb_btm_rscaler);
|
||||
|
||||
int qpnp_adc_get_revid_version(struct device *dev)
|
||||
{
|
||||
struct pmic_revid_data *revid_data;
|
||||
struct device_node *revid_dev_node;
|
||||
|
||||
revid_dev_node = of_parse_phandle(dev->of_node,
|
||||
"qcom,pmic-revid", 0);
|
||||
if (!revid_dev_node) {
|
||||
pr_debug("Missing qcom,pmic-revid property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
revid_data = get_revid_data(revid_dev_node);
|
||||
if (IS_ERR(revid_data)) {
|
||||
pr_debug("revid error rc = %ld\n", PTR_ERR(revid_data));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!revid_data)
|
||||
return -EINVAL;
|
||||
|
||||
if ((revid_data->rev1 == PM8941_V3P1_REV1) &&
|
||||
(revid_data->rev2 == PM8941_V3P1_REV2) &&
|
||||
(revid_data->rev3 == PM8941_V3P1_REV3) &&
|
||||
(revid_data->rev4 == PM8941_V3P1_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8941_SUBTYPE))
|
||||
return QPNP_REV_ID_8941_3_1;
|
||||
else if ((revid_data->rev1 == PM8941_V3P0_REV1) &&
|
||||
(revid_data->rev2 == PM8941_V3P0_REV2) &&
|
||||
(revid_data->rev3 == PM8941_V3P0_REV3) &&
|
||||
(revid_data->rev4 == PM8941_V3P0_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8941_SUBTYPE))
|
||||
return QPNP_REV_ID_8941_3_0;
|
||||
else if ((revid_data->rev1 == PM8941_V2P0_REV1) &&
|
||||
(revid_data->rev2 == PM8941_V2P0_REV2) &&
|
||||
(revid_data->rev3 == PM8941_V2P0_REV3) &&
|
||||
(revid_data->rev4 == PM8941_V2P0_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8941_SUBTYPE))
|
||||
return QPNP_REV_ID_8941_2_0;
|
||||
else if ((revid_data->rev1 == PM8226_V2P2_REV1) &&
|
||||
(revid_data->rev2 == PM8226_V2P2_REV2) &&
|
||||
(revid_data->rev3 == PM8226_V2P2_REV3) &&
|
||||
(revid_data->rev4 == PM8226_V2P2_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8226_SUBTYPE))
|
||||
return QPNP_REV_ID_8026_2_2;
|
||||
else if ((revid_data->rev1 == PM8226_V2P1_REV1) &&
|
||||
(revid_data->rev2 == PM8226_V2P1_REV2) &&
|
||||
(revid_data->rev3 == PM8226_V2P1_REV3) &&
|
||||
(revid_data->rev4 == PM8226_V2P1_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8226_SUBTYPE))
|
||||
return QPNP_REV_ID_8026_2_1;
|
||||
else if ((revid_data->rev1 == PM8226_V2P0_REV1) &&
|
||||
(revid_data->rev2 == PM8226_V2P0_REV2) &&
|
||||
(revid_data->rev3 == PM8226_V2P0_REV3) &&
|
||||
(revid_data->rev4 == PM8226_V2P0_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8226_SUBTYPE))
|
||||
return QPNP_REV_ID_8026_2_0;
|
||||
else if ((revid_data->rev1 == PM8226_V1P0_REV1) &&
|
||||
(revid_data->rev2 == PM8226_V1P0_REV2) &&
|
||||
(revid_data->rev3 == PM8226_V1P0_REV3) &&
|
||||
(revid_data->rev4 == PM8226_V1P0_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8226_SUBTYPE))
|
||||
return QPNP_REV_ID_8026_1_0;
|
||||
else if ((revid_data->rev1 == PM8110_V1P0_REV1) &&
|
||||
(revid_data->rev2 == PM8110_V1P0_REV2) &&
|
||||
(revid_data->rev3 == PM8110_V1P0_REV3) &&
|
||||
(revid_data->rev4 == PM8110_V1P0_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8110_SUBTYPE))
|
||||
return QPNP_REV_ID_8110_1_0;
|
||||
else if ((revid_data->rev1 == PM8110_V2P0_REV1) &&
|
||||
(revid_data->rev2 == PM8110_V2P0_REV2) &&
|
||||
(revid_data->rev3 == PM8110_V2P0_REV3) &&
|
||||
(revid_data->rev4 == PM8110_V2P0_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8110_SUBTYPE))
|
||||
return QPNP_REV_ID_8110_2_0;
|
||||
else if ((revid_data->rev1 == PM8916_V1P0_REV1) &&
|
||||
(revid_data->rev2 == PM8916_V1P0_REV2) &&
|
||||
(revid_data->rev3 == PM8916_V1P0_REV3) &&
|
||||
(revid_data->rev4 == PM8916_V1P0_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8916_SUBTYPE))
|
||||
return QPNP_REV_ID_8916_1_0;
|
||||
else if ((revid_data->rev1 == PM8916_V1P1_REV1) &&
|
||||
(revid_data->rev2 == PM8916_V1P1_REV2) &&
|
||||
(revid_data->rev3 == PM8916_V1P1_REV3) &&
|
||||
(revid_data->rev4 == PM8916_V1P1_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8916_SUBTYPE))
|
||||
return QPNP_REV_ID_8916_1_1;
|
||||
else if ((revid_data->rev1 == PM8916_V2P0_REV1) &&
|
||||
(revid_data->rev2 == PM8916_V2P0_REV2) &&
|
||||
(revid_data->rev3 == PM8916_V2P0_REV3) &&
|
||||
(revid_data->rev4 == PM8916_V2P0_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8916_SUBTYPE))
|
||||
return QPNP_REV_ID_8916_2_0;
|
||||
else if ((revid_data->rev1 == PM8909_V1P0_REV1) &&
|
||||
(revid_data->rev2 == PM8909_V1P0_REV2) &&
|
||||
(revid_data->rev3 == PM8909_V1P0_REV3) &&
|
||||
(revid_data->rev4 == PM8909_V1P0_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8909_SUBTYPE))
|
||||
return QPNP_REV_ID_8909_1_0;
|
||||
else if ((revid_data->rev1 == PM8909_V1P1_REV1) &&
|
||||
(revid_data->rev2 == PM8909_V1P1_REV2) &&
|
||||
(revid_data->rev3 == PM8909_V1P1_REV3) &&
|
||||
(revid_data->rev4 == PM8909_V1P1_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8909_SUBTYPE))
|
||||
return QPNP_REV_ID_8909_1_1;
|
||||
else if ((revid_data->rev4 == PM8950_V1P0_REV4) &&
|
||||
(revid_data->pmic_subtype == PM8950_SUBTYPE))
|
||||
return QPNP_REV_ID_PM8950_1_0;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(qpnp_adc_get_revid_version);
|
||||
|
||||
int32_t qpnp_adc_get_devicetree_data(struct platform_device *pdev,
|
||||
struct qpnp_adc_drv *adc_qpnp)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
unsigned int base;
|
||||
struct device_node *child;
|
||||
struct qpnp_adc_amux *adc_channel_list;
|
||||
struct qpnp_adc_properties *adc_prop;
|
||||
struct qpnp_adc_amux_properties *amux_prop;
|
||||
int count_adc_channel_list = 0, decimation = 0, rc = 0, i = 0;
|
||||
|
||||
if (!node)
|
||||
return -EINVAL;
|
||||
|
||||
for_each_child_of_node(node, child)
|
||||
count_adc_channel_list++;
|
||||
|
||||
if (!count_adc_channel_list) {
|
||||
pr_err("No channel listing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
adc_qpnp->pdev = pdev;
|
||||
|
||||
adc_prop = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct qpnp_adc_properties),
|
||||
GFP_KERNEL);
|
||||
if (!adc_prop)
|
||||
return -ENOMEM;
|
||||
|
||||
adc_channel_list = devm_kzalloc(&pdev->dev,
|
||||
((sizeof(struct qpnp_adc_amux)) * count_adc_channel_list),
|
||||
GFP_KERNEL);
|
||||
if (!adc_channel_list)
|
||||
return -ENOMEM;
|
||||
|
||||
amux_prop = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct qpnp_adc_amux_properties) +
|
||||
sizeof(struct qpnp_vadc_chan_properties), GFP_KERNEL);
|
||||
if (!amux_prop) {
|
||||
dev_err(&pdev->dev, "Unable to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
adc_qpnp->adc_channels = adc_channel_list;
|
||||
adc_qpnp->amux_prop = amux_prop;
|
||||
|
||||
for_each_child_of_node(node, child) {
|
||||
int channel_num, scaling = 0, post_scaling = 0;
|
||||
int fast_avg_setup = 0, calib_type = 0, rc, hw_settle_time = 0;
|
||||
const char *channel_name;
|
||||
|
||||
channel_name = of_get_property(child,
|
||||
"label", NULL) ? : child->name;
|
||||
if (!channel_name) {
|
||||
pr_err("Invalid channel name\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(child, "reg", &channel_num);
|
||||
if (rc) {
|
||||
pr_err("Invalid channel num\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(child,
|
||||
"qcom,hw-settle-time", &hw_settle_time);
|
||||
if (rc) {
|
||||
pr_err("Invalid channel hw settle time property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(child,
|
||||
"qcom,pre-div-channel-scaling", &scaling);
|
||||
if (rc) {
|
||||
pr_err("Invalid channel scaling property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(child,
|
||||
"qcom,scale-fn-type", &post_scaling);
|
||||
if (rc) {
|
||||
pr_err("Invalid channel post scaling property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_property_read_bool(child, "qcom,ratiometric"))
|
||||
calib_type = CALIB_RATIOMETRIC;
|
||||
else
|
||||
calib_type = CALIB_ABSOLUTE;
|
||||
|
||||
rc = of_property_read_u32(child,
|
||||
"qcom,decimation", &decimation);
|
||||
if (rc) {
|
||||
pr_err("Invalid decimation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(child,
|
||||
"qcom,fast-avg-setup", &fast_avg_setup);
|
||||
if (rc) {
|
||||
pr_err("Invalid channel fast average setup\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Individual channel properties */
|
||||
adc_channel_list[i].name = (char *)channel_name;
|
||||
adc_channel_list[i].channel_num = channel_num;
|
||||
adc_channel_list[i].adc_decimation = decimation;
|
||||
adc_channel_list[i].fast_avg_setup = fast_avg_setup;
|
||||
|
||||
adc_channel_list[i].chan_path_prescaling = scaling;
|
||||
adc_channel_list[i].adc_scale_fn = post_scaling;
|
||||
adc_channel_list[i].hw_settle_time = hw_settle_time;
|
||||
adc_channel_list[i].calib_type = calib_type;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Get the ADC VDD reference voltage and ADC bit resolution */
|
||||
rc = of_property_read_u32(node, "qcom,adc-vdd-reference",
|
||||
&adc_prop->adc_vdd_reference);
|
||||
if (rc) {
|
||||
pr_err("Invalid adc vdd reference property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
adc_qpnp->adc_prop = adc_prop;
|
||||
|
||||
/* Get the peripheral address */
|
||||
rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
|
||||
if (rc < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Couldn't find reg in node = %s rc = %d\n",
|
||||
pdev->dev.of_node->full_name, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
adc_qpnp->offset = base;
|
||||
|
||||
/* Register the ADC peripheral interrupt */
|
||||
adc_qpnp->adc_irq_eoc = platform_get_irq_byname(pdev,
|
||||
"eoc-int-en-set");
|
||||
if (adc_qpnp->adc_irq_eoc < 0) {
|
||||
pr_err("Invalid irq\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qpnp_adc_get_devicetree_data);
|
2628
drivers/thermal/qpnp-adc-tm.c
Normal file
2628
drivers/thermal/qpnp-adc-tm.c
Normal file
File diff suppressed because it is too large
Load diff
1255
include/linux/qpnp/qpnp-adc.h
Normal file
1255
include/linux/qpnp/qpnp-adc.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue