xref: /openbmc/linux/drivers/iio/adc/npcm_adc.c (revision 9bf85fbc9d8f7fe927d47af886846c56ead6d2d3)
1*9bf85fbcSTomer Maimon // SPDX-License-Identifier: GPL-2.0
2*9bf85fbcSTomer Maimon // Copyright (c) 2019 Nuvoton Technology corporation.
3*9bf85fbcSTomer Maimon 
4*9bf85fbcSTomer Maimon #include <linux/clk.h>
5*9bf85fbcSTomer Maimon #include <linux/device.h>
6*9bf85fbcSTomer Maimon #include <linux/mfd/syscon.h>
7*9bf85fbcSTomer Maimon #include <linux/io.h>
8*9bf85fbcSTomer Maimon #include <linux/iio/iio.h>
9*9bf85fbcSTomer Maimon #include <linux/interrupt.h>
10*9bf85fbcSTomer Maimon #include <linux/kernel.h>
11*9bf85fbcSTomer Maimon #include <linux/module.h>
12*9bf85fbcSTomer Maimon #include <linux/platform_device.h>
13*9bf85fbcSTomer Maimon #include <linux/regmap.h>
14*9bf85fbcSTomer Maimon #include <linux/regulator/consumer.h>
15*9bf85fbcSTomer Maimon #include <linux/spinlock.h>
16*9bf85fbcSTomer Maimon #include <linux/uaccess.h>
17*9bf85fbcSTomer Maimon 
18*9bf85fbcSTomer Maimon struct npcm_adc {
19*9bf85fbcSTomer Maimon 	bool int_status;
20*9bf85fbcSTomer Maimon 	u32 adc_sample_hz;
21*9bf85fbcSTomer Maimon 	struct device *dev;
22*9bf85fbcSTomer Maimon 	void __iomem *regs;
23*9bf85fbcSTomer Maimon 	struct clk *adc_clk;
24*9bf85fbcSTomer Maimon 	wait_queue_head_t wq;
25*9bf85fbcSTomer Maimon 	struct regulator *vref;
26*9bf85fbcSTomer Maimon 	struct regmap *rst_regmap;
27*9bf85fbcSTomer Maimon };
28*9bf85fbcSTomer Maimon 
29*9bf85fbcSTomer Maimon /* NPCM7xx reset module */
30*9bf85fbcSTomer Maimon #define NPCM7XX_IPSRST1_OFFSET		0x020
31*9bf85fbcSTomer Maimon #define NPCM7XX_IPSRST1_ADC_RST		BIT(27)
32*9bf85fbcSTomer Maimon 
33*9bf85fbcSTomer Maimon /* ADC registers */
34*9bf85fbcSTomer Maimon #define NPCM_ADCCON	 0x00
35*9bf85fbcSTomer Maimon #define NPCM_ADCDATA	 0x04
36*9bf85fbcSTomer Maimon 
37*9bf85fbcSTomer Maimon /* ADCCON Register Bits */
38*9bf85fbcSTomer Maimon #define NPCM_ADCCON_ADC_INT_EN		BIT(21)
39*9bf85fbcSTomer Maimon #define NPCM_ADCCON_REFSEL		BIT(19)
40*9bf85fbcSTomer Maimon #define NPCM_ADCCON_ADC_INT_ST		BIT(18)
41*9bf85fbcSTomer Maimon #define NPCM_ADCCON_ADC_EN		BIT(17)
42*9bf85fbcSTomer Maimon #define NPCM_ADCCON_ADC_RST		BIT(16)
43*9bf85fbcSTomer Maimon #define NPCM_ADCCON_ADC_CONV		BIT(13)
44*9bf85fbcSTomer Maimon 
45*9bf85fbcSTomer Maimon #define NPCM_ADCCON_CH_MASK		GENMASK(27, 24)
46*9bf85fbcSTomer Maimon #define NPCM_ADCCON_CH(x)		((x) << 24)
47*9bf85fbcSTomer Maimon #define NPCM_ADCCON_DIV_SHIFT		1
48*9bf85fbcSTomer Maimon #define NPCM_ADCCON_DIV_MASK		GENMASK(8, 1)
49*9bf85fbcSTomer Maimon #define NPCM_ADC_DATA_MASK(x)		((x) & GENMASK(9, 0))
50*9bf85fbcSTomer Maimon 
51*9bf85fbcSTomer Maimon #define NPCM_ADC_ENABLE		(NPCM_ADCCON_ADC_EN | NPCM_ADCCON_ADC_INT_EN)
52*9bf85fbcSTomer Maimon 
53*9bf85fbcSTomer Maimon /* ADC General Definition */
54*9bf85fbcSTomer Maimon #define NPCM_RESOLUTION_BITS		10
55*9bf85fbcSTomer Maimon #define NPCM_INT_VREF_MV		2000
56*9bf85fbcSTomer Maimon 
57*9bf85fbcSTomer Maimon #define NPCM_ADC_CHAN(ch) {					\
58*9bf85fbcSTomer Maimon 	.type = IIO_VOLTAGE,					\
59*9bf85fbcSTomer Maimon 	.indexed = 1,						\
60*9bf85fbcSTomer Maimon 	.channel = ch,						\
61*9bf85fbcSTomer Maimon 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
62*9bf85fbcSTomer Maimon 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
63*9bf85fbcSTomer Maimon 				BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
64*9bf85fbcSTomer Maimon }
65*9bf85fbcSTomer Maimon 
66*9bf85fbcSTomer Maimon static const struct iio_chan_spec npcm_adc_iio_channels[] = {
67*9bf85fbcSTomer Maimon 	NPCM_ADC_CHAN(0),
68*9bf85fbcSTomer Maimon 	NPCM_ADC_CHAN(1),
69*9bf85fbcSTomer Maimon 	NPCM_ADC_CHAN(2),
70*9bf85fbcSTomer Maimon 	NPCM_ADC_CHAN(3),
71*9bf85fbcSTomer Maimon 	NPCM_ADC_CHAN(4),
72*9bf85fbcSTomer Maimon 	NPCM_ADC_CHAN(5),
73*9bf85fbcSTomer Maimon 	NPCM_ADC_CHAN(6),
74*9bf85fbcSTomer Maimon 	NPCM_ADC_CHAN(7),
75*9bf85fbcSTomer Maimon };
76*9bf85fbcSTomer Maimon 
77*9bf85fbcSTomer Maimon static irqreturn_t npcm_adc_isr(int irq, void *data)
78*9bf85fbcSTomer Maimon {
79*9bf85fbcSTomer Maimon 	u32 regtemp;
80*9bf85fbcSTomer Maimon 	struct iio_dev *indio_dev = data;
81*9bf85fbcSTomer Maimon 	struct npcm_adc *info = iio_priv(indio_dev);
82*9bf85fbcSTomer Maimon 
83*9bf85fbcSTomer Maimon 	regtemp = ioread32(info->regs + NPCM_ADCCON);
84*9bf85fbcSTomer Maimon 	if (regtemp & NPCM_ADCCON_ADC_INT_ST) {
85*9bf85fbcSTomer Maimon 		iowrite32(regtemp, info->regs + NPCM_ADCCON);
86*9bf85fbcSTomer Maimon 		wake_up_interruptible(&info->wq);
87*9bf85fbcSTomer Maimon 		info->int_status = true;
88*9bf85fbcSTomer Maimon 	}
89*9bf85fbcSTomer Maimon 
90*9bf85fbcSTomer Maimon 	return IRQ_HANDLED;
91*9bf85fbcSTomer Maimon }
92*9bf85fbcSTomer Maimon 
93*9bf85fbcSTomer Maimon static int npcm_adc_read(struct npcm_adc *info, int *val, u8 channel)
94*9bf85fbcSTomer Maimon {
95*9bf85fbcSTomer Maimon 	int ret;
96*9bf85fbcSTomer Maimon 	u32 regtemp;
97*9bf85fbcSTomer Maimon 
98*9bf85fbcSTomer Maimon 	/* Select ADC channel */
99*9bf85fbcSTomer Maimon 	regtemp = ioread32(info->regs + NPCM_ADCCON);
100*9bf85fbcSTomer Maimon 	regtemp &= ~NPCM_ADCCON_CH_MASK;
101*9bf85fbcSTomer Maimon 	info->int_status = false;
102*9bf85fbcSTomer Maimon 	iowrite32(regtemp | NPCM_ADCCON_CH(channel) |
103*9bf85fbcSTomer Maimon 		  NPCM_ADCCON_ADC_CONV, info->regs + NPCM_ADCCON);
104*9bf85fbcSTomer Maimon 
105*9bf85fbcSTomer Maimon 	ret = wait_event_interruptible_timeout(info->wq, info->int_status,
106*9bf85fbcSTomer Maimon 					       msecs_to_jiffies(10));
107*9bf85fbcSTomer Maimon 	if (ret == 0) {
108*9bf85fbcSTomer Maimon 		regtemp = ioread32(info->regs + NPCM_ADCCON);
109*9bf85fbcSTomer Maimon 		if ((regtemp & NPCM_ADCCON_ADC_CONV) && info->rst_regmap) {
110*9bf85fbcSTomer Maimon 			/* if conversion failed - reset ADC module */
111*9bf85fbcSTomer Maimon 			regmap_write(info->rst_regmap, NPCM7XX_IPSRST1_OFFSET,
112*9bf85fbcSTomer Maimon 				     NPCM7XX_IPSRST1_ADC_RST);
113*9bf85fbcSTomer Maimon 			msleep(100);
114*9bf85fbcSTomer Maimon 			regmap_write(info->rst_regmap, NPCM7XX_IPSRST1_OFFSET,
115*9bf85fbcSTomer Maimon 				     0x0);
116*9bf85fbcSTomer Maimon 			msleep(100);
117*9bf85fbcSTomer Maimon 
118*9bf85fbcSTomer Maimon 			/* Enable ADC and start conversion module */
119*9bf85fbcSTomer Maimon 			iowrite32(NPCM_ADC_ENABLE | NPCM_ADCCON_ADC_CONV,
120*9bf85fbcSTomer Maimon 				  info->regs + NPCM_ADCCON);
121*9bf85fbcSTomer Maimon 			dev_err(info->dev, "RESET ADC Complete\n");
122*9bf85fbcSTomer Maimon 		}
123*9bf85fbcSTomer Maimon 		return -ETIMEDOUT;
124*9bf85fbcSTomer Maimon 	}
125*9bf85fbcSTomer Maimon 	if (ret < 0)
126*9bf85fbcSTomer Maimon 		return ret;
127*9bf85fbcSTomer Maimon 
128*9bf85fbcSTomer Maimon 	*val = NPCM_ADC_DATA_MASK(ioread32(info->regs + NPCM_ADCDATA));
129*9bf85fbcSTomer Maimon 
130*9bf85fbcSTomer Maimon 	return 0;
131*9bf85fbcSTomer Maimon }
132*9bf85fbcSTomer Maimon 
133*9bf85fbcSTomer Maimon static int npcm_adc_read_raw(struct iio_dev *indio_dev,
134*9bf85fbcSTomer Maimon 			     struct iio_chan_spec const *chan, int *val,
135*9bf85fbcSTomer Maimon 			     int *val2, long mask)
136*9bf85fbcSTomer Maimon {
137*9bf85fbcSTomer Maimon 	int ret;
138*9bf85fbcSTomer Maimon 	int vref_uv;
139*9bf85fbcSTomer Maimon 	struct npcm_adc *info = iio_priv(indio_dev);
140*9bf85fbcSTomer Maimon 
141*9bf85fbcSTomer Maimon 	switch (mask) {
142*9bf85fbcSTomer Maimon 	case IIO_CHAN_INFO_RAW:
143*9bf85fbcSTomer Maimon 		mutex_lock(&indio_dev->mlock);
144*9bf85fbcSTomer Maimon 		ret = npcm_adc_read(info, val, chan->channel);
145*9bf85fbcSTomer Maimon 		mutex_unlock(&indio_dev->mlock);
146*9bf85fbcSTomer Maimon 		if (ret) {
147*9bf85fbcSTomer Maimon 			dev_err(info->dev, "NPCM ADC read failed\n");
148*9bf85fbcSTomer Maimon 			return ret;
149*9bf85fbcSTomer Maimon 		}
150*9bf85fbcSTomer Maimon 		return IIO_VAL_INT;
151*9bf85fbcSTomer Maimon 	case IIO_CHAN_INFO_SCALE:
152*9bf85fbcSTomer Maimon 		if (info->vref) {
153*9bf85fbcSTomer Maimon 			vref_uv = regulator_get_voltage(info->vref);
154*9bf85fbcSTomer Maimon 			*val = vref_uv / 1000;
155*9bf85fbcSTomer Maimon 		} else {
156*9bf85fbcSTomer Maimon 			*val = NPCM_INT_VREF_MV;
157*9bf85fbcSTomer Maimon 		}
158*9bf85fbcSTomer Maimon 		*val2 = NPCM_RESOLUTION_BITS;
159*9bf85fbcSTomer Maimon 		return IIO_VAL_FRACTIONAL_LOG2;
160*9bf85fbcSTomer Maimon 	case IIO_CHAN_INFO_SAMP_FREQ:
161*9bf85fbcSTomer Maimon 		*val = info->adc_sample_hz;
162*9bf85fbcSTomer Maimon 		return IIO_VAL_INT;
163*9bf85fbcSTomer Maimon 	default:
164*9bf85fbcSTomer Maimon 		return -EINVAL;
165*9bf85fbcSTomer Maimon 	}
166*9bf85fbcSTomer Maimon 
167*9bf85fbcSTomer Maimon 	return 0;
168*9bf85fbcSTomer Maimon }
169*9bf85fbcSTomer Maimon 
170*9bf85fbcSTomer Maimon static const struct iio_info npcm_adc_iio_info = {
171*9bf85fbcSTomer Maimon 	.read_raw = &npcm_adc_read_raw,
172*9bf85fbcSTomer Maimon };
173*9bf85fbcSTomer Maimon 
174*9bf85fbcSTomer Maimon static const struct of_device_id npcm_adc_match[] = {
175*9bf85fbcSTomer Maimon 	{ .compatible = "nuvoton,npcm750-adc", },
176*9bf85fbcSTomer Maimon 	{ /* sentinel */ }
177*9bf85fbcSTomer Maimon };
178*9bf85fbcSTomer Maimon MODULE_DEVICE_TABLE(of, npcm_adc_match);
179*9bf85fbcSTomer Maimon 
180*9bf85fbcSTomer Maimon static int npcm_adc_probe(struct platform_device *pdev)
181*9bf85fbcSTomer Maimon {
182*9bf85fbcSTomer Maimon 	int ret;
183*9bf85fbcSTomer Maimon 	int irq;
184*9bf85fbcSTomer Maimon 	u32 div;
185*9bf85fbcSTomer Maimon 	u32 reg_con;
186*9bf85fbcSTomer Maimon 	struct resource *res;
187*9bf85fbcSTomer Maimon 	struct npcm_adc *info;
188*9bf85fbcSTomer Maimon 	struct iio_dev *indio_dev;
189*9bf85fbcSTomer Maimon 	struct device *dev = &pdev->dev;
190*9bf85fbcSTomer Maimon 	struct device_node *np = pdev->dev.of_node;
191*9bf85fbcSTomer Maimon 
192*9bf85fbcSTomer Maimon 	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
193*9bf85fbcSTomer Maimon 	if (!indio_dev)
194*9bf85fbcSTomer Maimon 		return -ENOMEM;
195*9bf85fbcSTomer Maimon 	info = iio_priv(indio_dev);
196*9bf85fbcSTomer Maimon 
197*9bf85fbcSTomer Maimon 	info->dev = &pdev->dev;
198*9bf85fbcSTomer Maimon 
199*9bf85fbcSTomer Maimon 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
200*9bf85fbcSTomer Maimon 	info->regs = devm_ioremap_resource(&pdev->dev, res);
201*9bf85fbcSTomer Maimon 	if (IS_ERR(info->regs))
202*9bf85fbcSTomer Maimon 		return PTR_ERR(info->regs);
203*9bf85fbcSTomer Maimon 
204*9bf85fbcSTomer Maimon 	info->adc_clk = devm_clk_get(&pdev->dev, NULL);
205*9bf85fbcSTomer Maimon 	if (IS_ERR(info->adc_clk)) {
206*9bf85fbcSTomer Maimon 		dev_warn(&pdev->dev, "ADC clock failed: can't read clk\n");
207*9bf85fbcSTomer Maimon 		return PTR_ERR(info->adc_clk);
208*9bf85fbcSTomer Maimon 	}
209*9bf85fbcSTomer Maimon 
210*9bf85fbcSTomer Maimon 	/* calculate ADC clock sample rate */
211*9bf85fbcSTomer Maimon 	reg_con = ioread32(info->regs + NPCM_ADCCON);
212*9bf85fbcSTomer Maimon 	div = reg_con & NPCM_ADCCON_DIV_MASK;
213*9bf85fbcSTomer Maimon 	div = div >> NPCM_ADCCON_DIV_SHIFT;
214*9bf85fbcSTomer Maimon 	info->adc_sample_hz = clk_get_rate(info->adc_clk) / ((div + 1) * 2);
215*9bf85fbcSTomer Maimon 
216*9bf85fbcSTomer Maimon 	if (of_device_is_compatible(np, "nuvoton,npcm750-adc")) {
217*9bf85fbcSTomer Maimon 		info->rst_regmap = syscon_regmap_lookup_by_compatible
218*9bf85fbcSTomer Maimon 			("nuvoton,npcm750-rst");
219*9bf85fbcSTomer Maimon 		if (IS_ERR(info->rst_regmap)) {
220*9bf85fbcSTomer Maimon 			dev_err(&pdev->dev, "Failed to find nuvoton,npcm750-rst\n");
221*9bf85fbcSTomer Maimon 			ret = PTR_ERR(info->rst_regmap);
222*9bf85fbcSTomer Maimon 			goto err_disable_clk;
223*9bf85fbcSTomer Maimon 		}
224*9bf85fbcSTomer Maimon 	}
225*9bf85fbcSTomer Maimon 
226*9bf85fbcSTomer Maimon 	irq = platform_get_irq(pdev, 0);
227*9bf85fbcSTomer Maimon 	if (irq <= 0) {
228*9bf85fbcSTomer Maimon 		dev_err(dev, "failed getting interrupt resource\n");
229*9bf85fbcSTomer Maimon 		ret = -EINVAL;
230*9bf85fbcSTomer Maimon 		goto err_disable_clk;
231*9bf85fbcSTomer Maimon 	}
232*9bf85fbcSTomer Maimon 
233*9bf85fbcSTomer Maimon 	ret = devm_request_irq(&pdev->dev, irq, npcm_adc_isr, 0,
234*9bf85fbcSTomer Maimon 			       "NPCM_ADC", indio_dev);
235*9bf85fbcSTomer Maimon 	if (ret < 0) {
236*9bf85fbcSTomer Maimon 		dev_err(dev, "failed requesting interrupt\n");
237*9bf85fbcSTomer Maimon 		goto err_disable_clk;
238*9bf85fbcSTomer Maimon 	}
239*9bf85fbcSTomer Maimon 
240*9bf85fbcSTomer Maimon 	reg_con = ioread32(info->regs + NPCM_ADCCON);
241*9bf85fbcSTomer Maimon 	info->vref = devm_regulator_get_optional(&pdev->dev, "vref");
242*9bf85fbcSTomer Maimon 	if (!IS_ERR(info->vref)) {
243*9bf85fbcSTomer Maimon 		ret = regulator_enable(info->vref);
244*9bf85fbcSTomer Maimon 		if (ret) {
245*9bf85fbcSTomer Maimon 			dev_err(&pdev->dev, "Can't enable ADC reference voltage\n");
246*9bf85fbcSTomer Maimon 			goto err_disable_clk;
247*9bf85fbcSTomer Maimon 		}
248*9bf85fbcSTomer Maimon 
249*9bf85fbcSTomer Maimon 		iowrite32(reg_con & ~NPCM_ADCCON_REFSEL,
250*9bf85fbcSTomer Maimon 			  info->regs + NPCM_ADCCON);
251*9bf85fbcSTomer Maimon 	} else {
252*9bf85fbcSTomer Maimon 		/*
253*9bf85fbcSTomer Maimon 		 * Any error which is not ENODEV indicates the regulator
254*9bf85fbcSTomer Maimon 		 * has been specified and so is a failure case.
255*9bf85fbcSTomer Maimon 		 */
256*9bf85fbcSTomer Maimon 		if (PTR_ERR(info->vref) != -ENODEV) {
257*9bf85fbcSTomer Maimon 			ret = PTR_ERR(info->vref);
258*9bf85fbcSTomer Maimon 			goto err_disable_clk;
259*9bf85fbcSTomer Maimon 		}
260*9bf85fbcSTomer Maimon 
261*9bf85fbcSTomer Maimon 		/* Use internal reference */
262*9bf85fbcSTomer Maimon 		iowrite32(reg_con | NPCM_ADCCON_REFSEL,
263*9bf85fbcSTomer Maimon 			  info->regs + NPCM_ADCCON);
264*9bf85fbcSTomer Maimon 	}
265*9bf85fbcSTomer Maimon 
266*9bf85fbcSTomer Maimon 	init_waitqueue_head(&info->wq);
267*9bf85fbcSTomer Maimon 
268*9bf85fbcSTomer Maimon 	reg_con = ioread32(info->regs + NPCM_ADCCON);
269*9bf85fbcSTomer Maimon 	reg_con |= NPCM_ADC_ENABLE;
270*9bf85fbcSTomer Maimon 
271*9bf85fbcSTomer Maimon 	/* Enable the ADC Module */
272*9bf85fbcSTomer Maimon 	iowrite32(reg_con, info->regs + NPCM_ADCCON);
273*9bf85fbcSTomer Maimon 
274*9bf85fbcSTomer Maimon 	/* Start ADC conversion */
275*9bf85fbcSTomer Maimon 	iowrite32(reg_con | NPCM_ADCCON_ADC_CONV, info->regs + NPCM_ADCCON);
276*9bf85fbcSTomer Maimon 
277*9bf85fbcSTomer Maimon 	platform_set_drvdata(pdev, indio_dev);
278*9bf85fbcSTomer Maimon 	indio_dev->name = dev_name(&pdev->dev);
279*9bf85fbcSTomer Maimon 	indio_dev->dev.parent = &pdev->dev;
280*9bf85fbcSTomer Maimon 	indio_dev->info = &npcm_adc_iio_info;
281*9bf85fbcSTomer Maimon 	indio_dev->modes = INDIO_DIRECT_MODE;
282*9bf85fbcSTomer Maimon 	indio_dev->channels = npcm_adc_iio_channels;
283*9bf85fbcSTomer Maimon 	indio_dev->num_channels = ARRAY_SIZE(npcm_adc_iio_channels);
284*9bf85fbcSTomer Maimon 
285*9bf85fbcSTomer Maimon 	ret = iio_device_register(indio_dev);
286*9bf85fbcSTomer Maimon 	if (ret) {
287*9bf85fbcSTomer Maimon 		dev_err(&pdev->dev, "Couldn't register the device.\n");
288*9bf85fbcSTomer Maimon 		goto err_iio_register;
289*9bf85fbcSTomer Maimon 	}
290*9bf85fbcSTomer Maimon 
291*9bf85fbcSTomer Maimon 	pr_info("NPCM ADC driver probed\n");
292*9bf85fbcSTomer Maimon 
293*9bf85fbcSTomer Maimon 	return 0;
294*9bf85fbcSTomer Maimon 
295*9bf85fbcSTomer Maimon err_iio_register:
296*9bf85fbcSTomer Maimon 	iowrite32(reg_con & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON);
297*9bf85fbcSTomer Maimon 	if (!IS_ERR(info->vref))
298*9bf85fbcSTomer Maimon 		regulator_disable(info->vref);
299*9bf85fbcSTomer Maimon err_disable_clk:
300*9bf85fbcSTomer Maimon 	clk_disable_unprepare(info->adc_clk);
301*9bf85fbcSTomer Maimon 
302*9bf85fbcSTomer Maimon 	return ret;
303*9bf85fbcSTomer Maimon }
304*9bf85fbcSTomer Maimon 
305*9bf85fbcSTomer Maimon static int npcm_adc_remove(struct platform_device *pdev)
306*9bf85fbcSTomer Maimon {
307*9bf85fbcSTomer Maimon 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
308*9bf85fbcSTomer Maimon 	struct npcm_adc *info = iio_priv(indio_dev);
309*9bf85fbcSTomer Maimon 	u32 regtemp;
310*9bf85fbcSTomer Maimon 
311*9bf85fbcSTomer Maimon 	iio_device_unregister(indio_dev);
312*9bf85fbcSTomer Maimon 
313*9bf85fbcSTomer Maimon 	regtemp = ioread32(info->regs + NPCM_ADCCON);
314*9bf85fbcSTomer Maimon 	iowrite32(regtemp & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON);
315*9bf85fbcSTomer Maimon 	if (!IS_ERR(info->vref))
316*9bf85fbcSTomer Maimon 		regulator_disable(info->vref);
317*9bf85fbcSTomer Maimon 	clk_disable_unprepare(info->adc_clk);
318*9bf85fbcSTomer Maimon 
319*9bf85fbcSTomer Maimon 	return 0;
320*9bf85fbcSTomer Maimon }
321*9bf85fbcSTomer Maimon 
322*9bf85fbcSTomer Maimon static struct platform_driver npcm_adc_driver = {
323*9bf85fbcSTomer Maimon 	.probe		= npcm_adc_probe,
324*9bf85fbcSTomer Maimon 	.remove		= npcm_adc_remove,
325*9bf85fbcSTomer Maimon 	.driver		= {
326*9bf85fbcSTomer Maimon 		.name	= "npcm_adc",
327*9bf85fbcSTomer Maimon 		.of_match_table = npcm_adc_match,
328*9bf85fbcSTomer Maimon 	},
329*9bf85fbcSTomer Maimon };
330*9bf85fbcSTomer Maimon 
331*9bf85fbcSTomer Maimon module_platform_driver(npcm_adc_driver);
332*9bf85fbcSTomer Maimon 
333*9bf85fbcSTomer Maimon MODULE_DESCRIPTION("Nuvoton NPCM ADC Driver");
334*9bf85fbcSTomer Maimon MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
335*9bf85fbcSTomer Maimon MODULE_LICENSE("GPL v2");
336