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

Add support to read current channels on PM8350B and SMB139x
charge pumps.

IIN_FB - Input current drawn by main charger (PM8350B)
ICHG_FB - Charging current from main charger (PM8350B)
IIN_SMB - Input current drawn by one of SMB139x
ICHG_SMB - Charging current from one of SMB139x

Since, most of these channels needs prescale ratios post reading
ADC code and before scaling, add the necessary prescale ratios.

Change-Id: Id9b866f684d574813904a5fd8e658f59b1d7bcbf
Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
[quic_subbaram@quicinc.com: Fixed merge conflicts in
 qcom-vadc-common.h due to location change and common code moved
 to qcom-vadc-common.c]
Signed-off-by: Subbaraman Narayanamurthy <quic_subbaram@quicinc.com>
[quic_collinsd@quicinc.com: changed struct vadc_prescale_ratio to
 struct u32_fract and changed prescale "num" and "den" to
 "numerator" and "denominator" respectively]
Signed-off-by: David Collins <quic_collinsd@quicinc.com>
This commit is contained in:
Subbaraman Narayanamurthy 2020-09-11 12:55:05 -07:00 committed by David Collins
parent 5a34473338
commit f90d42fefa
3 changed files with 74 additions and 0 deletions

View File

@ -555,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)
@ -620,6 +625,14 @@ static const struct adc5_channels adc7_chans_pmic[ADC5_MAX_CHANNEL] = {
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

@ -530,12 +530,26 @@ 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,
@ -587,6 +601,8 @@ 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},
@ -820,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,

View File

@ -122,6 +122,10 @@ struct vadc_linear_graph {
* 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,
@ -143,6 +147,8 @@ enum vadc_scale_fn_type {
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,
};