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

Commit 81157611 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "thermal: adc-tm: Add support for PMIC7 ADC_TM"

parents ba52c694 bfdf1402
Loading
Loading
Loading
Loading
+233 −3
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "qcom-vadc-common.h"

#define ADC_USR_STATUS1				0x8
#define ADC7_USR_STATUS1_CONV_FAULT		BIT(7)
#define ADC_USR_STATUS1_REQ_STS			BIT(1)
#define ADC_USR_STATUS1_EOC			BIT(0)
#define ADC_USR_STATUS1_REQ_STS_EOC_MASK	0x3
@@ -73,6 +74,9 @@
#define ADC_CHAN_MIN				ADC_USBIN
#define ADC_CHAN_MAX				ADC_LR_MUX3_BUF_PU1_PU2_XO_THERM

#define ADC_CHANNEL_OFFSET			0x8
#define ADC_CHANNEL_MASK			0xff

/*
 * Conversion time varies between 139uS to 6827uS based on the decimation,
 * clock rate, fast average samples with no measurement in queue.
@@ -89,6 +93,11 @@
#define ADC_CAL_DELAY_CTL_VAL_256S		0x73
#define ADC_CAL_DELAY_CTL_VAL_125MS		0x3

/* For PMIC7 */
#define ADC_APP_SID					0x40
#define ADC_APP_SID_MASK			0xf
#define ADC7_CONV_TIMEOUT		msecs_to_jiffies(10)

enum adc_cal_method {
	ADC_NO_CAL = 0,
	ADC_RATIOMETRIC_CAL,
@@ -111,6 +120,7 @@ struct pmic_rev_data {
 * @cal_method: calibration method.
 * @cal_val: calibration value
 * @decimation: sampling rate supported for the channel.
 * @sid: slave id of PMIC owning the channel, for PMIC7.
 * @prescale: channel scaling performed on the input signal.
 * @hw_settle_time: the time between AMUX being configured and the
 *	start of conversion.
@@ -124,6 +134,7 @@ struct adc_channel_prop {
	enum adc_cal_method		cal_method;
	enum adc_cal_val		cal_val;
	unsigned int			decimation;
	unsigned int			sid;
	unsigned int			prescale;
	unsigned int			hw_settle_time;
	unsigned int			avg_samples;
@@ -161,6 +172,7 @@ struct adc_chip {
	bool			skip_usb_wa;
	void			*ipc_log0;
	void			*ipc_log1;
	bool			is_pmic7;
	struct pmic_revid_data	*pmic_rev_id;
	const struct adc_data	*data;
};
@@ -187,6 +199,11 @@ static int adc_write(struct adc_chip *adc, u16 offset, u8 *data, int len)
	return regmap_bulk_write(adc->regmap, adc->base + offset, data, len);
}

static int adc_masked_write(struct adc_chip *adc, u16 offset, u8 mask, u8 val)
{
	return regmap_update_bits(adc->regmap, adc->base + offset, mask, val);
}

static int adc_prescaling_from_dt(u32 num, u32 den)
{
	unsigned int pre;
@@ -529,6 +546,49 @@ static int adc_configure(struct adc_chip *adc,
	return ret;
}

static int adc7_configure(struct adc_chip *adc,
			struct adc_channel_prop *prop)
{
	int ret;
	u8 conv_req = 0, buf[4];

	ret = adc_masked_write(adc, ADC_APP_SID, ADC_APP_SID_MASK, prop->sid);
	if (ret)
		return ret;

	ret = adc_read(adc, ADC_USR_DIG_PARAM, buf, sizeof(buf));
	if (ret < 0)
		return ret;

	/* Digital param selection */
	adc_update_dig_param(adc, prop, &buf[0]);

	/* Update fast average sample value */
	buf[1] &= (u8) ~ADC_USR_FAST_AVG_CTL_SAMPLES_MASK;
	buf[1] |= prop->avg_samples;

	/* Select ADC channel */
	buf[2] = prop->channel;

	/* Select HW settle delay for channel */
	buf[3] &= (u8) ~ADC_USR_HW_SETTLE_DELAY_MASK;
	buf[3] |= prop->hw_settle_time;

	/* Select CONV request */
	conv_req = ADC_USR_CONV_REQ_REQ;

	if (!adc->poll_eoc)
		reinit_completion(&adc->complete);

	ret = adc_write(adc, ADC_USR_DIG_PARAM, buf, sizeof(buf));
	if (ret)
		return ret;

	ret = adc_write(adc, ADC_USR_CONV_REQ, &conv_req, 1);

	return ret;
}

static int adc_do_conversion(struct adc_chip *adc,
			struct adc_channel_prop *prop,
			struct iio_chan_spec const *chan,
@@ -579,6 +639,44 @@ static int adc_do_conversion(struct adc_chip *adc,
	return ret;
}

static int adc7_do_conversion(struct adc_chip *adc,
			struct adc_channel_prop *prop,
			struct iio_chan_spec const *chan,
			u16 *data_volt, u16 *data_cur)
{
	int ret;
	u8 status = 0;

	mutex_lock(&adc->lock);

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

	/* No support for polling mode at present*/
	wait_for_completion_timeout(&adc->complete,
					ADC7_CONV_TIMEOUT);

	ret = adc_read(adc, ADC_USR_STATUS1, &status, 1);
	if (ret < 0)
		goto unlock;

	if (status & ADC7_USR_STATUS1_CONV_FAULT) {
		pr_err("Unexpected conversion fault\n");
		ret = -EIO;
		goto unlock;
	}

	ret = adc_read_voltage_data(adc, data_volt);

unlock:
	mutex_unlock(&adc->lock);

	return ret;
}

static irqreturn_t adc_isr(int irq, void *dev_id)
{
	struct adc_chip *adc = dev_id;
@@ -601,6 +699,66 @@ static int adc_of_xlate(struct iio_dev *indio_dev,
	return -EINVAL;
}

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

	for (i = 0; i < adc->nchannels; i++) {
		v_channel = ((adc->chan_props[i].sid << ADC_CHANNEL_OFFSET) |
			adc->chan_props[i].channel);
		if (v_channel == iiospec->args[0])
			return i;
	}

	return -EINVAL;
}

static int adc7_read_raw(struct iio_dev *indio_dev,
			 struct iio_chan_spec const *chan, int *val, int *val2,
			 long mask)
{
	struct adc_chip *adc = iio_priv(indio_dev);
	struct adc_channel_prop *prop;
	u16 adc_code_volt, adc_code_cur;
	int ret;

	prop = &adc->chan_props[chan->address];

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

		ret = qcom_vadc_hw_scale(prop->scale_fn_type,
			&adc_prescale_ratios[prop->prescale],
			adc->data, prop->lut_index,
			adc_code_volt, val);

		if (ret)
			return ret;

		return IIO_VAL_INT;

	case IIO_CHAN_INFO_RAW:
		ret = adc7_do_conversion(adc, prop, chan,
					&adc_code_volt, &adc_code_cur);
		if (ret)
			return ret;

		*val = (int)adc_code_volt;
		return IIO_VAL_INT;

	default:
		return -EINVAL;
	}

	return 0;
}

static int adc_read_raw(struct iio_dev *indio_dev,
			 struct iio_chan_spec const *chan, int *val, int *val2,
			 long mask)
@@ -672,6 +830,11 @@ static const struct iio_info adc_info = {
	.of_xlate = adc_of_xlate,
};

static const struct iio_info adc7_info = {
	.read_raw = adc7_read_raw,
	.of_xlate = adc7_of_xlate,
};

struct adc_channels {
	const char *datasheet_name;
	unsigned int prescale_index;
@@ -770,6 +933,39 @@ static const struct adc_channels adc_chans_pmic5[ADC_MAX_CHANNEL] = {
					SCALE_HW_CALIB_THERM_100K_PULLUP)
};

static const struct adc_channels adc7_chans_pmic[ADC_MAX_CHANNEL] = {
	[ADC7_REF_GND]		= ADC_CHAN_VOLT("ref_gnd", 0,
					SCALE_HW_CALIB_DEFAULT)
	[ADC7_1P25VREF]		= ADC_CHAN_VOLT("vref_1p25", 0,
					SCALE_HW_CALIB_DEFAULT)
	[ADC7_VPH_PWR]		= ADC_CHAN_VOLT("vph_pwr", 1,
					SCALE_HW_CALIB_DEFAULT)
	[ADC7_VBAT_SNS]		= ADC_CHAN_VOLT("vbat_sns", 3,
					SCALE_HW_CALIB_DEFAULT)
	[ADC7_DIE_TEMP]		= ADC_CHAN_TEMP("die_temp", 0,
					SCALE_HW_CALIB_PMIC_THERM_PM7)
	[ADC7_AMUX_THM1_100K_PU]	= ADC_CHAN_TEMP("amux_thm1_pu2", 0,
					SCALE_HW_CALIB_THERM_100K_PU_PM7)
	[ADC7_AMUX_THM2_100K_PU]	= ADC_CHAN_TEMP("amux_thm2_pu2", 0,
					SCALE_HW_CALIB_THERM_100K_PU_PM7)
	[ADC7_AMUX_THM3_100K_PU]	= ADC_CHAN_TEMP("amux_thm3_pu2", 0,
					SCALE_HW_CALIB_THERM_100K_PU_PM7)
	[ADC7_AMUX_THM4_100K_PU]	= ADC_CHAN_TEMP("amux_thm4_pu2", 0,
					SCALE_HW_CALIB_THERM_100K_PU_PM7)
	[ADC7_AMUX_THM5_100K_PU]	= ADC_CHAN_TEMP("amux_thm5_pu2", 0,
					SCALE_HW_CALIB_THERM_100K_PU_PM7)
	[ADC7_AMUX_THM6_100K_PU]	= ADC_CHAN_TEMP("amux_thm6_pu2", 0,
					SCALE_HW_CALIB_THERM_100K_PU_PM7)
	[ADC7_GPIO1_100K_PU]	= ADC_CHAN_TEMP("gpio1_pu2", 0,
					SCALE_HW_CALIB_THERM_100K_PU_PM7)
	[ADC7_GPIO2_100K_PU]	= ADC_CHAN_TEMP("gpio2_pu2", 0,
					SCALE_HW_CALIB_THERM_100K_PU_PM7)
	[ADC7_GPIO3_100K_PU]	= ADC_CHAN_TEMP("gpio3_pu2", 0,
					SCALE_HW_CALIB_THERM_100K_PU_PM7)
	[ADC7_GPIO4_100K_PU]	= ADC_CHAN_TEMP("gpio4_pu2", 0,
					SCALE_HW_CALIB_THERM_100K_PU_PM7)
};

static const struct adc_channels adc_chans_rev2[ADC_MAX_CHANNEL] = {
	[ADC_REF_GND]		= ADC_CHAN_VOLT("ref_gnd", 1,
					SCALE_HW_CALIB_DEFAULT)
@@ -793,14 +989,16 @@ static const struct adc_channels adc_chans_rev2[ADC_MAX_CHANNEL] = {
					SCALE_HW_CALIB_THERM_100K_PULLUP)
};

static int adc_get_dt_channel_data(struct device *dev,
static int adc_get_dt_channel_data(struct adc_chip *adc,
				    struct adc_channel_prop *prop,
				    struct device_node *node,
				    const struct adc_data *data)
{
	const char *name = node->name, *channel_name;
	u32 chan, value, varr[2];
	u32 sid = 0;
	int ret;
	struct device *dev = adc->dev;

	ret = of_property_read_u32(node, "reg", &chan);
	if (ret) {
@@ -808,6 +1006,16 @@ static int adc_get_dt_channel_data(struct device *dev,
		return ret;
	}

	/*
	 * Value read from "reg" is virtual channel number
	 * virtual channel number = (sid << 8 | channel number).
	 */

	if (adc->is_pmic7) {
		sid = (chan >> ADC_CHANNEL_OFFSET);
		chan = (chan & ADC_CHANNEL_MASK);
	}

	if (chan > ADC_PARALLEL_ISENSE_VBAT_IDATA) {
		dev_err(dev, "%s invalid channel number %d\n", name, chan);
		return -EINVAL;
@@ -815,6 +1023,7 @@ static int adc_get_dt_channel_data(struct device *dev,

	/* the channel has DT description */
	prop->channel = chan;
	prop->sid = sid;

	channel_name = of_get_property(node,
				"label", NULL) ? : node->name;
@@ -876,6 +1085,7 @@ static int adc_get_dt_channel_data(struct device *dev,

	prop->scale_fn_type = -EINVAL;
	ret = of_property_read_u32(node, "qcom,scale-fn-type", &value);

	if (!ret && value < SCALE_HW_CALIB_MAX)
		prop->scale_fn_type = value;

@@ -921,6 +1131,14 @@ const struct adc_data data_pmic5_lite = {
					800, 900, 1, 2, 4, 6, 8, 10},
};

const struct adc_data adc7_data_pmic = {
	.full_scale_code_volt = 0x70e4,
	.adc_chans = adc7_chans_pmic,
	.decimation = (unsigned int []) {85, 340, 1360},
	.hw_settle = (unsigned int []) {15, 100, 200, 300, 400, 500, 600, 700,
			1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000},
};

const struct adc_data data_pmic_rev2 = {
	.full_scale_code_volt = 0x4000,
	.full_scale_code_cur = 0x1800,
@@ -935,6 +1153,10 @@ static const struct of_device_id adc_match_table[] = {
		.compatible = "qcom,spmi-adc5",
		.data = &data_pmic5,
	},
	{
		.compatible = "qcom,spmi-adc7",
		.data = &adc7_data_pmic,
	},
	{
		.compatible = "qcom,spmi-adc-rev2",
		.data = &data_pmic_rev2,
@@ -980,7 +1202,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, data);
		ret = adc_get_dt_channel_data(adc, &prop, child, data);
		if (ret) {
			of_node_put(child);
			return ret;
@@ -1069,6 +1291,7 @@ static int adc_probe(struct platform_device *pdev)
	adc = iio_priv(indio_dev);
	adc->regmap = regmap;
	adc->dev = dev;

	adc->pmic_rev_id = pmic_rev_id;

	prop_addr = of_get_address(dev->of_node, 0, NULL, NULL);
@@ -1086,6 +1309,14 @@ static int adc_probe(struct platform_device *pdev)

	adc->skip_usb_wa = skip_usb_wa;

	if (of_device_is_compatible(node, "qcom,spmi-adc7")) {
		indio_dev->info = &adc7_info;
		adc->is_pmic7 = true;
	} else
		indio_dev->info = &adc_info;

	platform_set_drvdata(pdev, adc);

	init_completion(&adc->complete);
	mutex_init(&adc->lock);

@@ -1111,7 +1342,6 @@ static int adc_probe(struct platform_device *pdev)
	indio_dev->dev.of_node = node;
	indio_dev->name = pdev->name;
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->info = &adc_info;
	indio_dev->channels = adc->iio_chans;
	indio_dev->num_channels = adc->nchannels;

+259 −0
Original line number Diff line number Diff line
@@ -570,6 +570,195 @@ static const struct lut_table lut_table_400[] = {
	{adcmap_batt_therm_400k_6125, ARRAY_SIZE(adcmap_batt_therm_400k_6125)},
};

static const struct vadc_map_pt adcmap7_die_temp[] = {
	{ 433700, 1967},
	{ 473100, 1964},
	{ 512400, 1957},
	{ 551500, 1949},
	{ 590500, 1940},
	{ 629300, 1930},
	{ 667900, 1921},
	{ 706400, 1910},
	{ 744600, 1896},
	{ 782500, 1878},
	{ 820100, 1859},
	{ 857300, 0},
};

/*
 * Resistance to temperature table for 100k pull up for NTCG104EF104.
 */
static const struct vadc_map_pt adcmap7_100k[] = {
	{ 4250657, -40960 },
	{ 3962085, -39936 },
	{ 3694875, -38912 },
	{ 3447322, -37888 },
	{ 3217867, -36864 },
	{ 3005082, -35840 },
	{ 2807660, -34816 },
	{ 2624405, -33792 },
	{ 2454218, -32768 },
	{ 2296094, -31744 },
	{ 2149108, -30720 },
	{ 2012414, -29696 },
	{ 1885232, -28672 },
	{ 1766846, -27648 },
	{ 1656598, -26624 },
	{ 1553884, -25600 },
	{ 1458147, -24576 },
	{ 1368873, -23552 },
	{ 1285590, -22528 },
	{ 1207863, -21504 },
	{ 1135290, -20480 },
	{ 1067501, -19456 },
	{ 1004155, -18432 },
	{ 944935, -17408 },
	{ 889550, -16384 },
	{ 837731, -15360 },
	{ 789229, -14336 },
	{ 743813, -13312 },
	{ 701271, -12288 },
	{ 661405, -11264 },
	{ 624032, -10240 },
	{ 588982, -9216 },
	{ 556100, -8192 },
	{ 525239, -7168 },
	{ 496264, -6144 },
	{ 469050, -5120 },
	{ 443480, -4096 },
	{ 419448, -3072 },
	{ 396851, -2048 },
	{ 375597, -1024 },
	{ 355598, 0 },
	{ 336775, 1024 },
	{ 319052, 2048 },
	{ 302359, 3072 },
	{ 286630, 4096 },
	{ 271806, 5120 },
	{ 257829, 6144 },
	{ 244646, 7168 },
	{ 232209, 8192 },
	{ 220471, 9216 },
	{ 209390, 10240 },
	{ 198926, 11264 },
	{ 189040, 12288 },
	{ 179698, 13312 },
	{ 170868, 14336 },
	{ 162519, 15360 },
	{ 154622, 16384 },
	{ 147150, 17408 },
	{ 140079, 18432 },
	{ 133385, 19456 },
	{ 127046, 20480 },
	{ 121042, 21504 },
	{ 115352, 22528 },
	{ 109960, 23552 },
	{ 104848, 24576 },
	{ 100000, 25600 },
	{ 95402, 26624 },
	{ 91038, 27648 },
	{ 86897, 28672 },
	{ 82965, 29696 },
	{ 79232, 30720 },
	{ 75686, 31744 },
	{ 72316, 32768 },
	{ 69114, 33792 },
	{ 66070, 34816 },
	{ 63176, 35840 },
	{ 60423, 36864 },
	{ 57804, 37888 },
	{ 55312, 38912 },
	{ 52940, 39936 },
	{ 50681, 40960 },
	{ 48531, 41984 },
	{ 46482, 43008 },
	{ 44530, 44032 },
	{ 42670, 45056 },
	{ 40897, 46080 },
	{ 39207, 47104 },
	{ 37595, 48128 },
	{ 36057, 49152 },
	{ 34590, 50176 },
	{ 33190, 51200 },
	{ 31853, 52224 },
	{ 30577, 53248 },
	{ 29358, 54272 },
	{ 28194, 55296 },
	{ 27082, 56320 },
	{ 26020, 57344 },
	{ 25004, 58368 },
	{ 24033, 59392 },
	{ 23104, 60416 },
	{ 22216, 61440 },
	{ 21367, 62464 },
	{ 20554, 63488 },
	{ 19776, 64512 },
	{ 19031, 65536 },
	{ 18318, 66560 },
	{ 17636, 67584 },
	{ 16982, 68608 },
	{ 16355, 69632 },
	{ 15755, 70656 },
	{ 15180, 71680 },
	{ 14628, 72704 },
	{ 14099, 73728 },
	{ 13592, 74752 },
	{ 13106, 75776 },
	{ 12640, 76800 },
	{ 12192, 77824 },
	{ 11762, 78848 },
	{ 11350, 79872 },
	{ 10954, 80896 },
	{ 10574, 81920 },
	{ 10209, 82944 },
	{ 9858, 83968 },
	{ 9521, 84992 },
	{ 9197, 86016 },
	{ 8886, 87040 },
	{ 8587, 88064 },
	{ 8299, 89088 },
	{ 8023, 90112 },
	{ 7757, 91136 },
	{ 7501, 92160 },
	{ 7254, 93184 },
	{ 7017, 94208 },
	{ 6789, 95232 },
	{ 6570, 96256 },
	{ 6358, 97280 },
	{ 6155, 98304 },
	{ 5959, 99328 },
	{ 5770, 100352 },
	{ 5588, 101376 },
	{ 5412, 102400 },
	{ 5243, 103424 },
	{ 5080, 104448 },
	{ 4923, 105472 },
	{ 4771, 106496 },
	{ 4625, 107520 },
	{ 4484, 108544 },
	{ 4348, 109568 },
	{ 4217, 110592 },
	{ 4090, 111616 },
	{ 3968, 112640 },
	{ 3850, 113664 },
	{ 3736, 114688 },
	{ 3626, 115712 },
	{ 3519, 116736 },
	{ 3417, 117760 },
	{ 3317, 118784 },
	{ 3221, 119808 },
	{ 3129, 120832 },
	{ 3039, 121856 },
	{ 2952, 122880 },
	{ 2868, 123904 },
	{ 2787, 124928 },
	{ 2709, 125952 },
	{ 2633, 126976 },
	{ 2560, 128000 },
	{ 2489, 129024 },
	{ 2420, 130048 }
};

static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts,
				      u32 tablesize, s32 input, s64 *output)
{
@@ -796,6 +985,32 @@ static int qcom_vadc_scale_hw_calib_batt_therm_100(
	return 0;
}

static int qcom_vadc7_scale_hw_calib_therm(
				const struct vadc_prescale_ratio *prescale,
				const struct adc_data *data,
				u16 adc_code, int *result_mdec)
{
	s64 resistance = 0, result = 0;
	int ret;

	if (adc_code >= RATIO_MAX_ADC7)
		return -EINVAL;

	/* (ADC code * R_PULLUP (100Kohm)) / (full_scale_code - ADC code)*/
	resistance = (s64) adc_code * R_PU_100K;
	resistance = div64_s64(resistance, (RATIO_MAX_ADC7 - adc_code));

	ret = qcom_vadc_map_voltage_temp(adcmap7_100k,
				 ARRAY_SIZE(adcmap7_100k),
				 resistance, &result);
	if (ret)
		return ret;

	*result_mdec = result;

	return 0;
}

static int qcom_vadc_scale_hw_calib_batt_therm_30(
				const struct vadc_prescale_ratio *prescale,
				const struct adc_data *data,
@@ -896,6 +1111,44 @@ static int qcom_vadc_scale_hw_calib_die_temp(
	return 0;
}

static int qcom_vadc7_scale_hw_calib_die_temp(
				const struct vadc_prescale_ratio *prescale,
				const struct adc_data *data,
				u16 adc_code, int *result_mdec)
{

	s64 voltage, vtemp0, temp;
	int adc_vdd_ref_mv = 1875, i = 0;

	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);
	voltage = voltage * prescale->den;
	voltage = div64_s64(voltage, prescale->num);

	while (i < ARRAY_SIZE(adcmap7_die_temp)) {
		if (adcmap7_die_temp[i].x > voltage)
			break;
		i++;
	}

	if (i == 0) {
		*result_mdec = DIE_TEMP_ADC7_SCALE_1;
	} else if (i == ARRAY_SIZE(adcmap7_die_temp)) {
		*result_mdec = DIE_TEMP_ADC7_MAX;
	} else {
		vtemp0 = adcmap7_die_temp[i-1].x;
		voltage = voltage - vtemp0;
		temp = div64_s64(voltage, adcmap7_die_temp[i-1].y);
		temp += DIE_TEMP_ADC7_SCALE_1 + (DIE_TEMP_ADC7_SCALE_2 * (i-1));
		*result_mdec = temp;
	}
	return 0;
}

static int qcom_vadc_scale_hw_smb_temp(
				const struct vadc_prescale_ratio *prescale,
				const struct adc_data *data,
@@ -1075,6 +1328,12 @@ int qcom_vadc_hw_scale(enum vadc_scale_fn_type scaletype,
	case SCALE_HW_CALIB_PM5_SMB1398_TEMP:
		return qcom_vadc_scale_hw_smb1398_temp(prescale, data,
						adc_code, result);
	case SCALE_HW_CALIB_THERM_100K_PU_PM7:
		return qcom_vadc7_scale_hw_calib_therm(prescale, data,
						adc_code, result);
	case SCALE_HW_CALIB_PMIC_THERM_PM7:
		return qcom_vadc7_scale_hw_calib_die_temp(prescale, data,
						adc_code, result);
	default:
		return -EINVAL;
	}
+13 −0
Original line number Diff line number Diff line
@@ -83,6 +83,13 @@
#define	ADC_DBG1(dev, msg, args...)		pr_debug(msg, ##args)
#endif

#define R_PU_100K			100000
#define RATIO_MAX_ADC7		0x4000

#define DIE_TEMP_ADC7_SCALE_1				-60
#define DIE_TEMP_ADC7_SCALE_2				20
#define DIE_TEMP_ADC7_MAX				160

/**
 * struct vadc_map_pt - Map the graph representation for ADC channel
 * @x: Represent the ADC digitized code.
@@ -144,9 +151,13 @@ struct vadc_prescale_ratio {
 *	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_THERM_100K_PU_PM7: Returns temperature in millidegC using
 *	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_CUR: Returns result in uA for PMIC5.
 * SCALE_HW_CALIB_PMIC_THERM: 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
@@ -170,8 +181,10 @@ enum vadc_scale_fn_type {
	SCALE_HW_CALIB_DEFAULT,
	SCALE_HW_CALIB_THERM_100K_PULLUP,
	SCALE_HW_CALIB_XOTHERM,
	SCALE_HW_CALIB_THERM_100K_PU_PM7,
	SCALE_HW_CALIB_PMIC_THERM,
	SCALE_HW_CALIB_CUR,
	SCALE_HW_CALIB_PMIC_THERM_PM7,
	SCALE_HW_CALIB_PM5_CHG_TEMP,
	SCALE_HW_CALIB_PM5_SMB_TEMP,
	SCALE_HW_CALIB_BATT_THERM_100K,
+1 −1
Original line number Diff line number Diff line
obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o
obj-$(CONFIG_QTI_ADC_TM) += adc-tm.o adc-tm-common.o adc-tm5.o
obj-$(CONFIG_QTI_ADC_TM) += adc-tm.o adc-tm-common.o adc-tm5.o adc-tm7.o
obj-$(CONFIG_QTI_VIRTUAL_SENSOR) += qti_virtual_sensor.o
obj-$(CONFIG_QTI_QMI_SENSOR) += thermal_sensor_service_v01.o qmi_sensors.o
obj-$(CONFIG_QTI_BCL_PMIC5) += bcl_pmic5.o
+258 −0
Original line number Diff line number Diff line
@@ -47,6 +47,181 @@ static const struct adc_tm_map_pt adcmap_100k_104ef_104fb_1875_vref[] = {
	{ 46000,	125000 },
};

/*
 * Resistance to temperature table for NTCG104EF104 thermistor with
 * 100k pull-up.
 */
static const struct adc_tm_map_pt adcmap_100k_adc7[] = {
	{ 4250657, -40960 },
	{ 3962085, -39936 },
	{ 3694875, -38912 },
	{ 3447322, -37888 },
	{ 3217867, -36864 },
	{ 3005082, -35840 },
	{ 2807660, -34816 },
	{ 2624405, -33792 },
	{ 2454218, -32768 },
	{ 2296094, -31744 },
	{ 2149108, -30720 },
	{ 2012414, -29696 },
	{ 1885232, -28672 },
	{ 1766846, -27648 },
	{ 1656598, -26624 },
	{ 1553884, -25600 },
	{ 1458147, -24576 },
	{ 1368873, -23552 },
	{ 1285590, -22528 },
	{ 1207863, -21504 },
	{ 1135290, -20480 },
	{ 1067501, -19456 },
	{ 1004155, -18432 },
	{ 944935, -17408 },
	{ 889550, -16384 },
	{ 837731, -15360 },
	{ 789229, -14336 },
	{ 743813, -13312 },
	{ 701271, -12288 },
	{ 661405, -11264 },
	{ 624032, -10240 },
	{ 588982, -9216 },
	{ 556100, -8192 },
	{ 525239, -7168 },
	{ 496264, -6144 },
	{ 469050, -5120 },
	{ 443480, -4096 },
	{ 419448, -3072 },
	{ 396851, -2048 },
	{ 375597, -1024 },
	{ 355598, 0 },
	{ 336775, 1024 },
	{ 319052, 2048 },
	{ 302359, 3072 },
	{ 286630, 4096 },
	{ 271806, 5120 },
	{ 257829, 6144 },
	{ 244646, 7168 },
	{ 232209, 8192 },
	{ 220471, 9216 },
	{ 209390, 10240 },
	{ 198926, 11264 },
	{ 189040, 12288 },
	{ 179698, 13312 },
	{ 170868, 14336 },
	{ 162519, 15360 },
	{ 154622, 16384 },
	{ 147150, 17408 },
	{ 140079, 18432 },
	{ 133385, 19456 },
	{ 127046, 20480 },
	{ 121042, 21504 },
	{ 115352, 22528 },
	{ 109960, 23552 },
	{ 104848, 24576 },
	{ 100000, 25600 },
	{ 95402, 26624 },
	{ 91038, 27648 },
	{ 86897, 28672 },
	{ 82965, 29696 },
	{ 79232, 30720 },
	{ 75686, 31744 },
	{ 72316, 32768 },
	{ 69114, 33792 },
	{ 66070, 34816 },
	{ 63176, 35840 },
	{ 60423, 36864 },
	{ 57804, 37888 },
	{ 55312, 38912 },
	{ 52940, 39936 },
	{ 50681, 40960 },
	{ 48531, 41984 },
	{ 46482, 43008 },
	{ 44530, 44032 },
	{ 42670, 45056 },
	{ 40897, 46080 },
	{ 39207, 47104 },
	{ 37595, 48128 },
	{ 36057, 49152 },
	{ 34590, 50176 },
	{ 33190, 51200 },
	{ 31853, 52224 },
	{ 30577, 53248 },
	{ 29358, 54272 },
	{ 28194, 55296 },
	{ 27082, 56320 },
	{ 26020, 57344 },
	{ 25004, 58368 },
	{ 24033, 59392 },
	{ 23104, 60416 },
	{ 22216, 61440 },
	{ 21367, 62464 },
	{ 20554, 63488 },
	{ 19776, 64512 },
	{ 19031, 65536 },
	{ 18318, 66560 },
	{ 17636, 67584 },
	{ 16982, 68608 },
	{ 16355, 69632 },
	{ 15755, 70656 },
	{ 15180, 71680 },
	{ 14628, 72704 },
	{ 14099, 73728 },
	{ 13592, 74752 },
	{ 13106, 75776 },
	{ 12640, 76800 },
	{ 12192, 77824 },
	{ 11762, 78848 },
	{ 11350, 79872 },
	{ 10954, 80896 },
	{ 10574, 81920 },
	{ 10209, 82944 },
	{ 9858, 83968 },
	{ 9521, 84992 },
	{ 9197, 86016 },
	{ 8886, 87040 },
	{ 8587, 88064 },
	{ 8299, 89088 },
	{ 8023, 90112 },
	{ 7757, 91136 },
	{ 7501, 92160 },
	{ 7254, 93184 },
	{ 7017, 94208 },
	{ 6789, 95232 },
	{ 6570, 96256 },
	{ 6358, 97280 },
	{ 6155, 98304 },
	{ 5959, 99328 },
	{ 5770, 100352 },
	{ 5588, 101376 },
	{ 5412, 102400 },
	{ 5243, 103424 },
	{ 5080, 104448 },
	{ 4923, 105472 },
	{ 4771, 106496 },
	{ 4625, 107520 },
	{ 4484, 108544 },
	{ 4348, 109568 },
	{ 4217, 110592 },
	{ 4090, 111616 },
	{ 3968, 112640 },
	{ 3850, 113664 },
	{ 3736, 114688 },
	{ 3626, 115712 },
	{ 3519, 116736 },
	{ 3417, 117760 },
	{ 3317, 118784 },
	{ 3221, 119808 },
	{ 3129, 120832 },
	{ 3039, 121856 },
	{ 2952, 122880 },
	{ 2868, 123904 },
	{ 2787, 124928 },
	{ 2709, 125952 },
	{ 2633, 126976 },
	{ 2560, 128000 },
	{ 2489, 129024 },
	{ 2420, 130048 }
};

static void adc_tm_map_voltage_temp(const struct adc_tm_map_pt *pts,
				      size_t tablesize, int input, int *output)
{
@@ -140,6 +315,7 @@ int therm_fwd_scale(int64_t code, uint32_t adc_hc_vdd_ref_mv,
	volt = (s64) code * adc_hc_vdd_ref_mv;
	volt = div64_s64(volt, (data->full_scale_code_volt));

	/* Same API can be used for resistance-temperature table */
	adc_tm_map_voltage_temp(adcmap_100k_104ef_104fb_1875_vref,
				 ARRAY_SIZE(adcmap_100k_104ef_104fb_1875_vref),
				 (int) volt, &result);
@@ -148,6 +324,25 @@ int therm_fwd_scale(int64_t code, uint32_t adc_hc_vdd_ref_mv,
}
EXPORT_SYMBOL(therm_fwd_scale);

int therm_fwd_scale_adc7(int64_t code)
{
	int64_t resistance = 0;
	int result = 0;

	if (code >= RATIO_MAX_ADC7)
		return -EINVAL;

	resistance = (s64) code * R_PU_100K;
	resistance = div64_s64(resistance, (RATIO_MAX_ADC7 - code));

	adc_tm_map_voltage_temp(adcmap_100k_adc7,
				 ARRAY_SIZE(adcmap_100k_adc7),
				 (int) resistance, &result);

	return result;
}
EXPORT_SYMBOL(therm_fwd_scale_adc7);

void adc_tm_scale_therm_voltage_100k(struct adc_tm_config *param,
				const struct adc_tm_data *data)
{
@@ -188,6 +383,47 @@ void adc_tm_scale_therm_voltage_100k(struct adc_tm_config *param,
}
EXPORT_SYMBOL(adc_tm_scale_therm_voltage_100k);

void adc_tm_scale_therm_voltage_100k_adc7(struct adc_tm_config *param)
{
	int temp;
	int64_t resistance = 0;

	/* High temperature maps to lower threshold voltage */
	/* Same API can be used for resistance-temperature table */
	adc_tm_map_temp_voltage(
		adcmap_100k_adc7,
		ARRAY_SIZE(adcmap_100k_adc7),
		param->high_thr_temp, &resistance);

	param->low_thr_voltage = resistance * RATIO_MAX_ADC7;
	param->low_thr_voltage = div64_s64(param->low_thr_voltage,
						(resistance + R_PU_100K));

	temp = therm_fwd_scale_adc7(param->low_thr_voltage);
	if (temp == -EINVAL)
		return;

	if (temp < param->high_thr_temp)
		param->low_thr_voltage--;

	/* Low temperature maps to higher threshold voltage */
	/* Same API can be used for resistance-temperature table */
	adc_tm_map_temp_voltage(
		adcmap_100k_adc7,
		ARRAY_SIZE(adcmap_100k_adc7),
		param->low_thr_temp, &resistance);

	param->high_thr_voltage = resistance * RATIO_MAX_ADC7;
	param->high_thr_voltage = div64_s64(param->high_thr_voltage,
						(resistance + R_PU_100K));

	temp = therm_fwd_scale_adc7(param->high_thr_voltage);

	if (temp > param->low_thr_temp)
		param->high_thr_voltage++;
}
EXPORT_SYMBOL(adc_tm_scale_therm_voltage_100k_adc7);

int32_t adc_tm_absolute_rthr(const struct adc_tm_data *data,
			struct adc_tm_config *tm_config)
{
@@ -195,11 +431,13 @@ int32_t adc_tm_absolute_rthr(const struct adc_tm_data *data,

	low_thr =  div_s64(tm_config->low_thr_voltage, tm_config->prescal);
	low_thr *= data->full_scale_code_volt;

	low_thr = div64_s64(low_thr, ADC_HC_VDD_REF);
	tm_config->low_thr_voltage = low_thr;

	high_thr =  div_s64(tm_config->high_thr_voltage, tm_config->prescal);
	high_thr *= data->full_scale_code_volt;

	high_thr = div64_s64(high_thr, ADC_HC_VDD_REF);
	tm_config->high_thr_voltage = high_thr;

@@ -207,5 +445,25 @@ int32_t adc_tm_absolute_rthr(const struct adc_tm_data *data,
}
EXPORT_SYMBOL(adc_tm_absolute_rthr);

int32_t adc_tm_absolute_rthr_adc7(struct adc_tm_config *tm_config)
{
	int64_t low_thr = 0, high_thr = 0;

	low_thr =  div_s64(tm_config->low_thr_voltage, tm_config->prescal);
	low_thr *= MAX_CODE_VOLT;

	low_thr = div64_s64(low_thr, ADC_HC_VDD_REF);
	tm_config->low_thr_voltage = low_thr;

	high_thr =  div_s64(tm_config->high_thr_voltage, tm_config->prescal);
	high_thr *= MAX_CODE_VOLT;

	high_thr = div64_s64(high_thr, ADC_HC_VDD_REF);
	tm_config->high_thr_voltage = high_thr;

	return 0;
}
EXPORT_SYMBOL(adc_tm_absolute_rthr_adc7);

MODULE_DESCRIPTION("Qualcomm Technologies Inc. PMIC ADC_TM common driver");
MODULE_LICENSE("GPL v2");
Loading