brintos

brintos / linux-shallow public Read only

0
0
Text · 25.3 KiB · 9b69f40 Raw
941 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved.4 */5 6#include <linux/bitops.h>7#include <linux/completion.h>8#include <linux/delay.h>9#include <linux/err.h>10#include <linux/iio/adc/qcom-vadc-common.h>11#include <linux/iio/iio.h>12#include <linux/interrupt.h>13#include <linux/kernel.h>14#include <linux/log2.h>15#include <linux/math64.h>16#include <linux/module.h>17#include <linux/mod_devicetable.h>18#include <linux/platform_device.h>19#include <linux/property.h>20#include <linux/regmap.h>21#include <linux/slab.h>22 23#include <dt-bindings/iio/qcom,spmi-vadc.h>24 25#define ADC5_USR_REVISION1			0x026#define ADC5_USR_STATUS1			0x827#define ADC5_USR_STATUS1_CONV_FAULT		BIT(7)28#define ADC5_USR_STATUS1_REQ_STS		BIT(1)29#define ADC5_USR_STATUS1_EOC			BIT(0)30#define ADC5_USR_STATUS1_REQ_STS_EOC_MASK	0x331 32#define ADC5_USR_STATUS2			0x933#define ADC5_USR_STATUS2_CONV_SEQ_MASK		0x7034#define ADC5_USR_STATUS2_CONV_SEQ_MASK_SHIFT	0x535 36#define ADC5_USR_IBAT_MEAS			0xf37#define ADC5_USR_IBAT_MEAS_SUPPORTED		BIT(0)38 39#define ADC5_USR_DIG_PARAM			0x4240#define ADC5_USR_DIG_PARAM_CAL_VAL		BIT(6)41#define ADC5_USR_DIG_PARAM_CAL_VAL_SHIFT	642#define ADC5_USR_DIG_PARAM_CAL_SEL		0x3043#define ADC5_USR_DIG_PARAM_CAL_SEL_SHIFT	444#define ADC5_USR_DIG_PARAM_DEC_RATIO_SEL	0xc45#define ADC5_USR_DIG_PARAM_DEC_RATIO_SEL_SHIFT	246 47#define ADC5_USR_FAST_AVG_CTL			0x4348#define ADC5_USR_FAST_AVG_CTL_EN		BIT(7)49#define ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK	0x750 51#define ADC5_USR_CH_SEL_CTL			0x4452 53#define ADC5_USR_DELAY_CTL			0x4554#define ADC5_USR_HW_SETTLE_DELAY_MASK		0xf55 56#define ADC5_USR_EN_CTL1			0x4657#define ADC5_USR_EN_CTL1_ADC_EN			BIT(7)58 59#define ADC5_USR_CONV_REQ			0x4760#define ADC5_USR_CONV_REQ_REQ			BIT(7)61 62#define ADC5_USR_DATA0				0x5063 64#define ADC5_USR_DATA1				0x5165 66#define ADC5_USR_IBAT_DATA0			0x5267 68#define ADC5_USR_IBAT_DATA1			0x5369 70#define ADC_CHANNEL_OFFSET			0x871#define ADC_CHANNEL_MASK			GENMASK(7, 0)72 73/*74 * Conversion time varies based on the decimation, clock rate, fast average75 * samples and measurements queued across different VADC peripherals.76 * Set the timeout to a max of 100ms.77 */78#define ADC5_CONV_TIME_MIN_US			26379#define ADC5_CONV_TIME_MAX_US			26480#define ADC5_CONV_TIME_RETRY			40081#define ADC5_CONV_TIMEOUT			msecs_to_jiffies(100)82 83/* Digital version >= 5.3 supports hw_settle_2 */84#define ADC5_HW_SETTLE_DIFF_MINOR		385#define ADC5_HW_SETTLE_DIFF_MAJOR		586 87/* For PMIC7 */88#define ADC_APP_SID				0x4089#define ADC_APP_SID_MASK			GENMASK(3, 0)90#define ADC7_CONV_TIMEOUT			msecs_to_jiffies(10)91 92enum adc5_cal_method {93	ADC5_NO_CAL = 0,94	ADC5_RATIOMETRIC_CAL,95	ADC5_ABSOLUTE_CAL96};97 98enum adc5_cal_val {99	ADC5_TIMER_CAL = 0,100	ADC5_NEW_CAL101};102 103/**104 * struct adc5_channel_prop - ADC channel property.105 * @channel: channel number, refer to the channel list.106 * @cal_method: calibration method.107 * @cal_val: calibration value108 * @decimation: sampling rate supported for the channel.109 * @sid: slave id of PMIC owning the channel, for PMIC7.110 * @prescale: channel scaling performed on the input signal.111 * @hw_settle_time: the time between AMUX being configured and the112 *	start of conversion.113 * @avg_samples: ability to provide single result from the ADC114 *	that is an average of multiple measurements.115 * @scale_fn_type: Represents the scaling function to convert voltage116 *	physical units desired by the client for the channel.117 * @channel_name: Channel name used in device tree.118 */119struct adc5_channel_prop {120	unsigned int		channel;121	enum adc5_cal_method	cal_method;122	enum adc5_cal_val	cal_val;123	unsigned int		decimation;124	unsigned int		sid;125	unsigned int		prescale;126	unsigned int		hw_settle_time;127	unsigned int		avg_samples;128	enum vadc_scale_fn_type	scale_fn_type;129	const char		*channel_name;130};131 132/**133 * struct adc5_chip - ADC private structure.134 * @regmap: SPMI ADC5 peripheral register map field.135 * @dev: SPMI ADC5 device.136 * @base: base address for the ADC peripheral.137 * @nchannels: number of ADC channels.138 * @chan_props: array of ADC channel properties.139 * @iio_chans: array of IIO channels specification.140 * @poll_eoc: use polling instead of interrupt.141 * @complete: ADC result notification after interrupt is received.142 * @lock: ADC lock for access to the peripheral.143 * @data: software configuration data.144 */145struct adc5_chip {146	struct regmap		*regmap;147	struct device		*dev;148	u16			base;149	unsigned int		nchannels;150	struct adc5_channel_prop	*chan_props;151	struct iio_chan_spec	*iio_chans;152	bool			poll_eoc;153	struct completion	complete;154	struct mutex		lock;155	const struct adc5_data	*data;156};157 158static int adc5_read(struct adc5_chip *adc, u16 offset, u8 *data, int len)159{160	return regmap_bulk_read(adc->regmap, adc->base + offset, data, len);161}162 163static int adc5_write(struct adc5_chip *adc, u16 offset, u8 *data, int len)164{165	return regmap_bulk_write(adc->regmap, adc->base + offset, data, len);166}167 168static int adc5_masked_write(struct adc5_chip *adc, u16 offset, u8 mask, u8 val)169{170	return regmap_update_bits(adc->regmap, adc->base + offset, mask, val);171}172 173static int adc5_read_voltage_data(struct adc5_chip *adc, u16 *data)174{175	int ret;176	u8 rslt_lsb, rslt_msb;177 178	ret = adc5_read(adc, ADC5_USR_DATA0, &rslt_lsb, sizeof(rslt_lsb));179	if (ret)180		return ret;181 182	ret = adc5_read(adc, ADC5_USR_DATA1, &rslt_msb, sizeof(rslt_lsb));183	if (ret)184		return ret;185 186	*data = (rslt_msb << 8) | rslt_lsb;187 188	if (*data == ADC5_USR_DATA_CHECK) {189		dev_err(adc->dev, "Invalid data:0x%x\n", *data);190		return -EINVAL;191	}192 193	dev_dbg(adc->dev, "voltage raw code:0x%x\n", *data);194 195	return 0;196}197 198static int adc5_poll_wait_eoc(struct adc5_chip *adc)199{200	unsigned int count, retry = ADC5_CONV_TIME_RETRY;201	u8 status1;202	int ret;203 204	for (count = 0; count < retry; count++) {205		ret = adc5_read(adc, ADC5_USR_STATUS1, &status1,206							sizeof(status1));207		if (ret)208			return ret;209 210		status1 &= ADC5_USR_STATUS1_REQ_STS_EOC_MASK;211		if (status1 == ADC5_USR_STATUS1_EOC)212			return 0;213 214		usleep_range(ADC5_CONV_TIME_MIN_US, ADC5_CONV_TIME_MAX_US);215	}216 217	return -ETIMEDOUT;218}219 220static void adc5_update_dig_param(struct adc5_chip *adc,221			struct adc5_channel_prop *prop, u8 *data)222{223	/* Update calibration value */224	*data &= ~ADC5_USR_DIG_PARAM_CAL_VAL;225	*data |= (prop->cal_val << ADC5_USR_DIG_PARAM_CAL_VAL_SHIFT);226 227	/* Update calibration select */228	*data &= ~ADC5_USR_DIG_PARAM_CAL_SEL;229	*data |= (prop->cal_method << ADC5_USR_DIG_PARAM_CAL_SEL_SHIFT);230 231	/* Update decimation ratio select */232	*data &= ~ADC5_USR_DIG_PARAM_DEC_RATIO_SEL;233	*data |= (prop->decimation << ADC5_USR_DIG_PARAM_DEC_RATIO_SEL_SHIFT);234}235 236static int adc5_configure(struct adc5_chip *adc,237			struct adc5_channel_prop *prop)238{239	int ret;240	u8 buf[6];241 242	/* Read registers 0x42 through 0x46 */243	ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));244	if (ret)245		return ret;246 247	/* Digital param selection */248	adc5_update_dig_param(adc, prop, &buf[0]);249 250	/* Update fast average sample value */251	buf[1] &= (u8) ~ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK;252	buf[1] |= prop->avg_samples;253 254	/* Select ADC channel */255	buf[2] = prop->channel;256 257	/* Select HW settle delay for channel */258	buf[3] &= (u8) ~ADC5_USR_HW_SETTLE_DELAY_MASK;259	buf[3] |= prop->hw_settle_time;260 261	/* Select ADC enable */262	buf[4] |= ADC5_USR_EN_CTL1_ADC_EN;263 264	/* Select CONV request */265	buf[5] |= ADC5_USR_CONV_REQ_REQ;266 267	if (!adc->poll_eoc)268		reinit_completion(&adc->complete);269 270	return adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));271}272 273static int adc7_configure(struct adc5_chip *adc,274			struct adc5_channel_prop *prop)275{276	int ret;277	u8 conv_req = 0, buf[4];278 279	ret = adc5_masked_write(adc, ADC_APP_SID, ADC_APP_SID_MASK, prop->sid);280	if (ret)281		return ret;282 283	ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));284	if (ret)285		return ret;286 287	/* Digital param selection */288	adc5_update_dig_param(adc, prop, &buf[0]);289 290	/* Update fast average sample value */291	buf[1] &= ~ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK;292	buf[1] |= prop->avg_samples;293 294	/* Select ADC channel */295	buf[2] = prop->channel;296 297	/* Select HW settle delay for channel */298	buf[3] &= ~ADC5_USR_HW_SETTLE_DELAY_MASK;299	buf[3] |= prop->hw_settle_time;300 301	/* Select CONV request */302	conv_req = ADC5_USR_CONV_REQ_REQ;303 304	if (!adc->poll_eoc)305		reinit_completion(&adc->complete);306 307	ret = adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));308	if (ret)309		return ret;310 311	return adc5_write(adc, ADC5_USR_CONV_REQ, &conv_req, 1);312}313 314static int adc5_do_conversion(struct adc5_chip *adc,315			struct adc5_channel_prop *prop,316			struct iio_chan_spec const *chan,317			u16 *data_volt, u16 *data_cur)318{319	int ret;320 321	mutex_lock(&adc->lock);322 323	ret = adc5_configure(adc, prop);324	if (ret) {325		dev_err(adc->dev, "ADC configure failed with %d\n", ret);326		goto unlock;327	}328 329	if (adc->poll_eoc) {330		ret = adc5_poll_wait_eoc(adc);331		if (ret) {332			dev_err(adc->dev, "EOC bit not set\n");333			goto unlock;334		}335	} else {336		ret = wait_for_completion_timeout(&adc->complete,337							ADC5_CONV_TIMEOUT);338		if (!ret) {339			dev_dbg(adc->dev, "Did not get completion timeout.\n");340			ret = adc5_poll_wait_eoc(adc);341			if (ret) {342				dev_err(adc->dev, "EOC bit not set\n");343				goto unlock;344			}345		}346	}347 348	ret = adc5_read_voltage_data(adc, data_volt);349unlock:350	mutex_unlock(&adc->lock);351 352	return ret;353}354 355static int adc7_do_conversion(struct adc5_chip *adc,356			struct adc5_channel_prop *prop,357			struct iio_chan_spec const *chan,358			u16 *data_volt, u16 *data_cur)359{360	int ret;361	u8 status;362 363	mutex_lock(&adc->lock);364 365	ret = adc7_configure(adc, prop);366	if (ret) {367		dev_err(adc->dev, "ADC configure failed with %d\n", ret);368		goto unlock;369	}370 371	/* No support for polling mode at present */372	wait_for_completion_timeout(&adc->complete, ADC7_CONV_TIMEOUT);373 374	ret = adc5_read(adc, ADC5_USR_STATUS1, &status, 1);375	if (ret)376		goto unlock;377 378	if (status & ADC5_USR_STATUS1_CONV_FAULT) {379		dev_err(adc->dev, "Unexpected conversion fault\n");380		ret = -EIO;381		goto unlock;382	}383 384	ret = adc5_read_voltage_data(adc, data_volt);385 386unlock:387	mutex_unlock(&adc->lock);388 389	return ret;390}391 392typedef int (*adc_do_conversion)(struct adc5_chip *adc,393			struct adc5_channel_prop *prop,394			struct iio_chan_spec const *chan,395			u16 *data_volt, u16 *data_cur);396 397static irqreturn_t adc5_isr(int irq, void *dev_id)398{399	struct adc5_chip *adc = dev_id;400 401	complete(&adc->complete);402 403	return IRQ_HANDLED;404}405 406static int adc5_fwnode_xlate(struct iio_dev *indio_dev,407			     const struct fwnode_reference_args *iiospec)408{409	struct adc5_chip *adc = iio_priv(indio_dev);410	int i;411 412	for (i = 0; i < adc->nchannels; i++)413		if (adc->chan_props[i].channel == iiospec->args[0])414			return i;415 416	return -EINVAL;417}418 419static int adc7_fwnode_xlate(struct iio_dev *indio_dev,420			     const struct fwnode_reference_args *iiospec)421{422	struct adc5_chip *adc = iio_priv(indio_dev);423	int i, v_channel;424 425	for (i = 0; i < adc->nchannels; i++) {426		v_channel = (adc->chan_props[i].sid << ADC_CHANNEL_OFFSET) |427			adc->chan_props[i].channel;428		if (v_channel == iiospec->args[0])429			return i;430	}431 432	return -EINVAL;433}434 435static int adc_read_raw_common(struct iio_dev *indio_dev,436			 struct iio_chan_spec const *chan, int *val, int *val2,437			 long mask, adc_do_conversion do_conv)438{439	struct adc5_chip *adc = iio_priv(indio_dev);440	struct adc5_channel_prop *prop;441	u16 adc_code_volt, adc_code_cur;442	int ret;443 444	prop = &adc->chan_props[chan->address];445 446	switch (mask) {447	case IIO_CHAN_INFO_PROCESSED:448		ret = do_conv(adc, prop, chan,449					&adc_code_volt, &adc_code_cur);450		if (ret)451			return ret;452 453		ret = qcom_adc5_hw_scale(prop->scale_fn_type,454			prop->prescale,455			adc->data,456			adc_code_volt, val);457		if (ret)458			return ret;459 460		return IIO_VAL_INT;461	default:462		return -EINVAL;463	}464}465 466static int adc5_read_raw(struct iio_dev *indio_dev,467			 struct iio_chan_spec const *chan, int *val, int *val2,468			 long mask)469{470	return adc_read_raw_common(indio_dev, chan, val, val2,471				mask, adc5_do_conversion);472}473 474static int adc7_read_raw(struct iio_dev *indio_dev,475			 struct iio_chan_spec const *chan, int *val, int *val2,476			 long mask)477{478	return adc_read_raw_common(indio_dev, chan, val, val2,479				mask, adc7_do_conversion);480}481 482static const struct iio_info adc5_info = {483	.read_raw = adc5_read_raw,484	.fwnode_xlate = adc5_fwnode_xlate,485};486 487static const struct iio_info adc7_info = {488	.read_raw = adc7_read_raw,489	.fwnode_xlate = adc7_fwnode_xlate,490};491 492struct adc5_channels {493	const char *datasheet_name;494	unsigned int prescale_index;495	enum iio_chan_type type;496	long info_mask;497	enum vadc_scale_fn_type scale_fn_type;498};499 500/* In these definitions, _pre refers to an index into adc5_prescale_ratios. */501#define ADC5_CHAN(_dname, _type, _mask, _pre, _scale)			\502	{								\503		.datasheet_name = _dname,				\504		.prescale_index = _pre,					\505		.type = _type,						\506		.info_mask = _mask,					\507		.scale_fn_type = _scale,				\508	},								\509 510#define ADC5_CHAN_TEMP(_dname, _pre, _scale)				\511	ADC5_CHAN(_dname, IIO_TEMP,					\512		BIT(IIO_CHAN_INFO_PROCESSED),				\513		_pre, _scale)						\514 515#define ADC5_CHAN_VOLT(_dname, _pre, _scale)				\516	ADC5_CHAN(_dname, IIO_VOLTAGE,					\517		  BIT(IIO_CHAN_INFO_PROCESSED),				\518		  _pre, _scale)						\519 520static const struct adc5_channels adc5_chans_pmic[ADC5_MAX_CHANNEL] = {521	[ADC5_REF_GND]		= ADC5_CHAN_VOLT("ref_gnd", 0,522					SCALE_HW_CALIB_DEFAULT)523	[ADC5_1P25VREF]		= ADC5_CHAN_VOLT("vref_1p25", 0,524					SCALE_HW_CALIB_DEFAULT)525	[ADC5_VPH_PWR]		= ADC5_CHAN_VOLT("vph_pwr", 1,526					SCALE_HW_CALIB_DEFAULT)527	[ADC5_VBAT_SNS]		= ADC5_CHAN_VOLT("vbat_sns", 1,528					SCALE_HW_CALIB_DEFAULT)529	[ADC5_VCOIN]		= ADC5_CHAN_VOLT("vcoin", 1,530					SCALE_HW_CALIB_DEFAULT)531	[ADC5_DIE_TEMP]		= ADC5_CHAN_TEMP("die_temp", 0,532					SCALE_HW_CALIB_PMIC_THERM)533	[ADC5_USB_IN_I]		= ADC5_CHAN_VOLT("usb_in_i_uv", 0,534					SCALE_HW_CALIB_DEFAULT)535	[ADC5_USB_IN_V_16]	= ADC5_CHAN_VOLT("usb_in_v_div_16", 8,536					SCALE_HW_CALIB_DEFAULT)537	[ADC5_CHG_TEMP]		= ADC5_CHAN_TEMP("chg_temp", 0,538					SCALE_HW_CALIB_PM5_CHG_TEMP)539	/* Charger prescales SBUx and MID_CHG to fit within 1.8V upper unit */540	[ADC5_SBUx]		= ADC5_CHAN_VOLT("chg_sbux", 1,541					SCALE_HW_CALIB_DEFAULT)542	[ADC5_MID_CHG_DIV6]	= ADC5_CHAN_VOLT("chg_mid_chg", 3,543					SCALE_HW_CALIB_DEFAULT)544	[ADC5_XO_THERM_100K_PU]	= ADC5_CHAN_TEMP("xo_therm", 0,545					SCALE_HW_CALIB_XOTHERM)546	[ADC5_BAT_ID_100K_PU]	= ADC5_CHAN_TEMP("bat_id", 0,547					SCALE_HW_CALIB_DEFAULT)548	[ADC5_AMUX_THM1_100K_PU] = ADC5_CHAN_TEMP("amux_thm1_100k_pu", 0,549					SCALE_HW_CALIB_THERM_100K_PULLUP)550	[ADC5_AMUX_THM2_100K_PU] = ADC5_CHAN_TEMP("amux_thm2_100k_pu", 0,551					SCALE_HW_CALIB_THERM_100K_PULLUP)552	[ADC5_AMUX_THM3_100K_PU] = ADC5_CHAN_TEMP("amux_thm3_100k_pu", 0,553					SCALE_HW_CALIB_THERM_100K_PULLUP)554	[ADC5_AMUX_THM2]	= ADC5_CHAN_TEMP("amux_thm2", 0,555					SCALE_HW_CALIB_PM5_SMB_TEMP)556	[ADC5_GPIO1_100K_PU]	= ADC5_CHAN_TEMP("gpio1_100k_pu", 0,557					SCALE_HW_CALIB_THERM_100K_PULLUP)558	[ADC5_GPIO2_100K_PU]	= ADC5_CHAN_TEMP("gpio2_100k_pu", 0,559					SCALE_HW_CALIB_THERM_100K_PULLUP)560	[ADC5_GPIO3_100K_PU]	= ADC5_CHAN_TEMP("gpio3_100k_pu", 0,561					SCALE_HW_CALIB_THERM_100K_PULLUP)562	[ADC5_GPIO4_100K_PU]	= ADC5_CHAN_TEMP("gpio4_100k_pu", 0,563					SCALE_HW_CALIB_THERM_100K_PULLUP)564};565 566static const struct adc5_channels adc7_chans_pmic[ADC5_MAX_CHANNEL] = {567	[ADC7_REF_GND]		= ADC5_CHAN_VOLT("ref_gnd", 0,568					SCALE_HW_CALIB_DEFAULT)569	[ADC7_1P25VREF]		= ADC5_CHAN_VOLT("vref_1p25", 0,570					SCALE_HW_CALIB_DEFAULT)571	[ADC7_VPH_PWR]		= ADC5_CHAN_VOLT("vph_pwr", 1,572					SCALE_HW_CALIB_DEFAULT)573	[ADC7_VBAT_SNS]		= ADC5_CHAN_VOLT("vbat_sns", 3,574					SCALE_HW_CALIB_DEFAULT)575	[ADC7_DIE_TEMP]		= ADC5_CHAN_TEMP("die_temp", 0,576					SCALE_HW_CALIB_PMIC_THERM_PM7)577	[ADC7_AMUX_THM1_100K_PU] = ADC5_CHAN_TEMP("amux_thm1_pu2", 0,578					SCALE_HW_CALIB_THERM_100K_PU_PM7)579	[ADC7_AMUX_THM2_100K_PU] = ADC5_CHAN_TEMP("amux_thm2_pu2", 0,580					SCALE_HW_CALIB_THERM_100K_PU_PM7)581	[ADC7_AMUX_THM3_100K_PU] = ADC5_CHAN_TEMP("amux_thm3_pu2", 0,582					SCALE_HW_CALIB_THERM_100K_PU_PM7)583	[ADC7_AMUX_THM4_100K_PU] = ADC5_CHAN_TEMP("amux_thm4_pu2", 0,584					SCALE_HW_CALIB_THERM_100K_PU_PM7)585	[ADC7_AMUX_THM5_100K_PU] = ADC5_CHAN_TEMP("amux_thm5_pu2", 0,586					SCALE_HW_CALIB_THERM_100K_PU_PM7)587	[ADC7_AMUX_THM6_100K_PU] = ADC5_CHAN_TEMP("amux_thm6_pu2", 0,588					SCALE_HW_CALIB_THERM_100K_PU_PM7)589	[ADC7_GPIO1_100K_PU]	= ADC5_CHAN_TEMP("gpio1_pu2", 0,590					SCALE_HW_CALIB_THERM_100K_PU_PM7)591	[ADC7_GPIO2_100K_PU]	= ADC5_CHAN_TEMP("gpio2_pu2", 0,592					SCALE_HW_CALIB_THERM_100K_PU_PM7)593	[ADC7_GPIO3_100K_PU]	= ADC5_CHAN_TEMP("gpio3_pu2", 0,594					SCALE_HW_CALIB_THERM_100K_PU_PM7)595	[ADC7_GPIO4_100K_PU]	= ADC5_CHAN_TEMP("gpio4_pu2", 0,596					SCALE_HW_CALIB_THERM_100K_PU_PM7)597};598 599static const struct adc5_channels adc5_chans_rev2[ADC5_MAX_CHANNEL] = {600	[ADC5_REF_GND]		= ADC5_CHAN_VOLT("ref_gnd", 0,601					SCALE_HW_CALIB_DEFAULT)602	[ADC5_1P25VREF]		= ADC5_CHAN_VOLT("vref_1p25", 0,603					SCALE_HW_CALIB_DEFAULT)604	[ADC5_VREF_VADC]	= ADC5_CHAN_VOLT("vref_vadc", 0,605					SCALE_HW_CALIB_DEFAULT)606	[ADC5_VPH_PWR]		= ADC5_CHAN_VOLT("vph_pwr", 1,607					SCALE_HW_CALIB_DEFAULT)608	[ADC5_VBAT_SNS]		= ADC5_CHAN_VOLT("vbat_sns", 1,609					SCALE_HW_CALIB_DEFAULT)610	[ADC5_VCOIN]		= ADC5_CHAN_VOLT("vcoin", 1,611					SCALE_HW_CALIB_DEFAULT)612	[ADC5_DIE_TEMP]		= ADC5_CHAN_TEMP("die_temp", 0,613					SCALE_HW_CALIB_PMIC_THERM)614	[ADC5_AMUX_THM1_100K_PU] = ADC5_CHAN_TEMP("amux_thm1_100k_pu", 0,615					SCALE_HW_CALIB_THERM_100K_PULLUP)616	[ADC5_AMUX_THM2_100K_PU] = ADC5_CHAN_TEMP("amux_thm2_100k_pu", 0,617					SCALE_HW_CALIB_THERM_100K_PULLUP)618	[ADC5_AMUX_THM3_100K_PU] = ADC5_CHAN_TEMP("amux_thm3_100k_pu", 0,619					SCALE_HW_CALIB_THERM_100K_PULLUP)620	[ADC5_AMUX_THM4_100K_PU] = ADC5_CHAN_TEMP("amux_thm4_100k_pu", 0,621					SCALE_HW_CALIB_THERM_100K_PULLUP)622	[ADC5_AMUX_THM5_100K_PU] = ADC5_CHAN_TEMP("amux_thm5_100k_pu", 0,623					SCALE_HW_CALIB_THERM_100K_PULLUP)624	[ADC5_XO_THERM_100K_PU]	= ADC5_CHAN_TEMP("xo_therm_100k_pu", 0,625					SCALE_HW_CALIB_THERM_100K_PULLUP)626};627 628static int adc5_get_fw_channel_data(struct adc5_chip *adc,629				    struct adc5_channel_prop *prop,630				    struct fwnode_handle *fwnode,631				    const struct adc5_data *data)632{633	const char *channel_name;634	char *name;635	u32 chan, value, varr[2];636	u32 sid = 0;637	int ret;638	struct device *dev = adc->dev;639 640	name = devm_kasprintf(dev, GFP_KERNEL, "%pfwP", fwnode);641	if (!name)642		return -ENOMEM;643 644	/* Cut the address part */645	name[strchrnul(name, '@') - name] = '\0';646 647	ret = fwnode_property_read_u32(fwnode, "reg", &chan);648	if (ret) {649		dev_err(dev, "invalid channel number %s\n", name);650		return ret;651	}652 653	/* Value read from "reg" is virtual channel number */654 655	/* virtual channel number = sid << 8 | channel number */656 657	if (adc->data->info == &adc7_info) {658		sid = chan >> ADC_CHANNEL_OFFSET;659		chan = chan & ADC_CHANNEL_MASK;660	}661 662	if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA) {663		dev_err(dev, "%s invalid channel number %d\n", name, chan);664		return -EINVAL;665	}666 667	/* the channel has DT description */668	prop->channel = chan;669	prop->sid = sid;670 671	ret = fwnode_property_read_string(fwnode, "label", &channel_name);672	if (ret)673		channel_name = data->adc_chans[chan].datasheet_name;674 675	prop->channel_name = channel_name;676 677	ret = fwnode_property_read_u32(fwnode, "qcom,decimation", &value);678	if (!ret) {679		ret = qcom_adc5_decimation_from_dt(value, data->decimation);680		if (ret < 0) {681			dev_err(dev, "%02x invalid decimation %d\n",682				chan, value);683			return ret;684		}685		prop->decimation = ret;686	} else {687		prop->decimation = ADC5_DECIMATION_DEFAULT;688	}689 690	ret = fwnode_property_read_u32_array(fwnode, "qcom,pre-scaling", varr, 2);691	if (!ret) {692		ret = qcom_adc5_prescaling_from_dt(varr[0], varr[1]);693		if (ret < 0) {694			dev_err(dev, "%02x invalid pre-scaling <%d %d>\n",695				chan, varr[0], varr[1]);696			return ret;697		}698		prop->prescale = ret;699	} else {700		prop->prescale =701			adc->data->adc_chans[prop->channel].prescale_index;702	}703 704	ret = fwnode_property_read_u32(fwnode, "qcom,hw-settle-time", &value);705	if (!ret) {706		u8 dig_version[2];707 708		ret = adc5_read(adc, ADC5_USR_REVISION1, dig_version,709							sizeof(dig_version));710		if (ret) {711			dev_err(dev, "Invalid dig version read %d\n", ret);712			return ret;713		}714 715		dev_dbg(dev, "dig_ver:minor:%d, major:%d\n", dig_version[0],716						dig_version[1]);717		/* Digital controller >= 5.3 have hw_settle_2 option */718		if ((dig_version[0] >= ADC5_HW_SETTLE_DIFF_MINOR &&719			dig_version[1] >= ADC5_HW_SETTLE_DIFF_MAJOR) ||720			adc->data->info == &adc7_info)721			ret = qcom_adc5_hw_settle_time_from_dt(value, data->hw_settle_2);722		else723			ret = qcom_adc5_hw_settle_time_from_dt(value, data->hw_settle_1);724 725		if (ret < 0) {726			dev_err(dev, "%02x invalid hw-settle-time %d us\n",727				chan, value);728			return ret;729		}730		prop->hw_settle_time = ret;731	} else {732		prop->hw_settle_time = VADC_DEF_HW_SETTLE_TIME;733	}734 735	ret = fwnode_property_read_u32(fwnode, "qcom,avg-samples", &value);736	if (!ret) {737		ret = qcom_adc5_avg_samples_from_dt(value);738		if (ret < 0) {739			dev_err(dev, "%02x invalid avg-samples %d\n",740				chan, value);741			return ret;742		}743		prop->avg_samples = ret;744	} else {745		prop->avg_samples = VADC_DEF_AVG_SAMPLES;746	}747 748	if (fwnode_property_read_bool(fwnode, "qcom,ratiometric"))749		prop->cal_method = ADC5_RATIOMETRIC_CAL;750	else751		prop->cal_method = ADC5_ABSOLUTE_CAL;752 753	/*754	 * Default to using timer calibration. Using a fresh calibration value755	 * for every conversion will increase the overall time for a request.756	 */757	prop->cal_val = ADC5_TIMER_CAL;758 759	dev_dbg(dev, "%02x name %s\n", chan, name);760 761	return 0;762}763 764static const struct adc5_data adc5_data_pmic = {765	.full_scale_code_volt = 0x70e4,766	.full_scale_code_cur = 0x2710,767	.adc_chans = adc5_chans_pmic,768	.info = &adc5_info,769	.decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])770				{250, 420, 840},771	.hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])772				{15, 100, 200, 300, 400, 500, 600, 700,773				800, 900, 1, 2, 4, 6, 8, 10},774	.hw_settle_2 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])775				{15, 100, 200, 300, 400, 500, 600, 700,776				1, 2, 4, 8, 16, 32, 64, 128},777};778 779static const struct adc5_data adc7_data_pmic = {780	.full_scale_code_volt = 0x70e4,781	.adc_chans = adc7_chans_pmic,782	.info = &adc7_info,783	.decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])784				{85, 340, 1360},785	.hw_settle_2 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])786				{15, 100, 200, 300, 400, 500, 600, 700,787				1000, 2000, 4000, 8000, 16000, 32000,788				64000, 128000},789};790 791static const struct adc5_data adc5_data_pmic_rev2 = {792	.full_scale_code_volt = 0x4000,793	.full_scale_code_cur = 0x1800,794	.adc_chans = adc5_chans_rev2,795	.info = &adc5_info,796	.decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])797				{256, 512, 1024},798	.hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])799				{0, 100, 200, 300, 400, 500, 600, 700,800				800, 900, 1, 2, 4, 6, 8, 10},801	.hw_settle_2 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])802				{15, 100, 200, 300, 400, 500, 600, 700,803				1, 2, 4, 8, 16, 32, 64, 128},804};805 806static const struct of_device_id adc5_match_table[] = {807	{808		.compatible = "qcom,spmi-adc5",809		.data = &adc5_data_pmic,810	},811	{812		.compatible = "qcom,spmi-adc7",813		.data = &adc7_data_pmic,814	},815	{816		.compatible = "qcom,spmi-adc-rev2",817		.data = &adc5_data_pmic_rev2,818	},819	{ }820};821MODULE_DEVICE_TABLE(of, adc5_match_table);822 823static int adc5_get_fw_data(struct adc5_chip *adc)824{825	const struct adc5_channels *adc_chan;826	struct iio_chan_spec *iio_chan;827	struct adc5_channel_prop prop, *chan_props;828	unsigned int index = 0;829	int ret;830 831	adc->nchannels = device_get_child_node_count(adc->dev);832	if (!adc->nchannels)833		return -EINVAL;834 835	adc->iio_chans = devm_kcalloc(adc->dev, adc->nchannels,836				       sizeof(*adc->iio_chans), GFP_KERNEL);837	if (!adc->iio_chans)838		return -ENOMEM;839 840	adc->chan_props = devm_kcalloc(adc->dev, adc->nchannels,841					sizeof(*adc->chan_props), GFP_KERNEL);842	if (!adc->chan_props)843		return -ENOMEM;844 845	chan_props = adc->chan_props;846	iio_chan = adc->iio_chans;847	adc->data = device_get_match_data(adc->dev);848	if (!adc->data)849		adc->data = &adc5_data_pmic;850 851	device_for_each_child_node_scoped(adc->dev, child) {852		ret = adc5_get_fw_channel_data(adc, &prop, child, adc->data);853		if (ret)854			return ret;855 856		prop.scale_fn_type =857			adc->data->adc_chans[prop.channel].scale_fn_type;858		*chan_props = prop;859		adc_chan = &adc->data->adc_chans[prop.channel];860 861		iio_chan->channel = prop.channel;862		iio_chan->datasheet_name = adc_chan->datasheet_name;863		iio_chan->extend_name = prop.channel_name;864		iio_chan->info_mask_separate = adc_chan->info_mask;865		iio_chan->type = adc_chan->type;866		iio_chan->address = index;867		iio_chan++;868		chan_props++;869		index++;870	}871 872	return 0;873}874 875static int adc5_probe(struct platform_device *pdev)876{877	struct device *dev = &pdev->dev;878	struct iio_dev *indio_dev;879	struct adc5_chip *adc;880	struct regmap *regmap;881	int ret, irq_eoc;882	u32 reg;883 884	regmap = dev_get_regmap(dev->parent, NULL);885	if (!regmap)886		return -ENODEV;887 888	ret = device_property_read_u32(dev, "reg", &reg);889	if (ret < 0)890		return ret;891 892	indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));893	if (!indio_dev)894		return -ENOMEM;895 896	adc = iio_priv(indio_dev);897	adc->regmap = regmap;898	adc->dev = dev;899	adc->base = reg;900 901	init_completion(&adc->complete);902	mutex_init(&adc->lock);903 904	ret = adc5_get_fw_data(adc);905	if (ret)906		return dev_err_probe(dev, ret, "adc get dt data failed\n");907 908	irq_eoc = platform_get_irq(pdev, 0);909	if (irq_eoc < 0) {910		if (irq_eoc == -EPROBE_DEFER || irq_eoc == -EINVAL)911			return irq_eoc;912		adc->poll_eoc = true;913	} else {914		ret = devm_request_irq(dev, irq_eoc, adc5_isr, 0,915				       "pm-adc5", adc);916		if (ret)917			return ret;918	}919 920	indio_dev->name = pdev->name;921	indio_dev->modes = INDIO_DIRECT_MODE;922	indio_dev->info = adc->data->info;923	indio_dev->channels = adc->iio_chans;924	indio_dev->num_channels = adc->nchannels;925 926	return devm_iio_device_register(dev, indio_dev);927}928 929static struct platform_driver adc5_driver = {930	.driver = {931		.name = "qcom-spmi-adc5",932		.of_match_table = adc5_match_table,933	},934	.probe = adc5_probe,935};936module_platform_driver(adc5_driver);937 938MODULE_ALIAS("platform:qcom-spmi-adc5");939MODULE_DESCRIPTION("Qualcomm Technologies Inc. PMIC5 ADC driver");940MODULE_LICENSE("GPL v2");941