Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f29868eb authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "iio: adc: Add PMIC VADC channel support" into msm-4.14

parents 947c85b6 78f171bf
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ ADC node:
    Usage: required
    Value type: <string>
    Definition: Should contain "qcom,spmi-adc5" for PMIC5 ADC driver.
		Should contain "qcom,spmi-adc-rev2" for PMIC refresh ADC driver.

- reg:
    Usage: required
@@ -68,8 +69,10 @@ Channel node properties:
    Value type: <u32>
    Definition: This parameter is used to decrease ADC sampling rate.
            Quicker measurements can be made by reducing decimation ratio.
            Combined two step decimation values are 250, 420 and 840.
            For PMIC5 ADC, combined two step decimation values are 250, 420 and 840.
            If property is not found, default value of 840 will be used.
	    For PMIC refresh ADC, supported decimation values are 256, 512, 1024.
	    If property is not found, default value of 1024 will be used.

- qcom,ratiometric:
    Usage: optional
@@ -84,11 +87,18 @@ Channel node properties:
    Usage: optional
    Value type: <u32>
    Definition: Time between AMUX getting configured and the ADC starting
            conversion. Delay = 15us for value 0, 100us * (value) for values 0 < value < 11, and
            conversion.
	    For PMIC5, delay = 15us for value 0,
			100us * (value) for values 0 < value < 11, and
            		2ms * (value - 10) otherwise.
            Valid values are: 15, 100, 200, 300, 400, 500, 600, 700, 800,
            900 us and 1, 2, 4, 6, 8, 10 ms
            If property is not found, channel will use 15us.
	    For PMIC rev2, delay = 100us * (value) for values 0 < value < 11, and
			2ms * (value - 10) otherwise.
            Valid values are: 0, 100, 200, 300, 400, 500, 600, 700, 800,
            900 us and 1, 2, 4, 6, 8, 10 ms
            If property is not found, channel will use 0 us.

- qcom,avg-samples:
    Usage: optional
@@ -117,7 +127,7 @@ Example:
                        reg = <ADC_VPH_PWR>;
                        label = "vph_pwr";
                        qcom,decimation = <840>;
                        qcom,hw-settle-time = <200>;
                        qcom,hw-settle-time = <0>;
                        qcom,avg-samples = <1>;
                        qcom,pre-scaling = <1 3>;
                };
+162 −70
Original line number Diff line number Diff line
@@ -73,18 +73,18 @@

#define ADC_USR_IBAT_DATA1			0x53

#define ADC_USR_DATA_CHECK			0x8000

#define ADC_CHAN_MIN				ADC_USBIN
#define ADC_CHAN_MAX				ADC_LR_MUX3_BUF_PU1_PU2_XO_THERM

/*
 * Conversion time varies between 139uS to 6827uS based on the decimation,
 * clock rate, fast average samples with no measurement in queue.
 * Set the timeout to a max of 100ms.
 */
#define ADC_CONV_TIME_MIN_US			263
#define ADC_CONV_TIME_MAX_US			264
#define ADC_CONV_TIME_RETRY			1600
#define ADC_CONV_TIME_RETRY			400
#define ADC_CONV_TIMEOUT			msecs_to_jiffies(100)

enum adc_cal_method {
	ADC_NO_CAL = 0,
@@ -157,7 +157,8 @@ static const struct vadc_prescale_ratio adc_prescale_ratios[] = {
	{.num =  1, .den = 20},
	{.num =  1, .den =  8},
	{.num = 10, .den = 81},
	{.num =  1, .den = 10}
	{.num =  1, .den = 10},
	{.num =  1, .den = 16}
};

static int adc_read(struct adc_chip *adc, u16 offset, u8 *data, int len)
@@ -185,19 +186,17 @@ static int adc_prescaling_from_dt(u32 num, u32 den)
	return pre;
}

static int adc_hw_settle_time_from_dt(u32 value)
static int adc_hw_settle_time_from_dt(u32 value,
					const unsigned int *hw_settle)
{
	if ((value <= 1000 && value % 100) || (value > 1000 && value % 2000))
		return -EINVAL;
	uint32_t i;

	if (value == 15)
		value = 1;
	else if (value <= 1000)
		value /= 100;
	else
		value = value / 2000 + 10;
	for (i = 0; i < VADC_HW_SETTLE_SAMPLES_MAX; i++) {
		if (value == hw_settle[i])
			return i;
	}

	return value;
	return -EINVAL;
}

static int adc_avg_samples_from_dt(u32 value)
@@ -223,8 +222,10 @@ static int adc_read_current_data(struct adc_chip *adc, u16 *data)

	*data = (rslt_msb << 8) | rslt_lsb;

	if (*data == ADC_USR_DATA_CHECK)
	if (*data == ADC_USR_DATA_CHECK) {
		pr_err("Invalid data:0x%x\n", *data);
		return -EINVAL;
	}

	return ret;
}
@@ -244,8 +245,10 @@ static int adc_read_voltage_data(struct adc_chip *adc, u16 *data)

	*data = (rslt_msb << 8) | rslt_lsb;

	if (*data == ADC_USR_DATA_CHECK)
	if (*data == ADC_USR_DATA_CHECK) {
		pr_err("Invalid data:0x%x\n", *data);
		return -EINVAL;
	}

	return ret;
}
@@ -314,7 +317,7 @@ static int adc_configure(struct adc_chip *adc,
	buf[3] |= prop->hw_settle_time;

	/* Select ADC enable */
	buf[4] |= ADC_USR_EN_CTL1;
	buf[4] |= ADC_USR_EN_CTL1_ADC_EN;

	/* Select CONV request */
	buf[5] |= ADC_USR_CONV_REQ_REQ;
@@ -328,36 +331,42 @@ static int adc_configure(struct adc_chip *adc,
}

static int adc_do_conversion(struct adc_chip *adc,
		struct adc_channel_prop *prop, u16 *data_volt, u16 *data_cur)
			struct adc_channel_prop *prop,
			struct iio_chan_spec const *chan,
			u16 *data_volt, u16 *data_cur)
{
	int ret, timeout;
	unsigned int chan_type;
	int ret;

	mutex_lock(&adc->lock);

	ret = adc_configure(adc, prop);
	if (ret)
	if (ret) {
		pr_err("ADC configure failed with %d\n", ret);
		goto unlock;

	timeout = ADC_CONV_TIME_MIN_US * ADC_CONV_TIME_RETRY;
	}

	if (adc->poll_eoc) {
		ret = adc_poll_wait_eoc(adc);
		if (ret < 0) {
			pr_err("EOC bit not set\n");
			goto unlock;
		}
	} else {
		ret = wait_for_completion_timeout(&adc->complete, timeout);
		ret = wait_for_completion_timeout(&adc->complete,
							ADC_CONV_TIMEOUT);
		if (!ret) {
			ret = -ETIMEDOUT;
			pr_debug("Did not get completion timeout.\n");
			ret = adc_poll_wait_eoc(adc);
			if (ret < 0) {
				pr_err("EOC bit not set\n");
				goto unlock;
			}
		}
	}

	chan_type = adc->iio_chans[prop->channel].type;

	if (chan_type == IIO_VOLTAGE)
	if ((chan->type == IIO_VOLTAGE) || (chan->type == IIO_TEMP))
		ret = adc_read_voltage_data(adc, data_volt);
	else if (chan_type == IIO_CURRENT)
		ret = adc_read_current_data(adc, data_cur);
	else if (chan_type == IIO_POWER) {
	else if (chan->type == IIO_POWER) {
		ret = adc_read_voltage_data(adc, data_volt);
		if (ret)
			goto unlock;
@@ -379,6 +388,19 @@ static irqreturn_t adc_isr(int irq, void *dev_id)
	return IRQ_HANDLED;
}

static int adc_of_xlate(struct iio_dev *indio_dev,
				const struct of_phandle_args *iiospec)
{
	struct adc_chip *adc = iio_priv(indio_dev);
	int i;

	for (i = 0; i < adc->nchannels; i++)
		if (adc->chan_props[i].channel == iiospec->args[0])
			return i;

	return -EINVAL;
}

static int adc_read_raw(struct iio_dev *indio_dev,
			 struct iio_chan_spec const *chan, int *val, int *val2,
			 long mask)
@@ -386,20 +408,18 @@ static int adc_read_raw(struct iio_dev *indio_dev,
	struct adc_chip *adc = iio_priv(indio_dev);
	struct adc_channel_prop *prop;
	u16 adc_code_volt, adc_code_cur;
	unsigned int chan_type;
	int ret;

	prop = &adc->chan_props[chan->address];
	chan_type = adc->iio_chans[prop->channel].type;

	switch (mask) {
	case IIO_CHAN_INFO_PROCESSED:
		ret = adc_do_conversion(adc, prop,
		ret = adc_do_conversion(adc, prop, chan,
				&adc_code_volt, &adc_code_cur);
		if (ret)
			break;

		if (chan_type == IIO_VOLTAGE || chan_type == IIO_POWER)
		if ((chan->type == IIO_VOLTAGE) || (chan->type == IIO_TEMP))
			ret = qcom_vadc_hw_scale(prop->scale_fn_type,
				&adc_prescale_ratios[prop->prescale],
				adc->data,
@@ -407,21 +427,37 @@ static int adc_read_raw(struct iio_dev *indio_dev,
		if (ret)
			break;

		if (chan_type == IIO_CURRENT || chan_type == IIO_POWER)
		if (chan->type == IIO_POWER) {
			ret = qcom_vadc_hw_scale(SCALE_HW_CALIB_DEFAULT,
				&adc_prescale_ratios[VADC_DEF_VBAT_PRESCALING],
				adc->data,
				adc_code_volt, val);
			if (ret)
				break;

			ret = qcom_vadc_hw_scale(prop->scale_fn_type,
				&adc_prescale_ratios[prop->prescale],
				adc->data,
				adc_code_cur, val2);
			if (ret)
				break;
		}

		if (chan->type == IIO_POWER)
			return IIO_VAL_INT_MULTIPLE;
		else
			return IIO_VAL_INT;
	case IIO_CHAN_INFO_RAW:
		ret = adc_do_conversion(adc, prop,
		ret = adc_do_conversion(adc, prop, chan,
				&adc_code_volt, &adc_code_cur);
		if (ret)
			break;

		*val = (int)adc_code_volt;
		*val = (int)adc_code_cur;
		*val2 = (int)adc_code_cur;
		if (chan->type == IIO_POWER)
			return IIO_VAL_INT_MULTIPLE;
		else
			return IIO_VAL_INT;
	default:
		ret = -EINVAL;
@@ -434,6 +470,7 @@ static int adc_read_raw(struct iio_dev *indio_dev,
static const struct iio_info adc_info = {
	.read_raw = adc_read_raw,
	.driver_module = THIS_MODULE,
	.of_xlate = adc_of_xlate,
};

struct adc_channels {
@@ -463,12 +500,12 @@ struct adc_channels {
		  BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),\
		  _pre, _scale)						\

#define ADC_CHAN_CURRENT(_dname, _pre, _scale)				\
	ADC_CHAN(_dname, IIO_CURRENT,					\
#define ADC_CHAN_POWER(_dname, _pre, _scale)				\
	ADC_CHAN(_dname, IIO_POWER,					\
		  BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),\
		  _pre, _scale)						\

static const struct adc_channels adc_chans_pmic5[] = {
static const struct adc_channels adc_chans_pmic5[ADC_MAX_CHANNEL] = {
	[ADC_REF_GND]		= ADC_CHAN_VOLT("ref_gnd", 1,
					SCALE_HW_CALIB_DEFAULT)
	[ADC_1P25VREF]		= ADC_CHAN_VOLT("vref_1p25", 1,
@@ -479,24 +516,60 @@ static const struct adc_channels adc_chans_pmic5[] = {
					SCALE_HW_CALIB_DEFAULT)
	[ADC_DIE_TEMP]		= ADC_CHAN_TEMP("die_temp", 1,
					SCALE_HW_CALIB_PMIC_THERM)
	[ADC_USB_IN_I]		= ADC_CHAN_CURRENT("usb_in_i", 1,
						SCALE_HW_CALIB_CUR)
	[ADC_USB_IN_I]		= ADC_CHAN_VOLT("usb_in_i_uv", 1,
					SCALE_HW_CALIB_DEFAULT)
	[ADC_USB_IN_V_16]	= ADC_CHAN_VOLT("usb_in_v_div_16", 16,
					SCALE_HW_CALIB_DEFAULT)
	[ADC_CHG_TEMP]		= ADC_CHAN_TEMP("chg_temp", 1,
						SCALE_HW_CALIB_DEFAULT)
					SCALE_HW_CALIB_PM5_CHG_TEMP)
	/* Charger prescales SBUx and MID_CHG to fit within 1.8V upper unit */
	[ADC_SBUx]		= ADC_CHAN_VOLT("chg_sbux", 1,
	[ADC_SBUx]		= ADC_CHAN_VOLT("chg_sbux", 3,
					SCALE_HW_CALIB_DEFAULT)
	[ADC_MID_CHG]		= ADC_CHAN_VOLT("chg_mid_chg", 1,
	[ADC_MID_CHG_DIV6]	= ADC_CHAN_VOLT("chg_mid_chg", 6,
					SCALE_HW_CALIB_DEFAULT)
	[ADC_XO_THERM_PU2]	= ADC_CHAN_TEMP("xo_therm", 1,
					SCALE_HW_CALIB_XOTHERM)
	[ADC_AMUX_THM1_PU2]	= ADC_CHAN_TEMP("amux_thm1", 1,
					SCALE_HW_CALIB_THERM_100K_PULLUP)
	[ADC_AMUX_THM2_PU2]	= ADC_CHAN_TEMP("amux_thm2", 1,
					SCALE_HW_CALIB_THERM_100K_PULLUP)
	[ADC_AMUX_THM3_PU2]	= ADC_CHAN_TEMP("amux_thm3", 1,
					SCALE_HW_CALIB_THERM_100K_PULLUP)
	[ADC_INT_EXT_ISENSE_VBAT_VDATA]	= ADC_CHAN_POWER("int_ext_isense", 1,
					SCALE_HW_CALIB_CUR)
	[ADC_EXT_ISENSE_VBAT_VDATA]	= ADC_CHAN_POWER("ext_isense", 1,
					SCALE_HW_CALIB_CUR)
	[ADC_PARALLEL_ISENSE_VBAT_VDATA] = ADC_CHAN_POWER("parallel_isense", 1,
					SCALE_HW_CALIB_CUR)
};

static const struct adc_channels adc_chans_rev2[ADC_MAX_CHANNEL] = {
	[ADC_REF_GND]		= ADC_CHAN_VOLT("ref_gnd", 1,
					SCALE_HW_CALIB_DEFAULT)
	[ADC_1P25VREF]		= ADC_CHAN_VOLT("vref_1p25", 1,
					SCALE_HW_CALIB_DEFAULT)
	[ADC_VPH_PWR]		= ADC_CHAN_VOLT("vph_pwr", 3,
					SCALE_HW_CALIB_DEFAULT)
	[ADC_VBAT_SNS]		= ADC_CHAN_VOLT("vbat_sns", 3,
					SCALE_HW_CALIB_DEFAULT)
	[ADC_VCOIN]		= ADC_CHAN_VOLT("vcoin", 3,
					SCALE_HW_CALIB_DEFAULT)
	[ADC_DIE_TEMP]		= ADC_CHAN_TEMP("die_temp", 1,
					SCALE_HW_CALIB_PMIC_THERM)
	[ADC_AMUX_THM1_PU2]	= ADC_CHAN_TEMP("amux_thm1_pu2", 1,
					SCALE_HW_CALIB_THERM_100K_PULLUP)
	[ADC_AMUX_THM3_PU2]	= ADC_CHAN_TEMP("amux_thm3_pu2", 1,
					SCALE_HW_CALIB_THERM_100K_PULLUP)
	[ADC_AMUX_THM5_PU2]	= ADC_CHAN_TEMP("amux_thm5_pu2", 1,
					SCALE_HW_CALIB_THERM_100K_PULLUP)
	[ADC_XO_THERM_PU2]	= ADC_CHAN_TEMP("xo_therm", 1,
					SCALE_HW_CALIB_THERM_100K_PULLUP)
};

static int adc_get_dt_channel_data(struct device *dev,
				    struct adc_channel_prop *prop,
				    struct device_node *node)
				    struct device_node *node,
				    const struct adc_data *data)
{
	const char *name = node->name, *channel_name;
	u32 chan, value, varr[2];
@@ -508,7 +581,7 @@ static int adc_get_dt_channel_data(struct device *dev,
		return ret;
	}

	if (chan > ADC_REF_GND || chan < ADC_PARALLEL_ISENSE_VBAT_IDATA) {
	if (chan > ADC_PARALLEL_ISENSE_VBAT_IDATA) {
		dev_err(dev, "%s invalid channel number %d\n", name, chan);
		return -EINVAL;
	}
@@ -526,7 +599,7 @@ static int adc_get_dt_channel_data(struct device *dev,

	ret = of_property_read_u32(node, "qcom,decimation", &value);
	if (!ret) {
		ret = qcom_adc5_decimation_from_dt(value);
		ret = qcom_adc5_decimation_from_dt(value, data->decimation);
		if (ret < 0) {
			dev_err(dev, "%02x invalid decimation %d\n",
				chan, value);
@@ -534,7 +607,7 @@ static int adc_get_dt_channel_data(struct device *dev,
		}
		prop->decimation = ret;
	} else {
		prop->decimation = ADC5_DECIMATION_LONG;
		prop->decimation = ADC_DECIMATION_DEFAULT;
	}

	ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2);
@@ -550,7 +623,7 @@ static int adc_get_dt_channel_data(struct device *dev,

	ret = of_property_read_u32(node, "qcom,hw-settle-time", &value);
	if (!ret) {
		ret = adc_hw_settle_time_from_dt(value);
		ret = adc_hw_settle_time_from_dt(value, data->hw_settle);
		if (ret < 0) {
			dev_err(dev, "%02x invalid hw-settle-time %d us\n",
				chan, value);
@@ -585,9 +658,22 @@ static int adc_get_dt_channel_data(struct device *dev,
}

const struct adc_data data_pmic5 = {
	.full_scale_code_volt = 0x7085,
	.full_scale_code_cur = 0x1800,
	.full_scale_code_volt = 0x70e4,
	/* On PM855B, IBAT LSB = 10A/32767 */
	.full_scale_code_cur = 10000,
	.adc_chans = adc_chans_pmic5,
	.decimation = (unsigned int []) {250, 420, 840},
	.hw_settle = (unsigned int []) {15, 100, 200, 300, 400, 500, 600, 700,
					800, 900, 1, 2, 4, 6, 8, 10},
};

const struct adc_data data_pmic_rev2 = {
	.full_scale_code_volt = 0x4000,
	.full_scale_code_cur = 0x1800,
	.adc_chans = adc_chans_rev2,
	.decimation = (unsigned int []) {256, 512, 1024},
	.hw_settle = (unsigned int []) {0, 100, 200, 300, 400, 500, 600, 700,
					800, 900, 1, 2, 4, 6, 8, 10},
};

static const struct of_device_id adc_match_table[] = {
@@ -595,6 +681,10 @@ static const struct of_device_id adc_match_table[] = {
		.compatible = "qcom,spmi-adc5",
		.data = &data_pmic5,
	},
	{
		.compatible = "qcom,spmi-adc-rev2",
		.data = &data_pmic_rev2,
	},
	{ }
};

@@ -632,7 +722,7 @@ static int adc_get_dt_data(struct adc_chip *adc, struct device_node *node)
	adc->data = data;

	for_each_available_child_of_node(node, child) {
		ret = adc_get_dt_channel_data(adc->dev, &prop, child);
		ret = adc_get_dt_channel_data(adc->dev, &prop, child, data);
		if (ret) {
			of_node_put(child);
			return ret;
@@ -646,12 +736,12 @@ static int adc_get_dt_data(struct adc_chip *adc, struct device_node *node)

		iio_chan->channel = prop.channel;
		iio_chan->datasheet_name = prop.datasheet_name;
		iio_chan->extend_name = prop.datasheet_name;
		iio_chan->info_mask_separate = adc_chan->info_mask;
		iio_chan->type = adc_chan->type;
		iio_chan->indexed = 1;
		iio_chan->address = index++;

		iio_chan->address = index;
		iio_chan++;
		index++;
	}

	return 0;
@@ -687,8 +777,10 @@ static int adc_probe(struct platform_device *pdev)
	mutex_init(&adc->lock);

	ret = adc_get_dt_data(adc, node);
	if (ret)
	if (ret) {
		pr_err("adc get dt data failed\n");
		return ret;
	}

	irq_eoc = platform_get_irq(pdev, 0);
	if (irq_eoc < 0) {
+32 −36
Original line number Diff line number Diff line
@@ -273,7 +273,6 @@ static int qcom_vadc_scale_hw_calib_therm(
	if (ret)
		return ret;

	result *= 1000;
	*result_mdec = result;

	return 0;
@@ -307,12 +306,13 @@ static int qcom_vadc_scale_hw_calib_die_temp(
	return 0;
}

static int qcom_vadc_scale_hw_chg_temp(
static int qcom_vadc_scale_hw_chg5_temp(
				const struct vadc_prescale_ratio *prescale,
				const struct adc_data *data,
				u16 adc_code, int *result_mdec)
{
	s64 voltage = 0, result = 0, adc_vdd_ref_mv = 1875;
	s64 voltage = 0, adc_vdd_ref_mv = 1875;
	u64 temp;

	if (adc_code > VADC5_MAX_CODE)
		adc_code = 0;
@@ -320,41 +320,41 @@ static int qcom_vadc_scale_hw_chg_temp(
	/* (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);
	voltage = voltage * prescale->den;
	voltage = div64_s64(voltage, prescale->num);
	voltage = ((PMI_CHG_SCALE_1) * (voltage * 2));
	voltage = (voltage + PMI_CHG_SCALE_2);
	result =  div64_s64(voltage, 1000000);
	*result_mdec = result;
	if (voltage > 0) {
		temp = voltage * prescale->den;
		do_div(temp, prescale->num * 4);
		voltage = temp;
	} else {
		voltage = 0;
	}

	voltage = PMIC5_CHG_TEMP_SCALE_FACTOR - voltage;
	*result_mdec = voltage;

	return 0;
}

static int qcom_adc_scale_hw_calib_cur(
				const struct vadc_prescale_ratio *prescale,
				const struct adc_data *data,
				u16 adc_code, int *result_mamps)
				u16 adc_code, int *result_uamps)
{
	s64 voltage = 0, result = 0, adc_vdd_ref_mv = 1875;

	if (adc_code > VADC5_MAX_CODE)
		adc_code = 0;
	s64 voltage = 0, result = 0;

	if ((adc_code & 0x80) < 0x80) {
		/* (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_cur);
	if ((adc_code & ADC_USR_DATA_CHECK) == 0) {
		voltage = (s64) adc_code * data->full_scale_code_cur * 1000;
		voltage = div64_s64(voltage, VADC5_MAX_CODE);
		voltage = voltage * prescale->den;
		result = div64_s64(voltage, prescale->num);
		*result_mamps = result;
		*result_uamps = result;
	} else {
		adc_code = ~adc_code + 1;
		voltage = (s64) adc_code;
		voltage = ~voltage + 1;
		/* (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_cur);
		voltage = (s64) adc_code * data->full_scale_code_cur * 1000;
		voltage = div64_s64(voltage, VADC5_MAX_CODE);
		voltage = voltage * prescale->den;
		result = div64_s64(voltage, prescale->num);
		*result_mamps = -result;
		*result_uamps = -result;
	}

	return 0;
@@ -409,8 +409,8 @@ int qcom_vadc_hw_scale(enum vadc_scale_fn_type scaletype,
	case SCALE_HW_CALIB_CUR:
		return qcom_adc_scale_hw_calib_cur(prescale, data,
						adc_code, result);
	case SCALE_HW_CALIB_PMI_CHG_TEMP:
		return qcom_vadc_scale_hw_chg_temp(prescale, data,
	case SCALE_HW_CALIB_PM5_CHG_TEMP:
		return qcom_vadc_scale_hw_chg5_temp(prescale, data,
						adc_code, result);
	default:
		return -EINVAL;
@@ -428,18 +428,14 @@ int qcom_vadc_decimation_from_dt(u32 value)
}
EXPORT_SYMBOL(qcom_vadc_decimation_from_dt);

int qcom_adc5_decimation_from_dt(u32 value)
int qcom_adc5_decimation_from_dt(u32 value, const unsigned int *decimation)
{
	if (value != ADC5_DECIMATION_SHORT || value != ADC5_DECIMATION_MEDIUM
			|| value != ADC5_DECIMATION_LONG)
		return -EINVAL;
	uint32_t i;

	if (value == ADC5_DECIMATION_SHORT)
		return 0;
	else if (value == ADC5_DECIMATION_MEDIUM)
		return 1;
	else if (value == ADC5_DECIMATION_LONG)
		return 2;
	for (i = 0; i < ADC_DECIMATION_SAMPLES_MAX; i++) {
		if (value == decimation[i])
			return i;
	}

	return -EINVAL;
}
+22 −2
Original line number Diff line number Diff line
@@ -22,24 +22,31 @@
#define VADC_DEF_HW_SETTLE_TIME			0 /* 0 us */
#define VADC_DEF_AVG_SAMPLES			0 /* 1 sample */
#define VADC_DEF_CALIB_TYPE			VADC_CALIB_ABSOLUTE
#define VADC_DEF_VBAT_PRESCALING		1 /* 1:3 */

#define VADC_DECIMATION_MIN			512
#define VADC_DECIMATION_MAX			4096
#define ADC5_DECIMATION_SHORT			250
#define ADC5_DECIMATION_MEDIUM			420
#define ADC5_DECIMATION_LONG			840
/* Default decimation - 1024 for rev2, 840 for pmic5 */
#define ADC_DECIMATION_DEFAULT			2
#define ADC_DECIMATION_SAMPLES_MAX		3

#define VADC_HW_SETTLE_DELAY_MAX		10000
#define VADC_HW_SETTLE_SAMPLES_MAX		16
#define VADC_AVG_SAMPLES_MAX			512
#define ADC5_AVG_SAMPLES_MAX			16

#define KELVINMIL_CELSIUSMIL			273150
#define PMIC5_CHG_TEMP_SCALE_FACTOR		377500

#define PMI_CHG_SCALE_1				-138890
#define PMI_CHG_SCALE_2				391750000000LL

#define VADC5_MAX_CODE				0x7fff
#define VADC5_FULL_SCALE_CODE			0x70e4
#define ADC_USR_DATA_CHECK			0x8000

/**
 * struct vadc_map_pt - Map the graph representation for ADC channel
@@ -96,6 +103,17 @@ struct vadc_prescale_ratio {
 * SCALE_PMIC_THERM: Returns result in milli degree's Centigrade.
 * SCALE_XOTHERM: Returns XO thermistor voltage in millidegC.
 * SCALE_PMI_CHG_TEMP: Conversion for PMI CHG temp
 * SCALE_HW_CALIB_DEFAULT: Default scaling to convert raw adc code to
 *	voltage (uV) with hardware applied offset/slope values to adc code.
 * SCALE_HW_CALIB_THERM_100K_PULLUP: Returns temperature in millidegC using
 *	lookup table. The hardware applies offset/slope to adc code.
 * SCALE_HW_CALIB_XOTHERM: Returns XO thermistor voltage in millidegC using
 *	100k pullup. 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_CUR: Returns result in uA for PMIC5.
 * SCALE_HW_CALIB_PM5_CHG_TEMP: Returns result in millidegrees for PMIC5
 *	charger temperature.
 */
enum vadc_scale_fn_type {
	SCALE_DEFAULT = 0,
@@ -108,13 +126,15 @@ enum vadc_scale_fn_type {
	SCALE_HW_CALIB_XOTHERM,
	SCALE_HW_CALIB_PMIC_THERM,
	SCALE_HW_CALIB_CUR,
	SCALE_HW_CALIB_PMI_CHG_TEMP,
	SCALE_HW_CALIB_PM5_CHG_TEMP,
};

struct adc_data {
	const u32	full_scale_code_volt;
	const u32	full_scale_code_cur;
	const struct adc_channels *adc_chans;
	unsigned int	*decimation;
	unsigned int	*hw_settle;
};

int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
@@ -130,6 +150,6 @@ int qcom_vadc_hw_scale(enum vadc_scale_fn_type scaletype,

int qcom_vadc_decimation_from_dt(u32 value);

int qcom_adc5_decimation_from_dt(u32 value);
int qcom_adc5_decimation_from_dt(u32 value, const unsigned int *decimation);

#endif /* QCOM_VADC_COMMON_H */
+3 −1
Original line number Diff line number Diff line
@@ -145,7 +145,7 @@
#define ADC_GPIO6				0x17
#define ADC_GPIO7				0x18
#define ADC_SBUx				0x99
#define ADC_MID_CHG				0x1e
#define ADC_MID_CHG_DIV6			0x1e
#define ADC_OFF					0xff

/* 30k pull-up1 */
@@ -227,4 +227,6 @@
#define ADC_PARALLEL_ISENSE_VBAT_VDATA		0xb4
#define ADC_PARALLEL_ISENSE_VBAT_IDATA		0xb5

#define ADC_MAX_CHANNEL				0xc0

#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_H */