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