xref: /openbmc/linux/drivers/iio/adc/berlin2-adc.c (revision cbd3a015)
170f19379SAntoine Tenart /*
270f19379SAntoine Tenart  * Marvell Berlin2 ADC driver
370f19379SAntoine Tenart  *
470f19379SAntoine Tenart  * Copyright (C) 2015 Marvell Technology Group Ltd.
570f19379SAntoine Tenart  *
670f19379SAntoine Tenart  * Antoine Tenart <antoine.tenart@free-electrons.com>
770f19379SAntoine Tenart  *
870f19379SAntoine Tenart  * This file is licensed under the terms of the GNU General Public
970f19379SAntoine Tenart  * License version 2. This program is licensed "as is" without any
1070f19379SAntoine Tenart  * warranty of any kind, whether express or implied.
1170f19379SAntoine Tenart  */
1270f19379SAntoine Tenart 
1370f19379SAntoine Tenart #include <linux/iio/iio.h>
1470f19379SAntoine Tenart #include <linux/iio/driver.h>
1570f19379SAntoine Tenart #include <linux/iio/machine.h>
1670f19379SAntoine Tenart #include <linux/interrupt.h>
1770f19379SAntoine Tenart #include <linux/kernel.h>
1834de6b50SNuno Sá #include <linux/mod_devicetable.h>
1970f19379SAntoine Tenart #include <linux/module.h>
2034de6b50SNuno Sá #include <linux/of.h>
2170f19379SAntoine Tenart #include <linux/platform_device.h>
2270f19379SAntoine Tenart #include <linux/slab.h>
2370f19379SAntoine Tenart #include <linux/mfd/syscon.h>
2470f19379SAntoine Tenart #include <linux/regmap.h>
2570f19379SAntoine Tenart #include <linux/sched.h>
2670f19379SAntoine Tenart #include <linux/wait.h>
2770f19379SAntoine Tenart 
2870f19379SAntoine Tenart #define BERLIN2_SM_CTRL				0x14
2970f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_SM_SOC_INT		BIT(1)
3070f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_SOC_SM_INT		BIT(2)
3157cb0676SHartmut Knaack #define  BERLIN2_SM_CTRL_ADC_SEL(x)		((x) << 5)	/* 0-15 */
324b308e8cSHartmut Knaack #define  BERLIN2_SM_CTRL_ADC_SEL_MASK		GENMASK(8, 5)
3370f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_POWER		BIT(9)
3470f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2	(0x0 << 10)
3570f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV3	(0x1 << 10)
3670f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV4	(0x2 << 10)
3770f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV8	(0x3 << 10)
384b308e8cSHartmut Knaack #define  BERLIN2_SM_CTRL_ADC_CLKSEL_MASK	GENMASK(11, 10)
3970f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_START		BIT(12)
4070f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_RESET		BIT(13)
4170f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_BANDGAP_RDY	BIT(14)
4270f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_CONT_SINGLE	(0x0 << 15)
4370f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_CONT_CONTINUOUS	(0x1 << 15)
4470f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_BUFFER_EN		BIT(16)
4570f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_VREF_EXT		(0x0 << 17)
4670f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_VREF_INT		(0x1 << 17)
4770f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_ADC_ROTATE		BIT(19)
4870f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_TSEN_EN		BIT(20)
4970f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_TSEN_CLK_SEL_125	(0x0 << 21)	/* 1.25 MHz */
5070f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_TSEN_CLK_SEL_250	(0x1 << 21)	/* 2.5 MHz */
5170f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_TSEN_MODE_0_125	(0x0 << 22)	/* 0-125 C */
5270f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_TSEN_MODE_10_50	(0x1 << 22)	/* 10-50 C */
5370f19379SAntoine Tenart #define  BERLIN2_SM_CTRL_TSEN_RESET		BIT(29)
5470f19379SAntoine Tenart #define BERLIN2_SM_ADC_DATA			0x20
554b308e8cSHartmut Knaack #define  BERLIN2_SM_ADC_MASK			GENMASK(9, 0)
5670f19379SAntoine Tenart #define BERLIN2_SM_ADC_STATUS			0x1c
5770f19379SAntoine Tenart #define  BERLIN2_SM_ADC_STATUS_DATA_RDY(x)	BIT(x)		/* 0-15 */
5857cb0676SHartmut Knaack #define  BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK	GENMASK(15, 0)
5970f19379SAntoine Tenart #define  BERLIN2_SM_ADC_STATUS_INT_EN(x)	(BIT(x) << 16)	/* 0-15 */
6057cb0676SHartmut Knaack #define  BERLIN2_SM_ADC_STATUS_INT_EN_MASK	GENMASK(31, 16)
6170f19379SAntoine Tenart #define BERLIN2_SM_TSEN_STATUS			0x24
6270f19379SAntoine Tenart #define  BERLIN2_SM_TSEN_STATUS_DATA_RDY	BIT(0)
6370f19379SAntoine Tenart #define  BERLIN2_SM_TSEN_STATUS_INT_EN		BIT(1)
6470f19379SAntoine Tenart #define BERLIN2_SM_TSEN_DATA			0x28
6557cb0676SHartmut Knaack #define  BERLIN2_SM_TSEN_MASK			GENMASK(9, 0)
6670f19379SAntoine Tenart #define BERLIN2_SM_TSEN_CTRL			0x74
6770f19379SAntoine Tenart #define  BERLIN2_SM_TSEN_CTRL_START		BIT(8)
6870f19379SAntoine Tenart #define  BERLIN2_SM_TSEN_CTRL_SETTLING_4	(0x0 << 21)	/* 4 us */
6970f19379SAntoine Tenart #define  BERLIN2_SM_TSEN_CTRL_SETTLING_12	(0x1 << 21)	/* 12 us */
704b308e8cSHartmut Knaack #define  BERLIN2_SM_TSEN_CTRL_SETTLING_MASK	BIT(21)
7170f19379SAntoine Tenart #define  BERLIN2_SM_TSEN_CTRL_TRIM(x)		((x) << 22)
724b308e8cSHartmut Knaack #define  BERLIN2_SM_TSEN_CTRL_TRIM_MASK		GENMASK(25, 22)
7370f19379SAntoine Tenart 
7470f19379SAntoine Tenart struct berlin2_adc_priv {
7570f19379SAntoine Tenart 	struct regmap		*regmap;
7670f19379SAntoine Tenart 	struct mutex		lock;
7770f19379SAntoine Tenart 	wait_queue_head_t	wq;
7870f19379SAntoine Tenart 	bool			data_available;
7970f19379SAntoine Tenart 	int			data;
8070f19379SAntoine Tenart };
8170f19379SAntoine Tenart 
8270f19379SAntoine Tenart #define BERLIN2_ADC_CHANNEL(n, t)					\
8370f19379SAntoine Tenart 	{								\
8470f19379SAntoine Tenart 		.channel		= n,				\
8570f19379SAntoine Tenart 		.datasheet_name		= "channel"#n,			\
8670f19379SAntoine Tenart 		.type			= t,				\
8770f19379SAntoine Tenart 		.indexed		= 1,				\
8870f19379SAntoine Tenart 		.info_mask_separate	= BIT(IIO_CHAN_INFO_RAW),	\
8970f19379SAntoine Tenart 	}
9070f19379SAntoine Tenart 
91688febbdSHartmut Knaack static const struct iio_chan_spec berlin2_adc_channels[] = {
9270f19379SAntoine Tenart 	BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE),	/* external input */
9370f19379SAntoine Tenart 	BERLIN2_ADC_CHANNEL(1, IIO_VOLTAGE),	/* external input */
9470f19379SAntoine Tenart 	BERLIN2_ADC_CHANNEL(2, IIO_VOLTAGE),	/* external input */
9570f19379SAntoine Tenart 	BERLIN2_ADC_CHANNEL(3, IIO_VOLTAGE),	/* external input */
9670f19379SAntoine Tenart 	BERLIN2_ADC_CHANNEL(4, IIO_VOLTAGE),	/* reserved */
9770f19379SAntoine Tenart 	BERLIN2_ADC_CHANNEL(5, IIO_VOLTAGE),	/* reserved */
9870f19379SAntoine Tenart 	{					/* temperature sensor */
9970f19379SAntoine Tenart 		.channel		= 6,
10070f19379SAntoine Tenart 		.datasheet_name		= "channel6",
10170f19379SAntoine Tenart 		.type			= IIO_TEMP,
10270f19379SAntoine Tenart 		.indexed		= 0,
10370f19379SAntoine Tenart 		.info_mask_separate	= BIT(IIO_CHAN_INFO_PROCESSED),
10470f19379SAntoine Tenart 	},
10570f19379SAntoine Tenart 	BERLIN2_ADC_CHANNEL(7, IIO_VOLTAGE),	/* reserved */
10670f19379SAntoine Tenart 	IIO_CHAN_SOFT_TIMESTAMP(8),		/* timestamp */
10770f19379SAntoine Tenart };
10870f19379SAntoine Tenart 
berlin2_adc_read(struct iio_dev * indio_dev,int channel)10970f19379SAntoine Tenart static int berlin2_adc_read(struct iio_dev *indio_dev, int channel)
11070f19379SAntoine Tenart {
11170f19379SAntoine Tenart 	struct berlin2_adc_priv *priv = iio_priv(indio_dev);
11270f19379SAntoine Tenart 	int data, ret;
11370f19379SAntoine Tenart 
11470f19379SAntoine Tenart 	mutex_lock(&priv->lock);
11570f19379SAntoine Tenart 
1163ac06522SHartmut Knaack 	/* Enable the interrupts */
1173ac06522SHartmut Knaack 	regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS,
1183ac06522SHartmut Knaack 		     BERLIN2_SM_ADC_STATUS_INT_EN(channel));
1193ac06522SHartmut Knaack 
12070f19379SAntoine Tenart 	/* Configure the ADC */
12170f19379SAntoine Tenart 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
122b465fc54SHartmut Knaack 			   BERLIN2_SM_CTRL_ADC_RESET |
123b465fc54SHartmut Knaack 			   BERLIN2_SM_CTRL_ADC_SEL_MASK |
124b465fc54SHartmut Knaack 			   BERLIN2_SM_CTRL_ADC_START,
125b465fc54SHartmut Knaack 			   BERLIN2_SM_CTRL_ADC_SEL(channel) |
126b465fc54SHartmut Knaack 			   BERLIN2_SM_CTRL_ADC_START);
12770f19379SAntoine Tenart 
12870f19379SAntoine Tenart 	ret = wait_event_interruptible_timeout(priv->wq, priv->data_available,
12970f19379SAntoine Tenart 					       msecs_to_jiffies(1000));
13070f19379SAntoine Tenart 
13170f19379SAntoine Tenart 	/* Disable the interrupts */
13270f19379SAntoine Tenart 	regmap_update_bits(priv->regmap, BERLIN2_SM_ADC_STATUS,
13370f19379SAntoine Tenart 			   BERLIN2_SM_ADC_STATUS_INT_EN(channel), 0);
13470f19379SAntoine Tenart 
13570f19379SAntoine Tenart 	if (ret == 0)
13670f19379SAntoine Tenart 		ret = -ETIMEDOUT;
13770f19379SAntoine Tenart 	if (ret < 0) {
13870f19379SAntoine Tenart 		mutex_unlock(&priv->lock);
13970f19379SAntoine Tenart 		return ret;
14070f19379SAntoine Tenart 	}
14170f19379SAntoine Tenart 
14270f19379SAntoine Tenart 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
14370f19379SAntoine Tenart 			   BERLIN2_SM_CTRL_ADC_START, 0);
14470f19379SAntoine Tenart 
14570f19379SAntoine Tenart 	data = priv->data;
14670f19379SAntoine Tenart 	priv->data_available = false;
14770f19379SAntoine Tenart 
14870f19379SAntoine Tenart 	mutex_unlock(&priv->lock);
14970f19379SAntoine Tenart 
15070f19379SAntoine Tenart 	return data;
15170f19379SAntoine Tenart }
15270f19379SAntoine Tenart 
berlin2_adc_tsen_read(struct iio_dev * indio_dev)15370f19379SAntoine Tenart static int berlin2_adc_tsen_read(struct iio_dev *indio_dev)
15470f19379SAntoine Tenart {
15570f19379SAntoine Tenart 	struct berlin2_adc_priv *priv = iio_priv(indio_dev);
15670f19379SAntoine Tenart 	int data, ret;
15770f19379SAntoine Tenart 
15870f19379SAntoine Tenart 	mutex_lock(&priv->lock);
15970f19379SAntoine Tenart 
1603ac06522SHartmut Knaack 	/* Enable interrupts */
1613ac06522SHartmut Knaack 	regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS,
1623ac06522SHartmut Knaack 		     BERLIN2_SM_TSEN_STATUS_INT_EN);
1633ac06522SHartmut Knaack 
16470f19379SAntoine Tenart 	/* Configure the ADC */
16570f19379SAntoine Tenart 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
166b465fc54SHartmut Knaack 			   BERLIN2_SM_CTRL_TSEN_RESET |
167b465fc54SHartmut Knaack 			   BERLIN2_SM_CTRL_ADC_ROTATE,
16870f19379SAntoine Tenart 			   BERLIN2_SM_CTRL_ADC_ROTATE);
16970f19379SAntoine Tenart 
17070f19379SAntoine Tenart 	/* Configure the temperature sensor */
17170f19379SAntoine Tenart 	regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL,
172b465fc54SHartmut Knaack 			   BERLIN2_SM_TSEN_CTRL_TRIM_MASK |
173b465fc54SHartmut Knaack 			   BERLIN2_SM_TSEN_CTRL_SETTLING_MASK |
174b465fc54SHartmut Knaack 			   BERLIN2_SM_TSEN_CTRL_START,
175b465fc54SHartmut Knaack 			   BERLIN2_SM_TSEN_CTRL_TRIM(3) |
176b465fc54SHartmut Knaack 			   BERLIN2_SM_TSEN_CTRL_SETTLING_12 |
177b465fc54SHartmut Knaack 			   BERLIN2_SM_TSEN_CTRL_START);
17870f19379SAntoine Tenart 
17970f19379SAntoine Tenart 	ret = wait_event_interruptible_timeout(priv->wq, priv->data_available,
18070f19379SAntoine Tenart 					       msecs_to_jiffies(1000));
18170f19379SAntoine Tenart 
18270f19379SAntoine Tenart 	/* Disable interrupts */
18370f19379SAntoine Tenart 	regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_STATUS,
18470f19379SAntoine Tenart 			   BERLIN2_SM_TSEN_STATUS_INT_EN, 0);
18570f19379SAntoine Tenart 
18670f19379SAntoine Tenart 	if (ret == 0)
18770f19379SAntoine Tenart 		ret = -ETIMEDOUT;
18870f19379SAntoine Tenart 	if (ret < 0) {
18970f19379SAntoine Tenart 		mutex_unlock(&priv->lock);
19070f19379SAntoine Tenart 		return ret;
19170f19379SAntoine Tenart 	}
19270f19379SAntoine Tenart 
19370f19379SAntoine Tenart 	regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL,
19470f19379SAntoine Tenart 			   BERLIN2_SM_TSEN_CTRL_START, 0);
19570f19379SAntoine Tenart 
19670f19379SAntoine Tenart 	data = priv->data;
19770f19379SAntoine Tenart 	priv->data_available = false;
19870f19379SAntoine Tenart 
19970f19379SAntoine Tenart 	mutex_unlock(&priv->lock);
20070f19379SAntoine Tenart 
20170f19379SAntoine Tenart 	return data;
20270f19379SAntoine Tenart }
20370f19379SAntoine Tenart 
berlin2_adc_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)20470f19379SAntoine Tenart static int berlin2_adc_read_raw(struct iio_dev *indio_dev,
205b465fc54SHartmut Knaack 				struct iio_chan_spec const *chan, int *val,
206b465fc54SHartmut Knaack 				int *val2, long mask)
20770f19379SAntoine Tenart {
20870f19379SAntoine Tenart 	int temp;
20970f19379SAntoine Tenart 
21070f19379SAntoine Tenart 	switch (mask) {
21170f19379SAntoine Tenart 	case IIO_CHAN_INFO_RAW:
21270f19379SAntoine Tenart 		if (chan->type != IIO_VOLTAGE)
21370f19379SAntoine Tenart 			return -EINVAL;
21470f19379SAntoine Tenart 
21570f19379SAntoine Tenart 		*val = berlin2_adc_read(indio_dev, chan->channel);
21670f19379SAntoine Tenart 		if (*val < 0)
21770f19379SAntoine Tenart 			return *val;
21870f19379SAntoine Tenart 
21970f19379SAntoine Tenart 		return IIO_VAL_INT;
22070f19379SAntoine Tenart 	case IIO_CHAN_INFO_PROCESSED:
22170f19379SAntoine Tenart 		if (chan->type != IIO_TEMP)
22270f19379SAntoine Tenart 			return -EINVAL;
22370f19379SAntoine Tenart 
22470f19379SAntoine Tenart 		temp = berlin2_adc_tsen_read(indio_dev);
22570f19379SAntoine Tenart 		if (temp < 0)
22670f19379SAntoine Tenart 			return temp;
22770f19379SAntoine Tenart 
22870f19379SAntoine Tenart 		if (temp > 2047)
229609e9d88SHartmut Knaack 			temp -= 4096;
23070f19379SAntoine Tenart 
23170f19379SAntoine Tenart 		/* Convert to milli Celsius */
23270f19379SAntoine Tenart 		*val = ((temp * 100000) / 264 - 270000);
23370f19379SAntoine Tenart 		return IIO_VAL_INT;
23470f19379SAntoine Tenart 	default:
23570f19379SAntoine Tenart 		break;
23670f19379SAntoine Tenart 	}
23770f19379SAntoine Tenart 
23870f19379SAntoine Tenart 	return -EINVAL;
23970f19379SAntoine Tenart }
24070f19379SAntoine Tenart 
berlin2_adc_irq(int irq,void * private)24170f19379SAntoine Tenart static irqreturn_t berlin2_adc_irq(int irq, void *private)
24270f19379SAntoine Tenart {
24370f19379SAntoine Tenart 	struct berlin2_adc_priv *priv = iio_priv(private);
24470f19379SAntoine Tenart 	unsigned val;
24570f19379SAntoine Tenart 
24670f19379SAntoine Tenart 	regmap_read(priv->regmap, BERLIN2_SM_ADC_STATUS, &val);
24770f19379SAntoine Tenart 	if (val & BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK) {
24870f19379SAntoine Tenart 		regmap_read(priv->regmap, BERLIN2_SM_ADC_DATA, &priv->data);
24970f19379SAntoine Tenart 		priv->data &= BERLIN2_SM_ADC_MASK;
25070f19379SAntoine Tenart 
25170f19379SAntoine Tenart 		val &= ~BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK;
25270f19379SAntoine Tenart 		regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS, val);
25370f19379SAntoine Tenart 
25470f19379SAntoine Tenart 		priv->data_available = true;
25570f19379SAntoine Tenart 		wake_up_interruptible(&priv->wq);
25670f19379SAntoine Tenart 	}
25770f19379SAntoine Tenart 
25870f19379SAntoine Tenart 	return IRQ_HANDLED;
25970f19379SAntoine Tenart }
26070f19379SAntoine Tenart 
berlin2_adc_tsen_irq(int irq,void * private)26170f19379SAntoine Tenart static irqreturn_t berlin2_adc_tsen_irq(int irq, void *private)
26270f19379SAntoine Tenart {
26370f19379SAntoine Tenart 	struct berlin2_adc_priv *priv = iio_priv(private);
26470f19379SAntoine Tenart 	unsigned val;
26570f19379SAntoine Tenart 
26670f19379SAntoine Tenart 	regmap_read(priv->regmap, BERLIN2_SM_TSEN_STATUS, &val);
26770f19379SAntoine Tenart 	if (val & BERLIN2_SM_TSEN_STATUS_DATA_RDY) {
26870f19379SAntoine Tenart 		regmap_read(priv->regmap, BERLIN2_SM_TSEN_DATA, &priv->data);
26970f19379SAntoine Tenart 		priv->data &= BERLIN2_SM_TSEN_MASK;
27070f19379SAntoine Tenart 
27170f19379SAntoine Tenart 		val &= ~BERLIN2_SM_TSEN_STATUS_DATA_RDY;
27270f19379SAntoine Tenart 		regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS, val);
27370f19379SAntoine Tenart 
27470f19379SAntoine Tenart 		priv->data_available = true;
27570f19379SAntoine Tenart 		wake_up_interruptible(&priv->wq);
27670f19379SAntoine Tenart 	}
27770f19379SAntoine Tenart 
27870f19379SAntoine Tenart 	return IRQ_HANDLED;
27970f19379SAntoine Tenart }
28070f19379SAntoine Tenart 
28170f19379SAntoine Tenart static const struct iio_info berlin2_adc_info = {
28270f19379SAntoine Tenart 	.read_raw	= berlin2_adc_read_raw,
28370f19379SAntoine Tenart };
28470f19379SAntoine Tenart 
berlin2_adc_powerdown(void * regmap)285461a1c79SAlexandru Ardelean static void berlin2_adc_powerdown(void *regmap)
286461a1c79SAlexandru Ardelean {
287461a1c79SAlexandru Ardelean 	regmap_update_bits(regmap, BERLIN2_SM_CTRL,
288461a1c79SAlexandru Ardelean 			   BERLIN2_SM_CTRL_ADC_POWER, 0);
289461a1c79SAlexandru Ardelean 
290461a1c79SAlexandru Ardelean }
291461a1c79SAlexandru Ardelean 
berlin2_adc_probe(struct platform_device * pdev)29270f19379SAntoine Tenart static int berlin2_adc_probe(struct platform_device *pdev)
29370f19379SAntoine Tenart {
29470f19379SAntoine Tenart 	struct iio_dev *indio_dev;
29570f19379SAntoine Tenart 	struct berlin2_adc_priv *priv;
29670f19379SAntoine Tenart 	struct device_node *parent_np = of_get_parent(pdev->dev.of_node);
29770f19379SAntoine Tenart 	int irq, tsen_irq;
29870f19379SAntoine Tenart 	int ret;
29970f19379SAntoine Tenart 
300609e9d88SHartmut Knaack 	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
301*cbd3a015SXiongfeng Wang 	if (!indio_dev) {
302*cbd3a015SXiongfeng Wang 		of_node_put(parent_np);
30370f19379SAntoine Tenart 		return -ENOMEM;
304*cbd3a015SXiongfeng Wang 	}
30570f19379SAntoine Tenart 
30670f19379SAntoine Tenart 	priv = iio_priv(indio_dev);
30770f19379SAntoine Tenart 
30870f19379SAntoine Tenart 	priv->regmap = syscon_node_to_regmap(parent_np);
30970f19379SAntoine Tenart 	of_node_put(parent_np);
31070f19379SAntoine Tenart 	if (IS_ERR(priv->regmap))
31170f19379SAntoine Tenart 		return PTR_ERR(priv->regmap);
31270f19379SAntoine Tenart 
31370f19379SAntoine Tenart 	irq = platform_get_irq_byname(pdev, "adc");
31470f19379SAntoine Tenart 	if (irq < 0)
31519d56642SHartmut Knaack 		return irq;
31670f19379SAntoine Tenart 
31770f19379SAntoine Tenart 	tsen_irq = platform_get_irq_byname(pdev, "tsen");
31870f19379SAntoine Tenart 	if (tsen_irq < 0)
31919d56642SHartmut Knaack 		return tsen_irq;
32070f19379SAntoine Tenart 
32170f19379SAntoine Tenart 	ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0,
32270f19379SAntoine Tenart 			       pdev->dev.driver->name, indio_dev);
32370f19379SAntoine Tenart 	if (ret)
32470f19379SAntoine Tenart 		return ret;
32570f19379SAntoine Tenart 
32670f19379SAntoine Tenart 	ret = devm_request_irq(&pdev->dev, tsen_irq, berlin2_adc_tsen_irq,
32770f19379SAntoine Tenart 			       0, pdev->dev.driver->name, indio_dev);
32870f19379SAntoine Tenart 	if (ret)
32970f19379SAntoine Tenart 		return ret;
33070f19379SAntoine Tenart 
33170f19379SAntoine Tenart 	init_waitqueue_head(&priv->wq);
33270f19379SAntoine Tenart 	mutex_init(&priv->lock);
33370f19379SAntoine Tenart 
33470f19379SAntoine Tenart 	indio_dev->name = dev_name(&pdev->dev);
33570f19379SAntoine Tenart 	indio_dev->modes = INDIO_DIRECT_MODE;
33670f19379SAntoine Tenart 	indio_dev->info = &berlin2_adc_info;
33770f19379SAntoine Tenart 
33870f19379SAntoine Tenart 	indio_dev->channels = berlin2_adc_channels;
339546384c9SHartmut Knaack 	indio_dev->num_channels = ARRAY_SIZE(berlin2_adc_channels);
34070f19379SAntoine Tenart 
34170f19379SAntoine Tenart 	/* Power up the ADC */
34270f19379SAntoine Tenart 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
343b465fc54SHartmut Knaack 			   BERLIN2_SM_CTRL_ADC_POWER,
344b465fc54SHartmut Knaack 			   BERLIN2_SM_CTRL_ADC_POWER);
34570f19379SAntoine Tenart 
346461a1c79SAlexandru Ardelean 	ret = devm_add_action_or_reset(&pdev->dev, berlin2_adc_powerdown,
347461a1c79SAlexandru Ardelean 				       priv->regmap);
348461a1c79SAlexandru Ardelean 	if (ret)
34970f19379SAntoine Tenart 		return ret;
35070f19379SAntoine Tenart 
351461a1c79SAlexandru Ardelean 	return devm_iio_device_register(&pdev->dev, indio_dev);
35270f19379SAntoine Tenart }
35370f19379SAntoine Tenart 
35470f19379SAntoine Tenart static const struct of_device_id berlin2_adc_match[] = {
35570f19379SAntoine Tenart 	{ .compatible = "marvell,berlin2-adc", },
35670f19379SAntoine Tenart 	{ },
35770f19379SAntoine Tenart };
35870f19379SAntoine Tenart MODULE_DEVICE_TABLE(of, berlin2_adc_match);
35970f19379SAntoine Tenart 
36070f19379SAntoine Tenart static struct platform_driver berlin2_adc_driver = {
36170f19379SAntoine Tenart 	.driver	= {
36270f19379SAntoine Tenart 		.name		= "berlin2-adc",
36370f19379SAntoine Tenart 		.of_match_table	= berlin2_adc_match,
36470f19379SAntoine Tenart 	},
36570f19379SAntoine Tenart 	.probe	= berlin2_adc_probe,
36670f19379SAntoine Tenart };
36770f19379SAntoine Tenart module_platform_driver(berlin2_adc_driver);
36870f19379SAntoine Tenart 
36970f19379SAntoine Tenart MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
37070f19379SAntoine Tenart MODULE_DESCRIPTION("Marvell Berlin2 ADC driver");
37170f19379SAntoine Tenart MODULE_LICENSE("GPL v2");
372