xref: /linux/drivers/iio/adc/intel_dc_ti_adc.c (revision 4f38da1f027ea2c9f01bb71daa7a299c191b6940)
1*28e4b859SHans de Goede // SPDX-License-Identifier: GPL-2.0-only
2*28e4b859SHans de Goede /*
3*28e4b859SHans de Goede  * Intel Dollar Cove TI PMIC GPADC Driver
4*28e4b859SHans de Goede  *
5*28e4b859SHans de Goede  * Copyright (C) 2014 Intel Corporation (Ramakrishna Pallala <ramakrishna.pallala@intel.com>)
6*28e4b859SHans de Goede  * Copyright (C) 2024 - 2025 Hans de Goede <hansg@kernel.org>
7*28e4b859SHans de Goede  */
8*28e4b859SHans de Goede 
9*28e4b859SHans de Goede #include <linux/bits.h>
10*28e4b859SHans de Goede #include <linux/bitfield.h>
11*28e4b859SHans de Goede #include <linux/bitops.h>
12*28e4b859SHans de Goede #include <linux/cleanup.h>
13*28e4b859SHans de Goede #include <linux/delay.h>
14*28e4b859SHans de Goede #include <linux/device.h>
15*28e4b859SHans de Goede #include <linux/interrupt.h>
16*28e4b859SHans de Goede #include <linux/mfd/intel_soc_pmic.h>
17*28e4b859SHans de Goede #include <linux/mod_devicetable.h>
18*28e4b859SHans de Goede #include <linux/module.h>
19*28e4b859SHans de Goede #include <linux/mutex.h>
20*28e4b859SHans de Goede #include <linux/platform_device.h>
21*28e4b859SHans de Goede #include <linux/regmap.h>
22*28e4b859SHans de Goede #include <linux/wait.h>
23*28e4b859SHans de Goede 
24*28e4b859SHans de Goede #include <linux/iio/driver.h>
25*28e4b859SHans de Goede #include <linux/iio/iio.h>
26*28e4b859SHans de Goede #include <linux/iio/machine.h>
27*28e4b859SHans de Goede 
28*28e4b859SHans de Goede #define DC_TI_ADC_CNTL_REG			0x50
29*28e4b859SHans de Goede #define DC_TI_ADC_START				BIT(0)
30*28e4b859SHans de Goede #define DC_TI_ADC_CH_SEL			GENMASK(2, 1)
31*28e4b859SHans de Goede #define DC_TI_ADC_EN				BIT(5)
32*28e4b859SHans de Goede #define DC_TI_ADC_EN_EXT_BPTH_BIAS		BIT(6)
33*28e4b859SHans de Goede 
34*28e4b859SHans de Goede #define DC_TI_VBAT_ZSE_GE_REG			0x53
35*28e4b859SHans de Goede #define DC_TI_VBAT_GE				GENMASK(3, 0)
36*28e4b859SHans de Goede #define DC_TI_VBAT_ZSE				GENMASK(7, 4)
37*28e4b859SHans de Goede 
38*28e4b859SHans de Goede /* VBAT GE gain correction is in 0.0015 increments, ZSE is in 1.0 increments */
39*28e4b859SHans de Goede #define DC_TI_VBAT_GE_STEP			15
40*28e4b859SHans de Goede #define DC_TI_VBAT_GE_DIV			10000
41*28e4b859SHans de Goede 
42*28e4b859SHans de Goede #define DC_TI_ADC_DATA_REG_CH(x)		(0x54 + 2 * (x))
43*28e4b859SHans de Goede 
44*28e4b859SHans de Goede enum dc_ti_adc_id {
45*28e4b859SHans de Goede 	DC_TI_ADC_VBAT,
46*28e4b859SHans de Goede 	DC_TI_ADC_PMICTEMP,
47*28e4b859SHans de Goede 	DC_TI_ADC_BATTEMP,
48*28e4b859SHans de Goede 	DC_TI_ADC_SYSTEMP0,
49*28e4b859SHans de Goede };
50*28e4b859SHans de Goede 
51*28e4b859SHans de Goede struct dc_ti_adc_info {
52*28e4b859SHans de Goede 	struct mutex lock; /* Protects against concurrent accesses to the ADC */
53*28e4b859SHans de Goede 	wait_queue_head_t wait;
54*28e4b859SHans de Goede 	struct device *dev;
55*28e4b859SHans de Goede 	struct regmap *regmap;
56*28e4b859SHans de Goede 	int vbat_zse;
57*28e4b859SHans de Goede 	int vbat_ge;
58*28e4b859SHans de Goede 	bool conversion_done;
59*28e4b859SHans de Goede };
60*28e4b859SHans de Goede 
61*28e4b859SHans de Goede static const struct iio_chan_spec dc_ti_adc_channels[] = {
62*28e4b859SHans de Goede 	{
63*28e4b859SHans de Goede 		.indexed = 1,
64*28e4b859SHans de Goede 		.type = IIO_VOLTAGE,
65*28e4b859SHans de Goede 		.channel = DC_TI_ADC_VBAT,
66*28e4b859SHans de Goede 		.address = DC_TI_ADC_DATA_REG_CH(0),
67*28e4b859SHans de Goede 		.datasheet_name = "CH0",
68*28e4b859SHans de Goede 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
69*28e4b859SHans de Goede 				      BIT(IIO_CHAN_INFO_SCALE) |
70*28e4b859SHans de Goede 				      BIT(IIO_CHAN_INFO_PROCESSED),
71*28e4b859SHans de Goede 	}, {
72*28e4b859SHans de Goede 		.indexed = 1,
73*28e4b859SHans de Goede 		.type = IIO_TEMP,
74*28e4b859SHans de Goede 		.channel = DC_TI_ADC_PMICTEMP,
75*28e4b859SHans de Goede 		.address = DC_TI_ADC_DATA_REG_CH(1),
76*28e4b859SHans de Goede 		.datasheet_name = "CH1",
77*28e4b859SHans de Goede 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
78*28e4b859SHans de Goede 	}, {
79*28e4b859SHans de Goede 		.indexed = 1,
80*28e4b859SHans de Goede 		.type = IIO_TEMP,
81*28e4b859SHans de Goede 		.channel = DC_TI_ADC_BATTEMP,
82*28e4b859SHans de Goede 		.address = DC_TI_ADC_DATA_REG_CH(2),
83*28e4b859SHans de Goede 		.datasheet_name = "CH2",
84*28e4b859SHans de Goede 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
85*28e4b859SHans de Goede 	}, {
86*28e4b859SHans de Goede 		.indexed = 1,
87*28e4b859SHans de Goede 		.type = IIO_TEMP,
88*28e4b859SHans de Goede 		.channel = DC_TI_ADC_SYSTEMP0,
89*28e4b859SHans de Goede 		.address = DC_TI_ADC_DATA_REG_CH(3),
90*28e4b859SHans de Goede 		.datasheet_name = "CH3",
91*28e4b859SHans de Goede 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
92*28e4b859SHans de Goede 	}
93*28e4b859SHans de Goede };
94*28e4b859SHans de Goede 
95*28e4b859SHans de Goede static struct iio_map dc_ti_adc_default_maps[] = {
96*28e4b859SHans de Goede 	IIO_MAP("CH0", "chtdc_ti_battery", "VBAT"),
97*28e4b859SHans de Goede 	IIO_MAP("CH1", "chtdc_ti_battery", "PMICTEMP"),
98*28e4b859SHans de Goede 	IIO_MAP("CH2", "chtdc_ti_battery", "BATTEMP"),
99*28e4b859SHans de Goede 	IIO_MAP("CH3", "chtdc_ti_battery", "SYSTEMP0"),
100*28e4b859SHans de Goede 	{ }
101*28e4b859SHans de Goede };
102*28e4b859SHans de Goede 
103*28e4b859SHans de Goede static irqreturn_t dc_ti_adc_isr(int irq, void *data)
104*28e4b859SHans de Goede {
105*28e4b859SHans de Goede 	struct dc_ti_adc_info *info = data;
106*28e4b859SHans de Goede 
107*28e4b859SHans de Goede 	info->conversion_done = true;
108*28e4b859SHans de Goede 	wake_up(&info->wait);
109*28e4b859SHans de Goede 	return IRQ_HANDLED;
110*28e4b859SHans de Goede }
111*28e4b859SHans de Goede 
112*28e4b859SHans de Goede static int dc_ti_adc_scale(struct dc_ti_adc_info *info,
113*28e4b859SHans de Goede 			   struct iio_chan_spec const *chan,
114*28e4b859SHans de Goede 			   int *val, int *val2)
115*28e4b859SHans de Goede {
116*28e4b859SHans de Goede 	if (chan->channel != DC_TI_ADC_VBAT)
117*28e4b859SHans de Goede 		return -EINVAL;
118*28e4b859SHans de Goede 
119*28e4b859SHans de Goede 	/* Vbat ADC scale is 4.6875 mV / unit */
120*28e4b859SHans de Goede 	*val = 4;
121*28e4b859SHans de Goede 	*val2 = 687500;
122*28e4b859SHans de Goede 
123*28e4b859SHans de Goede 	return IIO_VAL_INT_PLUS_MICRO;
124*28e4b859SHans de Goede }
125*28e4b859SHans de Goede 
126*28e4b859SHans de Goede static int dc_ti_adc_raw_to_processed(struct dc_ti_adc_info *info,
127*28e4b859SHans de Goede 				      struct iio_chan_spec const *chan,
128*28e4b859SHans de Goede 				      int raw, int *val, int *val2)
129*28e4b859SHans de Goede {
130*28e4b859SHans de Goede 	if (chan->channel != DC_TI_ADC_VBAT)
131*28e4b859SHans de Goede 		return -EINVAL;
132*28e4b859SHans de Goede 
133*28e4b859SHans de Goede 	/* Apply calibration */
134*28e4b859SHans de Goede 	raw -= info->vbat_zse;
135*28e4b859SHans de Goede 	raw = raw * (DC_TI_VBAT_GE_DIV - info->vbat_ge * DC_TI_VBAT_GE_STEP) /
136*28e4b859SHans de Goede 	      DC_TI_VBAT_GE_DIV;
137*28e4b859SHans de Goede 	/* Vbat ADC scale is 4.6875 mV / unit */
138*28e4b859SHans de Goede 	raw *= 46875;
139*28e4b859SHans de Goede 
140*28e4b859SHans de Goede 	/* raw is now in 10000 units / mV, convert to milli + milli/1e6 */
141*28e4b859SHans de Goede 	*val = raw / 10000;
142*28e4b859SHans de Goede 	*val2 = (raw % 10000) * 100;
143*28e4b859SHans de Goede 
144*28e4b859SHans de Goede 	return IIO_VAL_INT_PLUS_MICRO;
145*28e4b859SHans de Goede }
146*28e4b859SHans de Goede 
147*28e4b859SHans de Goede static int dc_ti_adc_sample(struct dc_ti_adc_info *info,
148*28e4b859SHans de Goede 			    struct iio_chan_spec const *chan, int *val)
149*28e4b859SHans de Goede {
150*28e4b859SHans de Goede 	int ret, ch = chan->channel;
151*28e4b859SHans de Goede 	__be16 buf;
152*28e4b859SHans de Goede 
153*28e4b859SHans de Goede 	info->conversion_done = false;
154*28e4b859SHans de Goede 
155*28e4b859SHans de Goede 	/*
156*28e4b859SHans de Goede 	 * As per TI (PMIC Vendor), the ADC enable and ADC start commands should
157*28e4b859SHans de Goede 	 * not be sent together. Hence send the commands separately.
158*28e4b859SHans de Goede 	 */
159*28e4b859SHans de Goede 	ret = regmap_set_bits(info->regmap, DC_TI_ADC_CNTL_REG, DC_TI_ADC_EN);
160*28e4b859SHans de Goede 	if (ret)
161*28e4b859SHans de Goede 		return ret;
162*28e4b859SHans de Goede 
163*28e4b859SHans de Goede 	ret = regmap_update_bits(info->regmap, DC_TI_ADC_CNTL_REG,
164*28e4b859SHans de Goede 				 DC_TI_ADC_CH_SEL,
165*28e4b859SHans de Goede 				 FIELD_PREP(DC_TI_ADC_CH_SEL, ch));
166*28e4b859SHans de Goede 	if (ret)
167*28e4b859SHans de Goede 		return ret;
168*28e4b859SHans de Goede 
169*28e4b859SHans de Goede 	/*
170*28e4b859SHans de Goede 	 * As per PMIC Vendor, a minimum of 50 ųs delay is required between ADC
171*28e4b859SHans de Goede 	 * Enable and ADC START commands. This is also recommended by Intel
172*28e4b859SHans de Goede 	 * Hardware team after the timing analysis of GPADC signals. Since the
173*28e4b859SHans de Goede 	 * I2C Write transaction to set the channel number also imparts 25 ųs
174*28e4b859SHans de Goede 	 * delay, we need to wait for another 25 ųs before issuing ADC START.
175*28e4b859SHans de Goede 	 */
176*28e4b859SHans de Goede 	fsleep(25);
177*28e4b859SHans de Goede 
178*28e4b859SHans de Goede 	ret = regmap_set_bits(info->regmap, DC_TI_ADC_CNTL_REG,
179*28e4b859SHans de Goede 			      DC_TI_ADC_START);
180*28e4b859SHans de Goede 	if (ret)
181*28e4b859SHans de Goede 		return ret;
182*28e4b859SHans de Goede 
183*28e4b859SHans de Goede 	/* TI (PMIC Vendor) recommends 5 s timeout for conversion */
184*28e4b859SHans de Goede 	ret = wait_event_timeout(info->wait, info->conversion_done, 5 * HZ);
185*28e4b859SHans de Goede 	if (ret == 0) {
186*28e4b859SHans de Goede 		ret = -ETIMEDOUT;
187*28e4b859SHans de Goede 		goto disable_adc;
188*28e4b859SHans de Goede 	}
189*28e4b859SHans de Goede 
190*28e4b859SHans de Goede 	ret = regmap_bulk_read(info->regmap, chan->address, &buf, sizeof(buf));
191*28e4b859SHans de Goede 	if (ret)
192*28e4b859SHans de Goede 		goto disable_adc;
193*28e4b859SHans de Goede 
194*28e4b859SHans de Goede 	/* The ADC values are 10 bits wide */
195*28e4b859SHans de Goede 	*val = be16_to_cpu(buf) & GENMASK(9, 0);
196*28e4b859SHans de Goede 
197*28e4b859SHans de Goede disable_adc:
198*28e4b859SHans de Goede 	regmap_clear_bits(info->regmap, DC_TI_ADC_CNTL_REG,
199*28e4b859SHans de Goede 			  DC_TI_ADC_START | DC_TI_ADC_EN);
200*28e4b859SHans de Goede 	return ret;
201*28e4b859SHans de Goede }
202*28e4b859SHans de Goede 
203*28e4b859SHans de Goede static int dc_ti_adc_read_raw(struct iio_dev *indio_dev,
204*28e4b859SHans de Goede 			      struct iio_chan_spec const *chan,
205*28e4b859SHans de Goede 			      int *val, int *val2, long mask)
206*28e4b859SHans de Goede {
207*28e4b859SHans de Goede 	struct dc_ti_adc_info *info = iio_priv(indio_dev);
208*28e4b859SHans de Goede 	int ret;
209*28e4b859SHans de Goede 
210*28e4b859SHans de Goede 	if (mask == IIO_CHAN_INFO_SCALE)
211*28e4b859SHans de Goede 		return dc_ti_adc_scale(info, chan, val, val2);
212*28e4b859SHans de Goede 
213*28e4b859SHans de Goede 	guard(mutex)(&info->lock);
214*28e4b859SHans de Goede 
215*28e4b859SHans de Goede 	/*
216*28e4b859SHans de Goede 	 * If channel BPTHERM has been selected, first enable the BPTHERM BIAS
217*28e4b859SHans de Goede 	 * which provides the VREF Voltage reference to convert BPTHERM Input
218*28e4b859SHans de Goede 	 * voltage to temperature.
219*28e4b859SHans de Goede 	 */
220*28e4b859SHans de Goede 	if (chan->channel == DC_TI_ADC_BATTEMP) {
221*28e4b859SHans de Goede 		ret = regmap_set_bits(info->regmap, DC_TI_ADC_CNTL_REG,
222*28e4b859SHans de Goede 				      DC_TI_ADC_EN_EXT_BPTH_BIAS);
223*28e4b859SHans de Goede 		if (ret)
224*28e4b859SHans de Goede 			return ret;
225*28e4b859SHans de Goede 		/*
226*28e4b859SHans de Goede 		 * As per PMIC Vendor specifications, BPTHERM BIAS should be
227*28e4b859SHans de Goede 		 * enabled 35 ms before ADC_EN command.
228*28e4b859SHans de Goede 		 */
229*28e4b859SHans de Goede 		msleep(35);
230*28e4b859SHans de Goede 	}
231*28e4b859SHans de Goede 
232*28e4b859SHans de Goede 	ret = dc_ti_adc_sample(info, chan, val);
233*28e4b859SHans de Goede 
234*28e4b859SHans de Goede 	if (chan->channel == DC_TI_ADC_BATTEMP)
235*28e4b859SHans de Goede 		regmap_clear_bits(info->regmap, DC_TI_ADC_CNTL_REG,
236*28e4b859SHans de Goede 				  DC_TI_ADC_EN_EXT_BPTH_BIAS);
237*28e4b859SHans de Goede 
238*28e4b859SHans de Goede 	if (ret)
239*28e4b859SHans de Goede 		return ret;
240*28e4b859SHans de Goede 
241*28e4b859SHans de Goede 	switch (mask) {
242*28e4b859SHans de Goede 	case IIO_CHAN_INFO_RAW:
243*28e4b859SHans de Goede 		return IIO_VAL_INT;
244*28e4b859SHans de Goede 	case IIO_CHAN_INFO_PROCESSED:
245*28e4b859SHans de Goede 		return dc_ti_adc_raw_to_processed(info, chan, *val, val, val2);
246*28e4b859SHans de Goede 	}
247*28e4b859SHans de Goede 
248*28e4b859SHans de Goede 	return -EINVAL;
249*28e4b859SHans de Goede }
250*28e4b859SHans de Goede 
251*28e4b859SHans de Goede static const struct iio_info dc_ti_adc_iio_info = {
252*28e4b859SHans de Goede 	.read_raw = dc_ti_adc_read_raw,
253*28e4b859SHans de Goede };
254*28e4b859SHans de Goede 
255*28e4b859SHans de Goede static int dc_ti_adc_probe(struct platform_device *pdev)
256*28e4b859SHans de Goede {
257*28e4b859SHans de Goede 	struct device *dev = &pdev->dev;
258*28e4b859SHans de Goede 	struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent);
259*28e4b859SHans de Goede 	struct dc_ti_adc_info *info;
260*28e4b859SHans de Goede 	struct iio_dev *indio_dev;
261*28e4b859SHans de Goede 	unsigned int val;
262*28e4b859SHans de Goede 	int irq, ret;
263*28e4b859SHans de Goede 
264*28e4b859SHans de Goede 	irq = platform_get_irq(pdev, 0);
265*28e4b859SHans de Goede 	if (irq < 0)
266*28e4b859SHans de Goede 		return irq;
267*28e4b859SHans de Goede 
268*28e4b859SHans de Goede 	indio_dev = devm_iio_device_alloc(dev, sizeof(*info));
269*28e4b859SHans de Goede 	if (!indio_dev)
270*28e4b859SHans de Goede 		return -ENOMEM;
271*28e4b859SHans de Goede 
272*28e4b859SHans de Goede 	info = iio_priv(indio_dev);
273*28e4b859SHans de Goede 
274*28e4b859SHans de Goede 	ret = devm_mutex_init(dev, &info->lock);
275*28e4b859SHans de Goede 	if (ret)
276*28e4b859SHans de Goede 		return ret;
277*28e4b859SHans de Goede 
278*28e4b859SHans de Goede 	init_waitqueue_head(&info->wait);
279*28e4b859SHans de Goede 
280*28e4b859SHans de Goede 	info->dev = dev;
281*28e4b859SHans de Goede 	info->regmap = pmic->regmap;
282*28e4b859SHans de Goede 
283*28e4b859SHans de Goede 	indio_dev->name = "dc_ti_adc";
284*28e4b859SHans de Goede 	indio_dev->channels = dc_ti_adc_channels;
285*28e4b859SHans de Goede 	indio_dev->num_channels = ARRAY_SIZE(dc_ti_adc_channels);
286*28e4b859SHans de Goede 	indio_dev->info = &dc_ti_adc_iio_info;
287*28e4b859SHans de Goede 	indio_dev->modes = INDIO_DIRECT_MODE;
288*28e4b859SHans de Goede 
289*28e4b859SHans de Goede 	ret = regmap_read(info->regmap, DC_TI_VBAT_ZSE_GE_REG, &val);
290*28e4b859SHans de Goede 	if (ret)
291*28e4b859SHans de Goede 		return ret;
292*28e4b859SHans de Goede 
293*28e4b859SHans de Goede 	info->vbat_zse = sign_extend32(FIELD_GET(DC_TI_VBAT_ZSE, val), 3);
294*28e4b859SHans de Goede 	info->vbat_ge = sign_extend32(FIELD_GET(DC_TI_VBAT_GE, val), 3);
295*28e4b859SHans de Goede 
296*28e4b859SHans de Goede 	dev_dbg(dev, "vbat-zse %d vbat-ge %d\n", info->vbat_zse, info->vbat_ge);
297*28e4b859SHans de Goede 
298*28e4b859SHans de Goede 	ret = devm_iio_map_array_register(dev, indio_dev, dc_ti_adc_default_maps);
299*28e4b859SHans de Goede 	if (ret)
300*28e4b859SHans de Goede 		return ret;
301*28e4b859SHans de Goede 
302*28e4b859SHans de Goede 	ret = devm_request_threaded_irq(dev, irq, NULL, dc_ti_adc_isr,
303*28e4b859SHans de Goede 					IRQF_ONESHOT, indio_dev->name, info);
304*28e4b859SHans de Goede 	if (ret)
305*28e4b859SHans de Goede 		return ret;
306*28e4b859SHans de Goede 
307*28e4b859SHans de Goede 	return devm_iio_device_register(dev, indio_dev);
308*28e4b859SHans de Goede }
309*28e4b859SHans de Goede 
310*28e4b859SHans de Goede static const struct platform_device_id dc_ti_adc_ids[] = {
311*28e4b859SHans de Goede 	{ .name = "chtdc_ti_adc" },
312*28e4b859SHans de Goede 	{ }
313*28e4b859SHans de Goede };
314*28e4b859SHans de Goede MODULE_DEVICE_TABLE(platform, dc_ti_adc_ids);
315*28e4b859SHans de Goede 
316*28e4b859SHans de Goede static struct platform_driver dc_ti_adc_driver = {
317*28e4b859SHans de Goede 	.driver = {
318*28e4b859SHans de Goede 		.name	= "dc_ti_adc",
319*28e4b859SHans de Goede 	},
320*28e4b859SHans de Goede 	.probe		= dc_ti_adc_probe,
321*28e4b859SHans de Goede 	.id_table	= dc_ti_adc_ids,
322*28e4b859SHans de Goede };
323*28e4b859SHans de Goede module_platform_driver(dc_ti_adc_driver);
324*28e4b859SHans de Goede 
325*28e4b859SHans de Goede MODULE_AUTHOR("Ramakrishna Pallala (Intel)");
326*28e4b859SHans de Goede MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>");
327*28e4b859SHans de Goede MODULE_DESCRIPTION("Intel Dollar Cove (TI) GPADC Driver");
328*28e4b859SHans de Goede MODULE_LICENSE("GPL");
329