Merge "iio: qcom-spmi-adc5: add support to read current channels"

This commit is contained in:
qctecmdr 2022-06-04 09:38:56 -07:00 committed by Gerrit - the friendly Code Review server
commit 0a2dfab4a7
4 changed files with 555 additions and 13 deletions

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/bitops.h>
@ -75,9 +75,10 @@
* samples and measurements queued across different VADC peripherals.
* Set the timeout to a max of 100ms.
*/
#define ADC5_CONV_TIME_MIN_US 263
#define ADC5_CONV_TIME_MAX_US 264
#define ADC5_CONV_TIME_RETRY 400
#define ADC5_POLL_DELAY_MIN_US 10000
#define ADC5_POLL_DELAY_MAX_US 10001
#define ADC5_CONV_TIME_RETRY_POLL 40
#define ADC5_CONV_TIME_RETRY 30
#define ADC5_CONV_TIMEOUT msecs_to_jiffies(100)
/* Digital version >= 5.3 supports hw_settle_2 */
@ -87,7 +88,7 @@
/* For PMIC7 */
#define ADC_APP_SID 0x40
#define ADC_APP_SID_MASK GENMASK(3, 0)
#define ADC7_CONV_TIMEOUT msecs_to_jiffies(10)
#define ADC7_CONV_TIMEOUT_MS 501
enum adc5_cal_method {
ADC5_NO_CAL = 0,
@ -195,12 +196,17 @@ static int adc5_read_voltage_data(struct adc5_chip *adc, u16 *data)
return 0;
}
static int adc5_poll_wait_eoc(struct adc5_chip *adc)
static int adc5_poll_wait_eoc(struct adc5_chip *adc, bool poll_only)
{
unsigned int count, retry = ADC5_CONV_TIME_RETRY;
u8 status1;
int ret;
if (poll_only)
retry = ADC5_CONV_TIME_RETRY_POLL;
else
retry = ADC5_CONV_TIME_RETRY;
for (count = 0; count < retry; count++) {
ret = adc5_read(adc, ADC5_USR_STATUS1, &status1,
sizeof(status1));
@ -211,7 +217,7 @@ static int adc5_poll_wait_eoc(struct adc5_chip *adc)
if (status1 == ADC5_USR_STATUS1_EOC)
return 0;
usleep_range(ADC5_CONV_TIME_MIN_US, ADC5_CONV_TIME_MAX_US);
usleep_range(ADC5_POLL_DELAY_MIN_US, ADC5_POLL_DELAY_MAX_US);
}
return -ETIMEDOUT;
@ -327,7 +333,7 @@ static int adc5_do_conversion(struct adc5_chip *adc,
}
if (adc->poll_eoc) {
ret = adc5_poll_wait_eoc(adc);
ret = adc5_poll_wait_eoc(adc, true);
if (ret) {
dev_err(adc->dev, "EOC bit not set\n");
goto unlock;
@ -337,7 +343,7 @@ static int adc5_do_conversion(struct adc5_chip *adc,
ADC5_CONV_TIMEOUT);
if (!ret) {
dev_dbg(adc->dev, "Did not get completion timeout.\n");
ret = adc5_poll_wait_eoc(adc);
ret = adc5_poll_wait_eoc(adc, false);
if (ret) {
dev_err(adc->dev, "EOC bit not set\n");
goto unlock;
@ -359,6 +365,8 @@ static int adc7_do_conversion(struct adc5_chip *adc,
{
int ret;
u8 status;
unsigned long rc;
unsigned int time_pending_ms;
mutex_lock(&adc->lock);
@ -369,14 +377,44 @@ static int adc7_do_conversion(struct adc5_chip *adc,
}
/* No support for polling mode at present */
wait_for_completion_timeout(&adc->complete, ADC7_CONV_TIMEOUT);
rc = wait_for_completion_timeout(&adc->complete,
msecs_to_jiffies(ADC7_CONV_TIMEOUT_MS));
if (!rc) {
dev_err(adc->dev, "Reading ADC channel %s timed out\n",
prop->datasheet_name);
ret = -ETIMEDOUT;
goto unlock;
}
/*
* As per the hardware documentation, EOC should happen within 15 ms
* in a good case where there could be multiple conversion requests
* going through PMIC HW arbiter for reading ADC channels. However, if
* for some reason, one of the conversion request fails and times out,
* worst possible delay can be 500 ms. Hence print a warning when we
* see EOC completion happened more than 15 ms.
*/
time_pending_ms = jiffies_to_msecs(rc);
if (time_pending_ms < ADC7_CONV_TIMEOUT_MS &&
(ADC7_CONV_TIMEOUT_MS - time_pending_ms) > 15)
dev_warn(adc->dev, "ADC channel %s EOC took %u ms\n",
prop->datasheet_name,
ADC7_CONV_TIMEOUT_MS - time_pending_ms);
ret = adc5_read(adc, ADC5_USR_STATUS1, &status, 1);
if (ret)
goto unlock;
if (status & ADC5_USR_STATUS1_CONV_FAULT) {
dev_err(adc->dev, "Unexpected conversion fault\n");
dev_err(adc->dev, "ADC channel %s unexpected conversion fault\n",
prop->datasheet_name);
ret = -EIO;
goto unlock;
}
if (!(status & ADC5_USR_STATUS1_EOC)) {
dev_err(adc->dev, "ADC channel %s EOC bit not set, status=%#x\n",
prop->datasheet_name, status);
ret = -EIO;
goto unlock;
}
@ -517,6 +555,11 @@ struct adc5_channels {
BIT(IIO_CHAN_INFO_PROCESSED), \
_pre, _scale) \
#define ADC5_CHAN_CUR(_dname, _pre, _scale) \
ADC5_CHAN(_dname, IIO_CURRENT, \
BIT(IIO_CHAN_INFO_PROCESSED), \
_pre, _scale) \
static const struct adc5_channels adc5_chans_pmic[ADC5_MAX_CHANNEL] = {
[ADC5_REF_GND] = ADC5_CHAN_VOLT("ref_gnd", 0,
SCALE_HW_CALIB_DEFAULT)
@ -541,14 +584,32 @@ static const struct adc5_channels adc5_chans_pmic[ADC5_MAX_CHANNEL] = {
SCALE_HW_CALIB_DEFAULT)
[ADC5_XO_THERM_100K_PU] = ADC5_CHAN_TEMP("xo_therm", 0,
SCALE_HW_CALIB_XOTHERM)
[ADC5_BAT_THERM_100K_PU] = ADC5_CHAN_TEMP("bat_therm_100k_pu", 0,
SCALE_HW_CALIB_BATT_THERM_100K)
[ADC5_BAT_THERM_30K_PU] = ADC5_CHAN_TEMP("bat_therm_30k_pu", 0,
SCALE_HW_CALIB_BATT_THERM_30K)
[ADC5_BAT_THERM_400K_PU] = ADC5_CHAN_TEMP("bat_therm_400k_pu", 0,
SCALE_HW_CALIB_BATT_THERM_400K)
[ADC5_BAT_ID_100K_PU] = ADC5_CHAN_TEMP("bat_id", 0,
SCALE_HW_CALIB_DEFAULT)
[ADC5_AMUX_THM1_100K_PU] = ADC5_CHAN_TEMP("amux_thm1_100k_pu", 0,
SCALE_HW_CALIB_THERM_100K_PULLUP)
[ADC5_AMUX_THM2_100K_PU] = ADC5_CHAN_TEMP("amux_thm2_100k_pu", 0,
SCALE_HW_CALIB_THERM_100K_PULLUP)
[ADC5_AMUX_THM3_100K_PU] = ADC5_CHAN_TEMP("amux_thm3_100k_pu", 0,
SCALE_HW_CALIB_THERM_100K_PULLUP)
[ADC5_AMUX_THM4_100K_PU] = ADC5_CHAN_TEMP("amux_thm4_100k_pu", 0,
SCALE_HW_CALIB_THERM_100K_PULLUP)
[ADC5_AMUX_THM2] = ADC5_CHAN_TEMP("amux_thm2", 0,
SCALE_HW_CALIB_PM5_SMB_TEMP)
[ADC5_GPIO1_100K_PU] = ADC5_CHAN_TEMP("gpio1_100k_pu", 0,
SCALE_HW_CALIB_THERM_100K_PULLUP)
[ADC5_GPIO2_100K_PU] = ADC5_CHAN_TEMP("gpio2_100k_pu", 0,
SCALE_HW_CALIB_THERM_100K_PULLUP)
[ADC5_GPIO3_100K_PU] = ADC5_CHAN_TEMP("gpio3_100k_pu", 0,
SCALE_HW_CALIB_THERM_100K_PULLUP)
[ADC5_GPIO4_100K_PU] = ADC5_CHAN_TEMP("gpio4_100k_pu", 0,
SCALE_HW_CALIB_THERM_100K_PULLUP)
};
static const struct adc5_channels adc7_chans_pmic[ADC5_MAX_CHANNEL] = {
@ -560,6 +621,18 @@ static const struct adc5_channels adc7_chans_pmic[ADC5_MAX_CHANNEL] = {
SCALE_HW_CALIB_DEFAULT)
[ADC7_VBAT_SNS] = ADC5_CHAN_VOLT("vbat_sns", 3,
SCALE_HW_CALIB_DEFAULT)
[ADC7_AMUX_THM3] = ADC5_CHAN_TEMP("smb_temp", 0,
SCALE_HW_CALIB_PM7_SMB_TEMP)
[ADC7_CHG_TEMP] = ADC5_CHAN_TEMP("chg_temp", 0,
SCALE_HW_CALIB_PM7_CHG_TEMP)
[ADC7_IIN_FB] = ADC5_CHAN_CUR("iin_fb", 9,
SCALE_HW_CALIB_CUR)
[ADC7_ICHG_SMB] = ADC5_CHAN_CUR("ichg_smb", 10,
SCALE_HW_CALIB_CUR)
[ADC7_IIN_SMB] = ADC5_CHAN_CUR("iin_smb", 11,
SCALE_HW_CALIB_CUR)
[ADC7_ICHG_FB] = ADC5_CHAN_CUR("ichg_fb", 12,
SCALE_HW_CALIB_CUR_RAW)
[ADC7_DIE_TEMP] = ADC5_CHAN_TEMP("die_temp", 0,
SCALE_HW_CALIB_PMIC_THERM_PM7)
[ADC7_AMUX_THM1_100K_PU] = ADC5_CHAN_TEMP("amux_thm1_pu2", 0,

View File

@ -100,6 +100,237 @@ static const struct vadc_map_pt adcmap_100k_104ef_104fb_1875_vref[] = {
{ 46, 125000 },
};
/*
* Voltage to temperature table for 100k pull up for bat_therm with
* Alium.
*/
static const struct vadc_map_pt adcmap_batt_therm_100k[] = {
{1840, -400},
{1835, -380},
{1828, -360},
{1821, -340},
{1813, -320},
{1803, -300},
{1793, -280},
{1781, -260},
{1768, -240},
{1753, -220},
{1737, -200},
{1719, -180},
{1700, -160},
{1679, -140},
{1655, -120},
{1630, -100},
{1603, -80},
{1574, -60},
{1543, -40},
{1510, -20},
{1475, 0},
{1438, 20},
{1400, 40},
{1360, 60},
{1318, 80},
{1276, 100},
{1232, 120},
{1187, 140},
{1142, 160},
{1097, 180},
{1051, 200},
{1005, 220},
{960, 240},
{915, 260},
{871, 280},
{828, 300},
{786, 320},
{745, 340},
{705, 360},
{666, 380},
{629, 400},
{594, 420},
{560, 440},
{527, 460},
{497, 480},
{467, 500},
{439, 520},
{413, 540},
{388, 560},
{365, 580},
{343, 600},
{322, 620},
{302, 640},
{284, 660},
{267, 680},
{251, 700},
{235, 720},
{221, 740},
{208, 760},
{195, 780},
{184, 800},
{173, 820},
{163, 840},
{153, 860},
{144, 880},
{136, 900},
{128, 920},
{120, 940},
{114, 960},
{107, 980}
};
/*
* Voltage to temperature table for 30k pull up for bat_therm with
* Alium.
*/
static const struct vadc_map_pt adcmap_batt_therm_30k[] = {
{1864, -400},
{1863, -380},
{1861, -360},
{1858, -340},
{1856, -320},
{1853, -300},
{1850, -280},
{1846, -260},
{1842, -240},
{1837, -220},
{1831, -200},
{1825, -180},
{1819, -160},
{1811, -140},
{1803, -120},
{1794, -100},
{1784, -80},
{1773, -60},
{1761, -40},
{1748, -20},
{1734, 0},
{1718, 20},
{1702, 40},
{1684, 60},
{1664, 80},
{1643, 100},
{1621, 120},
{1597, 140},
{1572, 160},
{1546, 180},
{1518, 200},
{1489, 220},
{1458, 240},
{1426, 260},
{1393, 280},
{1359, 300},
{1324, 320},
{1288, 340},
{1252, 360},
{1214, 380},
{1176, 400},
{1138, 420},
{1100, 440},
{1061, 460},
{1023, 480},
{985, 500},
{947, 520},
{910, 540},
{873, 560},
{836, 580},
{801, 600},
{766, 620},
{732, 640},
{699, 660},
{668, 680},
{637, 700},
{607, 720},
{578, 740},
{550, 760},
{524, 780},
{498, 800},
{474, 820},
{451, 840},
{428, 860},
{407, 880},
{387, 900},
{367, 920},
{349, 940},
{332, 960},
{315, 980}
};
/*
* Voltage to temperature table for 400k pull up for bat_therm with
* Alium.
*/
static const struct vadc_map_pt adcmap_batt_therm_400k[] = {
{1744, -400},
{1724, -380},
{1701, -360},
{1676, -340},
{1648, -320},
{1618, -300},
{1584, -280},
{1548, -260},
{1509, -240},
{1468, -220},
{1423, -200},
{1377, -180},
{1328, -160},
{1277, -140},
{1225, -120},
{1171, -100},
{1117, -80},
{1062, -60},
{1007, -40},
{953, -20},
{899, 0},
{847, 20},
{795, 40},
{745, 60},
{697, 80},
{651, 100},
{607, 120},
{565, 140},
{526, 160},
{488, 180},
{453, 200},
{420, 220},
{390, 240},
{361, 260},
{334, 280},
{309, 300},
{286, 320},
{265, 340},
{245, 360},
{227, 380},
{210, 400},
{195, 420},
{180, 440},
{167, 460},
{155, 480},
{144, 500},
{133, 520},
{124, 540},
{115, 560},
{107, 580},
{99, 600},
{92, 620},
{86, 640},
{80, 660},
{75, 680},
{70, 700},
{65, 720},
{61, 740},
{57, 760},
{53, 780},
{50, 800},
{46, 820},
{43, 840},
{41, 860},
{38, 880},
{36, 900},
{34, 920},
{32, 940},
{30, 960},
{28, 980}
};
static const struct vadc_map_pt adcmap7_die_temp[] = {
{ 857300, 160000 },
{ 820100, 140000 },
@ -299,16 +530,42 @@ static const struct u32_fract adc5_prescale_ratios[] = {
{ .numerator = 10, .denominator = 81 },
{ .numerator = 1, .denominator = 10 },
{ .numerator = 1, .denominator = 16 },
/* Prescale ratios for current channels below */
{ .numerator = 32, .denominator = 100 }, /* IIN_FB */
{ .numerator = 14, .denominator = 100 }, /* ICHG_SMB */
{ .numerator = 28, .denominator = 100 }, /* IIN_SMB */
{ .numerator = 1000, .denominator = 305185 }, /* ICHG_FB */
{ .numerator = 1000, .denominator = 610370 }, /* ICHG_FB_2X */
};
static int qcom_vadc_scale_hw_calib_volt(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_uv);
static int qcom_vadc_scale_hw_calib_current(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_ua);
static int qcom_vadc_scale_hw_calib_current_raw(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_ua);
static int qcom_vadc_scale_hw_calib_therm(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec);
static int qcom_vadc_scale_hw_calib_batt_therm_100(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec);
static int qcom_vadc_scale_hw_calib_batt_therm_30(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec);
static int qcom_vadc_scale_hw_calib_batt_therm_400(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec);
static int qcom_vadc7_scale_hw_calib_therm(
const struct u32_fract *prescale,
const struct adc5_data *data,
@ -317,10 +574,22 @@ static int qcom_vadc_scale_hw_smb_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec);
static int qcom_vadc_scale_hw_pm7_smb_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec);
static int qcom_vadc_scale_hw_smb1398_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec);
static int qcom_vadc_scale_hw_chg5_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec);
static int qcom_vadc_scale_hw_pm7_chg_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec);
static int qcom_vadc_scale_hw_calib_die_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
@ -332,7 +601,15 @@ static int qcom_vadc7_scale_hw_calib_die_temp(
static struct qcom_adc5_scale_type scale_adc5_fn[] = {
[SCALE_HW_CALIB_DEFAULT] = {qcom_vadc_scale_hw_calib_volt},
[SCALE_HW_CALIB_CUR] = {qcom_vadc_scale_hw_calib_current},
[SCALE_HW_CALIB_CUR_RAW] = {qcom_vadc_scale_hw_calib_current_raw},
[SCALE_HW_CALIB_THERM_100K_PULLUP] = {qcom_vadc_scale_hw_calib_therm},
[SCALE_HW_CALIB_BATT_THERM_100K] = {
qcom_vadc_scale_hw_calib_batt_therm_100},
[SCALE_HW_CALIB_BATT_THERM_30K] = {
qcom_vadc_scale_hw_calib_batt_therm_30},
[SCALE_HW_CALIB_BATT_THERM_400K] = {
qcom_vadc_scale_hw_calib_batt_therm_400},
[SCALE_HW_CALIB_XOTHERM] = {qcom_vadc_scale_hw_calib_therm},
[SCALE_HW_CALIB_THERM_100K_PU_PM7] = {
qcom_vadc7_scale_hw_calib_therm},
@ -341,6 +618,9 @@ static struct qcom_adc5_scale_type scale_adc5_fn[] = {
qcom_vadc7_scale_hw_calib_die_temp},
[SCALE_HW_CALIB_PM5_CHG_TEMP] = {qcom_vadc_scale_hw_chg5_temp},
[SCALE_HW_CALIB_PM5_SMB_TEMP] = {qcom_vadc_scale_hw_smb_temp},
[SCALE_HW_CALIB_PM5_SMB1398_TEMP] = {qcom_vadc_scale_hw_smb1398_temp},
[SCALE_HW_CALIB_PM7_SMB_TEMP] = {qcom_vadc_scale_hw_pm7_smb_temp},
[SCALE_HW_CALIB_PM7_CHG_TEMP] = {qcom_vadc_scale_hw_pm7_chg_temp},
};
static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts,
@ -556,6 +836,45 @@ static int qcom_vadc7_scale_hw_calib_therm(
return 0;
}
static int qcom_vadc_scale_hw_calib_current_raw(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_ua)
{
s64 temp;
if (!prescale->numerator)
return -EINVAL;
temp = div_s64((s64)(s16)adc_code * prescale->denominator,
prescale->numerator);
*result_ua = (int) temp;
pr_debug("raw adc_code: %#x result_ua: %d\n", adc_code, *result_ua);
return 0;
}
static int qcom_vadc_scale_hw_calib_current(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_ua)
{
u32 adc_vdd_ref_mv = 1875;
s64 voltage;
if (!prescale->numerator)
return -EINVAL;
/* (ADC code * vref_vadc (1.875V)) / full_scale_code */
voltage = (s64)(s16) adc_code * adc_vdd_ref_mv * 1000;
voltage = div_s64(voltage, data->full_scale_code_volt);
voltage = div_s64(voltage * prescale->denominator, prescale->numerator);
*result_ua = (int) voltage;
pr_debug("adc_code: %#x result_ua: %d\n", adc_code, *result_ua);
return 0;
}
static int qcom_vadc_scale_hw_calib_volt(
const struct u32_fract *prescale,
const struct adc5_data *data,
@ -583,6 +902,54 @@ static int qcom_vadc_scale_hw_calib_therm(
voltage, result_mdec);
}
static int qcom_vadc_scale_hw_calib_batt_therm_100(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec)
{
int voltage;
voltage = qcom_vadc_scale_code_voltage_factor(adc_code,
prescale, data, 1000);
/* Map voltage to temperature from look-up table */
return qcom_vadc_map_voltage_temp(adcmap_batt_therm_100k,
ARRAY_SIZE(adcmap_batt_therm_100k),
voltage, result_mdec);
}
static int qcom_vadc_scale_hw_calib_batt_therm_30(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec)
{
int voltage;
voltage = qcom_vadc_scale_code_voltage_factor(adc_code,
prescale, data, 1000);
/* Map voltage to temperature from look-up table */
return qcom_vadc_map_voltage_temp(adcmap_batt_therm_30k,
ARRAY_SIZE(adcmap_batt_therm_30k),
voltage, result_mdec);
}
static int qcom_vadc_scale_hw_calib_batt_therm_400(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec)
{
int voltage;
voltage = qcom_vadc_scale_code_voltage_factor(adc_code,
prescale, data, 1000);
/* Map voltage to temperature from look-up table */
return qcom_vadc_map_voltage_temp(adcmap_batt_therm_400k,
ARRAY_SIZE(adcmap_batt_therm_400k),
voltage, result_mdec);
}
static int qcom_vadc_scale_hw_calib_die_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
@ -610,6 +977,47 @@ static int qcom_vadc7_scale_hw_calib_die_temp(
voltage, result_mdec);
}
static int qcom_vadc_scale_hw_pm7_chg_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec)
{
s64 temp;
int result_uv;
result_uv = qcom_vadc_scale_code_voltage_factor(adc_code,
prescale, data, 1);
/* T(C) = Vadc/0.0033 277.12 */
temp = div_s64((30303LL * result_uv) - (27712 * 1000000LL), 100000);
pr_debug("adc_code: %u result_uv: %d temp: %lld\n", adc_code, result_uv,
temp);
*result_mdec = temp > 0 ? temp : 0;
return 0;
}
static int qcom_vadc_scale_hw_pm7_smb_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec)
{
s64 temp;
int result_uv;
result_uv = qcom_vadc_scale_code_voltage_factor(adc_code,
prescale, data, 1);
/* T(C) = 25 + (25*Vadc - 24.885) / 0.0894 */
temp = div_s64(((25000LL * result_uv) - (24885 * 1000000LL)) * 10000,
894 * 1000000) + 25000;
pr_debug("adc_code: %#x result_uv: %d temp: %lld\n", adc_code,
result_uv, temp);
*result_mdec = temp > 0 ? temp : 0;
return 0;
}
static int qcom_vadc_scale_hw_smb_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
@ -622,6 +1030,35 @@ static int qcom_vadc_scale_hw_smb_temp(
return 0;
}
static int qcom_vadc_scale_hw_smb1398_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,
u16 adc_code, int *result_mdec)
{
s64 voltage = 0, adc_vdd_ref_mv = 1875;
u64 temp;
if (adc_code > VADC5_MAX_CODE)
adc_code = 0;
/* (ADC code * vref_vadc (1.875V)) / full_scale_code */
voltage = (s64) adc_code * adc_vdd_ref_mv * 1000;
voltage = div64_s64(voltage, data->full_scale_code_volt);
if (voltage > 0) {
temp = voltage * prescale->denominator;
temp *= 100;
do_div(temp, prescale->numerator * PMIC5_SMB1398_TEMP_SCALE_FACTOR);
voltage = temp;
} else {
voltage = 0;
}
voltage = voltage - PMIC5_SMB1398_TEMP_CONSTANT;
*result_mdec = voltage;
return 0;
}
static int qcom_vadc_scale_hw_chg5_temp(
const struct u32_fract *prescale,
const struct adc5_data *data,

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2012-2014,2018,2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2014,2018-2020 The Linux Foundation. All rights reserved.
*/
#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_H
@ -245,6 +245,9 @@
#define ADC7_CC1_ID 0x13
#define ADC7_VREF_BAT_THERM 0x15
#define ADC7_IIN_FB 0x17
#define ADC7_ICHG_SMB 0x18
#define ADC7_IIN_SMB 0x19
#define ADC7_ICHG_FB 0xa1
/* 30k pull-up1 */
#define ADC7_AMUX_THM1_30K_PU 0x24

View File

@ -44,6 +44,8 @@
#define PMIC5_CHG_TEMP_SCALE_FACTOR 377500
#define PMIC5_SMB_TEMP_CONSTANT 419400
#define PMIC5_SMB_TEMP_SCALE_FACTOR 356
#define PMIC5_SMB1398_TEMP_CONSTANT 268235
#define PMIC5_SMB1398_TEMP_SCALE_FACTOR 340
#define PMI_CHG_SCALE_1 -138890
#define PMI_CHG_SCALE_2 391750000000LL
@ -99,12 +101,31 @@ struct vadc_linear_graph {
* lookup table for PMIC7. The hardware applies offset/slope to adc code.
* SCALE_HW_CALIB_PMIC_THERM: Returns result in milli degree's Centigrade.
* The hardware applies offset/slope to adc code.
* SCALE_HW_CALIB_PMIC_THERM: Returns result in milli degree's Centigrade.
* SCALE_HW_CALIB_PMIC_THERM_PM7: Returns result in milli degree's Centigrade.
* The hardware applies offset/slope to adc code. This is for PMIC7.
* SCALE_HW_CALIB_PM5_CHG_TEMP: Returns result in millidegrees for PMIC5
* charger temperature.
* SCALE_HW_CALIB_PM5_SMB_TEMP: Returns result in millidegrees for PMIC5
* SMB1390 temperature.
* SCALE_HW_CALIB_BATT_THERM_100K: Returns battery thermistor voltage in
* decidegC using 100k pullup. The hardware applies offset/slope to adc
* code.
* SCALE_HW_CALIB_BATT_THERM_30K: Returns battery thermistor voltage in
* decidegC using 30k pullup. The hardware applies offset/slope to adc
* code.
* SCALE_HW_CALIB_BATT_THERM_400K: Returns battery thermistor voltage in
* decidegC using 400k pullup. The hardware applies offset/slope to adc
* code.
* SCALE_HW_CALIB_PM5_SMB1398_TEMP: Returns result in millidegrees for PMIC5
* SMB1398 temperature.
* SCALE_HW_CALIB_PM7_SMB_TEMP: Returns result in millidegrees for PMIC7
* SMB139x temperature.
* SCALE_HW_CALIB_PM7_CHG_TEMP: Returns result in millidegrees for PMIC7
* charger temperature.
* SCALE_HW_CALIB_CUR: Returns result in microamperes for PMIC7 channels that
* use voltage scaling.
* SCALE_HW_CALIB_CUR_RAW: Returns result in microamperes for PMIC7 channels
* that use raw ADC code.
*/
enum vadc_scale_fn_type {
SCALE_DEFAULT = 0,
@ -120,6 +141,14 @@ enum vadc_scale_fn_type {
SCALE_HW_CALIB_PMIC_THERM_PM7,
SCALE_HW_CALIB_PM5_CHG_TEMP,
SCALE_HW_CALIB_PM5_SMB_TEMP,
SCALE_HW_CALIB_BATT_THERM_100K,
SCALE_HW_CALIB_BATT_THERM_30K,
SCALE_HW_CALIB_BATT_THERM_400K,
SCALE_HW_CALIB_PM5_SMB1398_TEMP,
SCALE_HW_CALIB_PM7_SMB_TEMP,
SCALE_HW_CALIB_PM7_CHG_TEMP,
SCALE_HW_CALIB_CUR,
SCALE_HW_CALIB_CUR_RAW,
SCALE_HW_CALIB_INVALID,
};