xref: /openbmc/linux/drivers/iio/adc/rcar-gyroadc.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1efeb87d8SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0+
2059c53b3SMarek Vasut /*
3059c53b3SMarek Vasut  * Renesas R-Car GyroADC driver
4059c53b3SMarek Vasut  *
5059c53b3SMarek Vasut  * Copyright 2016 Marek Vasut <marek.vasut@gmail.com>
6059c53b3SMarek Vasut  */
7059c53b3SMarek Vasut 
8059c53b3SMarek Vasut #include <linux/module.h>
9059c53b3SMarek Vasut #include <linux/platform_device.h>
10059c53b3SMarek Vasut #include <linux/delay.h>
11059c53b3SMarek Vasut #include <linux/kernel.h>
12059c53b3SMarek Vasut #include <linux/slab.h>
13059c53b3SMarek Vasut #include <linux/io.h>
14059c53b3SMarek Vasut #include <linux/clk.h>
15059c53b3SMarek Vasut #include <linux/of.h>
16059c53b3SMarek Vasut #include <linux/of_irq.h>
17059c53b3SMarek Vasut #include <linux/regulator/consumer.h>
18059c53b3SMarek Vasut #include <linux/of_platform.h>
19059c53b3SMarek Vasut #include <linux/err.h>
20059c53b3SMarek Vasut #include <linux/pm_runtime.h>
21059c53b3SMarek Vasut 
22059c53b3SMarek Vasut #include <linux/iio/iio.h>
23059c53b3SMarek Vasut #include <linux/iio/sysfs.h>
24059c53b3SMarek Vasut #include <linux/iio/trigger.h>
25059c53b3SMarek Vasut 
26059c53b3SMarek Vasut #define DRIVER_NAME				"rcar-gyroadc"
27059c53b3SMarek Vasut 
28059c53b3SMarek Vasut /* GyroADC registers. */
29059c53b3SMarek Vasut #define RCAR_GYROADC_MODE_SELECT		0x00
30059c53b3SMarek Vasut #define RCAR_GYROADC_MODE_SELECT_1_MB88101A	0x0
31059c53b3SMarek Vasut #define RCAR_GYROADC_MODE_SELECT_2_ADCS7476	0x1
32059c53b3SMarek Vasut #define RCAR_GYROADC_MODE_SELECT_3_MAX1162	0x3
33059c53b3SMarek Vasut 
34059c53b3SMarek Vasut #define RCAR_GYROADC_START_STOP			0x04
35059c53b3SMarek Vasut #define RCAR_GYROADC_START_STOP_START		BIT(0)
36059c53b3SMarek Vasut 
37059c53b3SMarek Vasut #define RCAR_GYROADC_CLOCK_LENGTH		0x08
38059c53b3SMarek Vasut #define RCAR_GYROADC_1_25MS_LENGTH		0x0c
39059c53b3SMarek Vasut 
40059c53b3SMarek Vasut #define RCAR_GYROADC_REALTIME_DATA(ch)		(0x10 + ((ch) * 4))
41059c53b3SMarek Vasut #define RCAR_GYROADC_100MS_ADDED_DATA(ch)	(0x30 + ((ch) * 4))
42059c53b3SMarek Vasut #define RCAR_GYROADC_10MS_AVG_DATA(ch)		(0x50 + ((ch) * 4))
43059c53b3SMarek Vasut 
44059c53b3SMarek Vasut #define RCAR_GYROADC_FIFO_STATUS		0x70
45059c53b3SMarek Vasut #define RCAR_GYROADC_FIFO_STATUS_EMPTY(ch)	BIT(0 + (4 * (ch)))
46059c53b3SMarek Vasut #define RCAR_GYROADC_FIFO_STATUS_FULL(ch)	BIT(1 + (4 * (ch)))
47059c53b3SMarek Vasut #define RCAR_GYROADC_FIFO_STATUS_ERROR(ch)	BIT(2 + (4 * (ch)))
48059c53b3SMarek Vasut 
49059c53b3SMarek Vasut #define RCAR_GYROADC_INTR			0x74
50059c53b3SMarek Vasut #define RCAR_GYROADC_INTR_INT			BIT(0)
51059c53b3SMarek Vasut 
52059c53b3SMarek Vasut #define RCAR_GYROADC_INTENR			0x78
53059c53b3SMarek Vasut #define RCAR_GYROADC_INTENR_INTEN		BIT(0)
54059c53b3SMarek Vasut 
55059c53b3SMarek Vasut #define RCAR_GYROADC_SAMPLE_RATE		800	/* Hz */
56059c53b3SMarek Vasut 
57059c53b3SMarek Vasut #define RCAR_GYROADC_RUNTIME_PM_DELAY_MS	2000
58059c53b3SMarek Vasut 
59059c53b3SMarek Vasut enum rcar_gyroadc_model {
60059c53b3SMarek Vasut 	RCAR_GYROADC_MODEL_DEFAULT,
61059c53b3SMarek Vasut 	RCAR_GYROADC_MODEL_R8A7792,
62059c53b3SMarek Vasut };
63059c53b3SMarek Vasut 
64059c53b3SMarek Vasut struct rcar_gyroadc {
65059c53b3SMarek Vasut 	struct device			*dev;
66059c53b3SMarek Vasut 	void __iomem			*regs;
671a732f42SMarek Vasut 	struct clk			*clk;
68059c53b3SMarek Vasut 	struct regulator		*vref[8];
69059c53b3SMarek Vasut 	unsigned int			num_channels;
70059c53b3SMarek Vasut 	enum rcar_gyroadc_model		model;
71059c53b3SMarek Vasut 	unsigned int			mode;
72059c53b3SMarek Vasut 	unsigned int			sample_width;
73059c53b3SMarek Vasut };
74059c53b3SMarek Vasut 
rcar_gyroadc_hw_init(struct rcar_gyroadc * priv)75059c53b3SMarek Vasut static void rcar_gyroadc_hw_init(struct rcar_gyroadc *priv)
76059c53b3SMarek Vasut {
771a732f42SMarek Vasut 	const unsigned long clk_mhz = clk_get_rate(priv->clk) / 1000000;
78059c53b3SMarek Vasut 	const unsigned long clk_mul =
79059c53b3SMarek Vasut 		(priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) ? 10 : 5;
80059c53b3SMarek Vasut 	unsigned long clk_len = clk_mhz * clk_mul;
81059c53b3SMarek Vasut 
82059c53b3SMarek Vasut 	/*
83059c53b3SMarek Vasut 	 * According to the R-Car Gen2 datasheet Rev. 1.01, Sept 08 2014,
84059c53b3SMarek Vasut 	 * page 77-7, clock length must be even number. If it's odd number,
85059c53b3SMarek Vasut 	 * add one.
86059c53b3SMarek Vasut 	 */
87059c53b3SMarek Vasut 	if (clk_len & 1)
88059c53b3SMarek Vasut 		clk_len++;
89059c53b3SMarek Vasut 
90059c53b3SMarek Vasut 	/* Stop the GyroADC. */
91059c53b3SMarek Vasut 	writel(0, priv->regs + RCAR_GYROADC_START_STOP);
92059c53b3SMarek Vasut 
93059c53b3SMarek Vasut 	/* Disable IRQ on V2H. */
94059c53b3SMarek Vasut 	if (priv->model == RCAR_GYROADC_MODEL_R8A7792)
95059c53b3SMarek Vasut 		writel(0, priv->regs + RCAR_GYROADC_INTENR);
96059c53b3SMarek Vasut 
97059c53b3SMarek Vasut 	/* Set mode and timing. */
98059c53b3SMarek Vasut 	writel(priv->mode, priv->regs + RCAR_GYROADC_MODE_SELECT);
99059c53b3SMarek Vasut 	writel(clk_len, priv->regs + RCAR_GYROADC_CLOCK_LENGTH);
100059c53b3SMarek Vasut 	writel(clk_mhz * 1250, priv->regs + RCAR_GYROADC_1_25MS_LENGTH);
101059c53b3SMarek Vasut }
102059c53b3SMarek Vasut 
rcar_gyroadc_hw_start(struct rcar_gyroadc * priv)103059c53b3SMarek Vasut static void rcar_gyroadc_hw_start(struct rcar_gyroadc *priv)
104059c53b3SMarek Vasut {
105059c53b3SMarek Vasut 	/* Start sampling. */
106059c53b3SMarek Vasut 	writel(RCAR_GYROADC_START_STOP_START,
107059c53b3SMarek Vasut 	       priv->regs + RCAR_GYROADC_START_STOP);
108059c53b3SMarek Vasut 
109059c53b3SMarek Vasut 	/*
110059c53b3SMarek Vasut 	 * Wait for the first conversion to complete. This is longer than
111059c53b3SMarek Vasut 	 * the 1.25 mS in the datasheet because 1.25 mS is not enough for
112059c53b3SMarek Vasut 	 * the hardware to deliver the first sample and the hardware does
113059c53b3SMarek Vasut 	 * then return zeroes instead of valid data.
114059c53b3SMarek Vasut 	 */
115059c53b3SMarek Vasut 	mdelay(3);
116059c53b3SMarek Vasut }
117059c53b3SMarek Vasut 
rcar_gyroadc_hw_stop(struct rcar_gyroadc * priv)118059c53b3SMarek Vasut static void rcar_gyroadc_hw_stop(struct rcar_gyroadc *priv)
119059c53b3SMarek Vasut {
120059c53b3SMarek Vasut 	/* Stop the GyroADC. */
121059c53b3SMarek Vasut 	writel(0, priv->regs + RCAR_GYROADC_START_STOP);
122059c53b3SMarek Vasut }
123059c53b3SMarek Vasut 
124059c53b3SMarek Vasut #define RCAR_GYROADC_CHAN(_idx) {				\
125059c53b3SMarek Vasut 	.type			= IIO_VOLTAGE,			\
126059c53b3SMarek Vasut 	.indexed		= 1,				\
127059c53b3SMarek Vasut 	.channel		= (_idx),			\
128059c53b3SMarek Vasut 	.info_mask_separate	= BIT(IIO_CHAN_INFO_RAW) |	\
129059c53b3SMarek Vasut 				  BIT(IIO_CHAN_INFO_SCALE),	\
130059c53b3SMarek Vasut 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
131059c53b3SMarek Vasut }
132059c53b3SMarek Vasut 
133059c53b3SMarek Vasut static const struct iio_chan_spec rcar_gyroadc_iio_channels_1[] = {
134059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(0),
135059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(1),
136059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(2),
137059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(3),
138059c53b3SMarek Vasut };
139059c53b3SMarek Vasut 
140059c53b3SMarek Vasut static const struct iio_chan_spec rcar_gyroadc_iio_channels_2[] = {
141059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(0),
142059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(1),
143059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(2),
144059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(3),
145059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(4),
146059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(5),
147059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(6),
148059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(7),
149059c53b3SMarek Vasut };
150059c53b3SMarek Vasut 
151059c53b3SMarek Vasut static const struct iio_chan_spec rcar_gyroadc_iio_channels_3[] = {
152059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(0),
153059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(1),
154059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(2),
155059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(3),
156059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(4),
157059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(5),
158059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(6),
159059c53b3SMarek Vasut 	RCAR_GYROADC_CHAN(7),
160059c53b3SMarek Vasut };
161059c53b3SMarek Vasut 
rcar_gyroadc_set_power(struct rcar_gyroadc * priv,bool on)162059c53b3SMarek Vasut static int rcar_gyroadc_set_power(struct rcar_gyroadc *priv, bool on)
163059c53b3SMarek Vasut {
164059c53b3SMarek Vasut 	struct device *dev = priv->dev;
165059c53b3SMarek Vasut 
166059c53b3SMarek Vasut 	if (on) {
167db9c6c2eSJonathan Cameron 		return pm_runtime_resume_and_get(dev);
168059c53b3SMarek Vasut 	} else {
169059c53b3SMarek Vasut 		pm_runtime_mark_last_busy(dev);
170db9c6c2eSJonathan Cameron 		return pm_runtime_put_autosuspend(dev);
171059c53b3SMarek Vasut 	}
172059c53b3SMarek Vasut }
173059c53b3SMarek Vasut 
rcar_gyroadc_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)174059c53b3SMarek Vasut static int rcar_gyroadc_read_raw(struct iio_dev *indio_dev,
175059c53b3SMarek Vasut 				 struct iio_chan_spec const *chan,
176059c53b3SMarek Vasut 				 int *val, int *val2, long mask)
177059c53b3SMarek Vasut {
178059c53b3SMarek Vasut 	struct rcar_gyroadc *priv = iio_priv(indio_dev);
179059c53b3SMarek Vasut 	struct regulator *consumer;
180059c53b3SMarek Vasut 	unsigned int datareg = RCAR_GYROADC_REALTIME_DATA(chan->channel);
181059c53b3SMarek Vasut 	unsigned int vref;
182059c53b3SMarek Vasut 	int ret;
183059c53b3SMarek Vasut 
184059c53b3SMarek Vasut 	/*
185059c53b3SMarek Vasut 	 * MB88101 is special in that it has only single regulator for
186059c53b3SMarek Vasut 	 * all four channels.
187059c53b3SMarek Vasut 	 */
188059c53b3SMarek Vasut 	if (priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A)
189059c53b3SMarek Vasut 		consumer = priv->vref[0];
190059c53b3SMarek Vasut 	else
191059c53b3SMarek Vasut 		consumer = priv->vref[chan->channel];
192059c53b3SMarek Vasut 
193059c53b3SMarek Vasut 	switch (mask) {
194059c53b3SMarek Vasut 	case IIO_CHAN_INFO_RAW:
195059c53b3SMarek Vasut 		if (chan->type != IIO_VOLTAGE)
196059c53b3SMarek Vasut 			return -EINVAL;
197059c53b3SMarek Vasut 
198059c53b3SMarek Vasut 		/* Channel not connected. */
199059c53b3SMarek Vasut 		if (!consumer)
200059c53b3SMarek Vasut 			return -EINVAL;
201059c53b3SMarek Vasut 
202059c53b3SMarek Vasut 		ret = iio_device_claim_direct_mode(indio_dev);
203059c53b3SMarek Vasut 		if (ret)
204059c53b3SMarek Vasut 			return ret;
205059c53b3SMarek Vasut 
206059c53b3SMarek Vasut 		ret = rcar_gyroadc_set_power(priv, true);
207059c53b3SMarek Vasut 		if (ret < 0) {
208059c53b3SMarek Vasut 			iio_device_release_direct_mode(indio_dev);
209059c53b3SMarek Vasut 			return ret;
210059c53b3SMarek Vasut 		}
211059c53b3SMarek Vasut 
212059c53b3SMarek Vasut 		*val = readl(priv->regs + datareg);
213059c53b3SMarek Vasut 		*val &= BIT(priv->sample_width) - 1;
214059c53b3SMarek Vasut 
215059c53b3SMarek Vasut 		ret = rcar_gyroadc_set_power(priv, false);
216059c53b3SMarek Vasut 		iio_device_release_direct_mode(indio_dev);
217059c53b3SMarek Vasut 		if (ret < 0)
218059c53b3SMarek Vasut 			return ret;
219059c53b3SMarek Vasut 
220059c53b3SMarek Vasut 		return IIO_VAL_INT;
221059c53b3SMarek Vasut 	case IIO_CHAN_INFO_SCALE:
222059c53b3SMarek Vasut 		/* Channel not connected. */
223059c53b3SMarek Vasut 		if (!consumer)
224059c53b3SMarek Vasut 			return -EINVAL;
225059c53b3SMarek Vasut 
226059c53b3SMarek Vasut 		vref = regulator_get_voltage(consumer);
227059c53b3SMarek Vasut 		*val = vref / 1000;
228059c53b3SMarek Vasut 		*val2 = 1 << priv->sample_width;
229059c53b3SMarek Vasut 
230059c53b3SMarek Vasut 		return IIO_VAL_FRACTIONAL;
231059c53b3SMarek Vasut 	case IIO_CHAN_INFO_SAMP_FREQ:
232059c53b3SMarek Vasut 		*val = RCAR_GYROADC_SAMPLE_RATE;
233059c53b3SMarek Vasut 
234059c53b3SMarek Vasut 		return IIO_VAL_INT;
235059c53b3SMarek Vasut 	default:
236059c53b3SMarek Vasut 		return -EINVAL;
237059c53b3SMarek Vasut 	}
238059c53b3SMarek Vasut }
239059c53b3SMarek Vasut 
rcar_gyroadc_reg_access(struct iio_dev * indio_dev,unsigned int reg,unsigned int writeval,unsigned int * readval)240059c53b3SMarek Vasut static int rcar_gyroadc_reg_access(struct iio_dev *indio_dev,
241059c53b3SMarek Vasut 				   unsigned int reg, unsigned int writeval,
242059c53b3SMarek Vasut 				   unsigned int *readval)
243059c53b3SMarek Vasut {
244059c53b3SMarek Vasut 	struct rcar_gyroadc *priv = iio_priv(indio_dev);
245059c53b3SMarek Vasut 	unsigned int maxreg = RCAR_GYROADC_FIFO_STATUS;
246059c53b3SMarek Vasut 
247059c53b3SMarek Vasut 	if (readval == NULL)
248059c53b3SMarek Vasut 		return -EINVAL;
249059c53b3SMarek Vasut 
250059c53b3SMarek Vasut 	if (reg % 4)
251059c53b3SMarek Vasut 		return -EINVAL;
252059c53b3SMarek Vasut 
253059c53b3SMarek Vasut 	/* Handle the V2H case with extra interrupt block. */
254059c53b3SMarek Vasut 	if (priv->model == RCAR_GYROADC_MODEL_R8A7792)
255059c53b3SMarek Vasut 		maxreg = RCAR_GYROADC_INTENR;
256059c53b3SMarek Vasut 
257059c53b3SMarek Vasut 	if (reg > maxreg)
258059c53b3SMarek Vasut 		return -EINVAL;
259059c53b3SMarek Vasut 
260059c53b3SMarek Vasut 	*readval = readl(priv->regs + reg);
261059c53b3SMarek Vasut 
262059c53b3SMarek Vasut 	return 0;
263059c53b3SMarek Vasut }
264059c53b3SMarek Vasut 
265059c53b3SMarek Vasut static const struct iio_info rcar_gyroadc_iio_info = {
266059c53b3SMarek Vasut 	.read_raw		= rcar_gyroadc_read_raw,
267059c53b3SMarek Vasut 	.debugfs_reg_access	= rcar_gyroadc_reg_access,
268059c53b3SMarek Vasut };
269059c53b3SMarek Vasut 
270059c53b3SMarek Vasut static const struct of_device_id rcar_gyroadc_match[] = {
271059c53b3SMarek Vasut 	{
272059c53b3SMarek Vasut 		/* R-Car compatible GyroADC */
273059c53b3SMarek Vasut 		.compatible	= "renesas,rcar-gyroadc",
274059c53b3SMarek Vasut 		.data		= (void *)RCAR_GYROADC_MODEL_DEFAULT,
275059c53b3SMarek Vasut 	}, {
276059c53b3SMarek Vasut 		/* R-Car V2H specialty with interrupt registers. */
277059c53b3SMarek Vasut 		.compatible	= "renesas,r8a7792-gyroadc",
278059c53b3SMarek Vasut 		.data		= (void *)RCAR_GYROADC_MODEL_R8A7792,
279059c53b3SMarek Vasut 	}, {
280059c53b3SMarek Vasut 		/* sentinel */
281059c53b3SMarek Vasut 	}
282059c53b3SMarek Vasut };
283059c53b3SMarek Vasut 
284059c53b3SMarek Vasut MODULE_DEVICE_TABLE(of, rcar_gyroadc_match);
285059c53b3SMarek Vasut 
286*42d35bf6SKrzysztof Kozlowski static const struct of_device_id rcar_gyroadc_child_match[] __maybe_unused = {
287059c53b3SMarek Vasut 	/* Mode 1 ADCs */
288059c53b3SMarek Vasut 	{
289059c53b3SMarek Vasut 		.compatible	= "fujitsu,mb88101a",
290059c53b3SMarek Vasut 		.data		= (void *)RCAR_GYROADC_MODE_SELECT_1_MB88101A,
291059c53b3SMarek Vasut 	},
292059c53b3SMarek Vasut 	/* Mode 2 ADCs */
293059c53b3SMarek Vasut 	{
294059c53b3SMarek Vasut 		.compatible	= "ti,adcs7476",
295059c53b3SMarek Vasut 		.data		= (void *)RCAR_GYROADC_MODE_SELECT_2_ADCS7476,
296059c53b3SMarek Vasut 	}, {
297059c53b3SMarek Vasut 		.compatible	= "ti,adc121",
298059c53b3SMarek Vasut 		.data		= (void *)RCAR_GYROADC_MODE_SELECT_2_ADCS7476,
299059c53b3SMarek Vasut 	}, {
300059c53b3SMarek Vasut 		.compatible	= "adi,ad7476",
301059c53b3SMarek Vasut 		.data		= (void *)RCAR_GYROADC_MODE_SELECT_2_ADCS7476,
302059c53b3SMarek Vasut 	},
303059c53b3SMarek Vasut 	/* Mode 3 ADCs */
304059c53b3SMarek Vasut 	{
305059c53b3SMarek Vasut 		.compatible	= "maxim,max1162",
306059c53b3SMarek Vasut 		.data		= (void *)RCAR_GYROADC_MODE_SELECT_3_MAX1162,
307059c53b3SMarek Vasut 	}, {
308059c53b3SMarek Vasut 		.compatible	= "maxim,max11100",
309059c53b3SMarek Vasut 		.data		= (void *)RCAR_GYROADC_MODE_SELECT_3_MAX1162,
310059c53b3SMarek Vasut 	},
311059c53b3SMarek Vasut 	{ /* sentinel */ }
312059c53b3SMarek Vasut };
313059c53b3SMarek Vasut 
rcar_gyroadc_parse_subdevs(struct iio_dev * indio_dev)314059c53b3SMarek Vasut static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
315059c53b3SMarek Vasut {
316059c53b3SMarek Vasut 	const struct of_device_id *of_id;
317059c53b3SMarek Vasut 	const struct iio_chan_spec *channels;
318059c53b3SMarek Vasut 	struct rcar_gyroadc *priv = iio_priv(indio_dev);
319059c53b3SMarek Vasut 	struct device *dev = priv->dev;
320059c53b3SMarek Vasut 	struct device_node *np = dev->of_node;
321059c53b3SMarek Vasut 	struct device_node *child;
322059c53b3SMarek Vasut 	struct regulator *vref;
323059c53b3SMarek Vasut 	unsigned int reg;
32417fa2dcbSArnd Bergmann 	unsigned int adcmode = -1, childmode;
325059c53b3SMarek Vasut 	unsigned int sample_width;
326059c53b3SMarek Vasut 	unsigned int num_channels;
327059c53b3SMarek Vasut 	int ret, first = 1;
328059c53b3SMarek Vasut 
329059c53b3SMarek Vasut 	for_each_child_of_node(np, child) {
330059c53b3SMarek Vasut 		of_id = of_match_node(rcar_gyroadc_child_match, child);
331059c53b3SMarek Vasut 		if (!of_id) {
3321fc378faSRob Herring 			dev_err(dev, "Ignoring unsupported ADC \"%pOFn\".",
3331fc378faSRob Herring 				child);
334059c53b3SMarek Vasut 			continue;
335059c53b3SMarek Vasut 		}
336059c53b3SMarek Vasut 
3372a357345SGeert Uytterhoeven 		childmode = (uintptr_t)of_id->data;
338059c53b3SMarek Vasut 		switch (childmode) {
339059c53b3SMarek Vasut 		case RCAR_GYROADC_MODE_SELECT_1_MB88101A:
340059c53b3SMarek Vasut 			sample_width = 12;
341059c53b3SMarek Vasut 			channels = rcar_gyroadc_iio_channels_1;
342059c53b3SMarek Vasut 			num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_1);
343059c53b3SMarek Vasut 			break;
344059c53b3SMarek Vasut 		case RCAR_GYROADC_MODE_SELECT_2_ADCS7476:
345059c53b3SMarek Vasut 			sample_width = 15;
346059c53b3SMarek Vasut 			channels = rcar_gyroadc_iio_channels_2;
347059c53b3SMarek Vasut 			num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_2);
348059c53b3SMarek Vasut 			break;
349059c53b3SMarek Vasut 		case RCAR_GYROADC_MODE_SELECT_3_MAX1162:
350059c53b3SMarek Vasut 			sample_width = 16;
351059c53b3SMarek Vasut 			channels = rcar_gyroadc_iio_channels_3;
352059c53b3SMarek Vasut 			num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_3);
353059c53b3SMarek Vasut 			break;
35417fa2dcbSArnd Bergmann 		default:
355da4410d4STobias Jordan 			goto err_e_inval;
356059c53b3SMarek Vasut 		}
357059c53b3SMarek Vasut 
358059c53b3SMarek Vasut 		/*
359059c53b3SMarek Vasut 		 * MB88101 is special in that it's only a single chip taking
360059c53b3SMarek Vasut 		 * up all the CHS lines. Thus, the DT binding is also special
361059c53b3SMarek Vasut 		 * and has no reg property. If we run into such ADC, handle
362059c53b3SMarek Vasut 		 * it here.
363059c53b3SMarek Vasut 		 */
364059c53b3SMarek Vasut 		if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) {
365059c53b3SMarek Vasut 			reg = 0;
366059c53b3SMarek Vasut 		} else {
367059c53b3SMarek Vasut 			ret = of_property_read_u32(child, "reg", &reg);
368059c53b3SMarek Vasut 			if (ret) {
369059c53b3SMarek Vasut 				dev_err(dev,
3701fc378faSRob Herring 					"Failed to get child reg property of ADC \"%pOFn\".\n",
3711fc378faSRob Herring 					child);
372da4410d4STobias Jordan 				goto err_of_node_put;
373059c53b3SMarek Vasut 			}
374059c53b3SMarek Vasut 
375059c53b3SMarek Vasut 			/* Channel number is too high. */
376059c53b3SMarek Vasut 			if (reg >= num_channels) {
377059c53b3SMarek Vasut 				dev_err(dev,
3781fc378faSRob Herring 					"Only %i channels supported with %pOFn, but reg = <%i>.\n",
3791fc378faSRob Herring 					num_channels, child, reg);
380da4410d4STobias Jordan 				goto err_e_inval;
381059c53b3SMarek Vasut 			}
382059c53b3SMarek Vasut 		}
383059c53b3SMarek Vasut 
384059c53b3SMarek Vasut 		/* Child node selected different mode than the rest. */
385059c53b3SMarek Vasut 		if (!first && (adcmode != childmode)) {
386059c53b3SMarek Vasut 			dev_err(dev,
387059c53b3SMarek Vasut 				"Channel %i uses different ADC mode than the rest.\n",
388059c53b3SMarek Vasut 				reg);
389da4410d4STobias Jordan 			goto err_e_inval;
390059c53b3SMarek Vasut 		}
391059c53b3SMarek Vasut 
392059c53b3SMarek Vasut 		/* Channel is valid, grab the regulator. */
393059c53b3SMarek Vasut 		dev->of_node = child;
394059c53b3SMarek Vasut 		vref = devm_regulator_get(dev, "vref");
395059c53b3SMarek Vasut 		dev->of_node = np;
396059c53b3SMarek Vasut 		if (IS_ERR(vref)) {
397059c53b3SMarek Vasut 			dev_dbg(dev, "Channel %i 'vref' supply not connected.\n",
398059c53b3SMarek Vasut 				reg);
399da4410d4STobias Jordan 			ret = PTR_ERR(vref);
400da4410d4STobias Jordan 			goto err_of_node_put;
401059c53b3SMarek Vasut 		}
402059c53b3SMarek Vasut 
403059c53b3SMarek Vasut 		priv->vref[reg] = vref;
404059c53b3SMarek Vasut 
405059c53b3SMarek Vasut 		if (!first)
406059c53b3SMarek Vasut 			continue;
407059c53b3SMarek Vasut 
408059c53b3SMarek Vasut 		/* First child node which passed sanity tests. */
409059c53b3SMarek Vasut 		adcmode = childmode;
410059c53b3SMarek Vasut 		first = 0;
411059c53b3SMarek Vasut 
412059c53b3SMarek Vasut 		priv->num_channels = num_channels;
413059c53b3SMarek Vasut 		priv->mode = childmode;
414059c53b3SMarek Vasut 		priv->sample_width = sample_width;
415059c53b3SMarek Vasut 
416059c53b3SMarek Vasut 		indio_dev->channels = channels;
417059c53b3SMarek Vasut 		indio_dev->num_channels = num_channels;
418059c53b3SMarek Vasut 
419059c53b3SMarek Vasut 		/*
420059c53b3SMarek Vasut 		 * MB88101 is special and we only have one such device
421059c53b3SMarek Vasut 		 * attached to the GyroADC at a time, so if we found it,
422059c53b3SMarek Vasut 		 * we can stop parsing here.
423059c53b3SMarek Vasut 		 */
424da4410d4STobias Jordan 		if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) {
425da4410d4STobias Jordan 			of_node_put(child);
426059c53b3SMarek Vasut 			break;
427059c53b3SMarek Vasut 		}
428da4410d4STobias Jordan 	}
429059c53b3SMarek Vasut 
430059c53b3SMarek Vasut 	if (first) {
431059c53b3SMarek Vasut 		dev_err(dev, "No valid ADC channels found, aborting.\n");
432059c53b3SMarek Vasut 		return -EINVAL;
433059c53b3SMarek Vasut 	}
434059c53b3SMarek Vasut 
435059c53b3SMarek Vasut 	return 0;
436da4410d4STobias Jordan 
437da4410d4STobias Jordan err_e_inval:
438da4410d4STobias Jordan 	ret = -EINVAL;
439da4410d4STobias Jordan err_of_node_put:
440da4410d4STobias Jordan 	of_node_put(child);
441da4410d4STobias Jordan 	return ret;
442059c53b3SMarek Vasut }
443059c53b3SMarek Vasut 
rcar_gyroadc_deinit_supplies(struct iio_dev * indio_dev)444059c53b3SMarek Vasut static void rcar_gyroadc_deinit_supplies(struct iio_dev *indio_dev)
445059c53b3SMarek Vasut {
446059c53b3SMarek Vasut 	struct rcar_gyroadc *priv = iio_priv(indio_dev);
447059c53b3SMarek Vasut 	unsigned int i;
448059c53b3SMarek Vasut 
449059c53b3SMarek Vasut 	for (i = 0; i < priv->num_channels; i++) {
450059c53b3SMarek Vasut 		if (!priv->vref[i])
451059c53b3SMarek Vasut 			continue;
452059c53b3SMarek Vasut 
453059c53b3SMarek Vasut 		regulator_disable(priv->vref[i]);
454059c53b3SMarek Vasut 	}
455059c53b3SMarek Vasut }
456059c53b3SMarek Vasut 
rcar_gyroadc_init_supplies(struct iio_dev * indio_dev)457059c53b3SMarek Vasut static int rcar_gyroadc_init_supplies(struct iio_dev *indio_dev)
458059c53b3SMarek Vasut {
459059c53b3SMarek Vasut 	struct rcar_gyroadc *priv = iio_priv(indio_dev);
460059c53b3SMarek Vasut 	struct device *dev = priv->dev;
461059c53b3SMarek Vasut 	unsigned int i;
462059c53b3SMarek Vasut 	int ret;
463059c53b3SMarek Vasut 
464059c53b3SMarek Vasut 	for (i = 0; i < priv->num_channels; i++) {
465059c53b3SMarek Vasut 		if (!priv->vref[i])
466059c53b3SMarek Vasut 			continue;
467059c53b3SMarek Vasut 
468059c53b3SMarek Vasut 		ret = regulator_enable(priv->vref[i]);
469059c53b3SMarek Vasut 		if (ret) {
470059c53b3SMarek Vasut 			dev_err(dev, "Failed to enable regulator %i (ret=%i)\n",
471059c53b3SMarek Vasut 				i, ret);
472059c53b3SMarek Vasut 			goto err;
473059c53b3SMarek Vasut 		}
474059c53b3SMarek Vasut 	}
475059c53b3SMarek Vasut 
476059c53b3SMarek Vasut 	return 0;
477059c53b3SMarek Vasut 
478059c53b3SMarek Vasut err:
479059c53b3SMarek Vasut 	rcar_gyroadc_deinit_supplies(indio_dev);
480059c53b3SMarek Vasut 	return ret;
481059c53b3SMarek Vasut }
482059c53b3SMarek Vasut 
rcar_gyroadc_probe(struct platform_device * pdev)483059c53b3SMarek Vasut static int rcar_gyroadc_probe(struct platform_device *pdev)
484059c53b3SMarek Vasut {
485059c53b3SMarek Vasut 	struct device *dev = &pdev->dev;
486059c53b3SMarek Vasut 	struct rcar_gyroadc *priv;
487059c53b3SMarek Vasut 	struct iio_dev *indio_dev;
488059c53b3SMarek Vasut 	int ret;
489059c53b3SMarek Vasut 
490059c53b3SMarek Vasut 	indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
4915c25531dSGeert Uytterhoeven 	if (!indio_dev)
492059c53b3SMarek Vasut 		return -ENOMEM;
493059c53b3SMarek Vasut 
494059c53b3SMarek Vasut 	priv = iio_priv(indio_dev);
495059c53b3SMarek Vasut 	priv->dev = dev;
496059c53b3SMarek Vasut 
4976c78cc9cSJonathan Cameron 	priv->regs = devm_platform_ioremap_resource(pdev, 0);
498059c53b3SMarek Vasut 	if (IS_ERR(priv->regs))
499059c53b3SMarek Vasut 		return PTR_ERR(priv->regs);
500059c53b3SMarek Vasut 
5011a732f42SMarek Vasut 	priv->clk = devm_clk_get(dev, "fck");
5026d2710ceSKrzysztof Kozlowski 	if (IS_ERR(priv->clk))
5036d2710ceSKrzysztof Kozlowski 		return dev_err_probe(dev, PTR_ERR(priv->clk),
5046d2710ceSKrzysztof Kozlowski 				     "Failed to get IF clock\n");
505059c53b3SMarek Vasut 
506059c53b3SMarek Vasut 	ret = rcar_gyroadc_parse_subdevs(indio_dev);
507059c53b3SMarek Vasut 	if (ret)
508059c53b3SMarek Vasut 		return ret;
509059c53b3SMarek Vasut 
510059c53b3SMarek Vasut 	ret = rcar_gyroadc_init_supplies(indio_dev);
511059c53b3SMarek Vasut 	if (ret)
512059c53b3SMarek Vasut 		return ret;
513059c53b3SMarek Vasut 
514835122a3SJonathan Cameron 	priv->model = (uintptr_t)of_device_get_match_data(&pdev->dev);
515059c53b3SMarek Vasut 
516059c53b3SMarek Vasut 	platform_set_drvdata(pdev, indio_dev);
517059c53b3SMarek Vasut 
518059c53b3SMarek Vasut 	indio_dev->name = DRIVER_NAME;
519059c53b3SMarek Vasut 	indio_dev->info = &rcar_gyroadc_iio_info;
520059c53b3SMarek Vasut 	indio_dev->modes = INDIO_DIRECT_MODE;
521059c53b3SMarek Vasut 
5221a732f42SMarek Vasut 	ret = clk_prepare_enable(priv->clk);
523059c53b3SMarek Vasut 	if (ret) {
524059c53b3SMarek Vasut 		dev_err(dev, "Could not prepare or enable the IF clock.\n");
525059c53b3SMarek Vasut 		goto err_clk_if_enable;
526059c53b3SMarek Vasut 	}
527059c53b3SMarek Vasut 
528059c53b3SMarek Vasut 	pm_runtime_set_autosuspend_delay(dev, RCAR_GYROADC_RUNTIME_PM_DELAY_MS);
529059c53b3SMarek Vasut 	pm_runtime_use_autosuspend(dev);
530059c53b3SMarek Vasut 	pm_runtime_enable(dev);
531059c53b3SMarek Vasut 
532db9c6c2eSJonathan Cameron 	ret = pm_runtime_resume_and_get(dev);
533db9c6c2eSJonathan Cameron 	if (ret)
534db9c6c2eSJonathan Cameron 		goto err_power_up;
535db9c6c2eSJonathan Cameron 
536059c53b3SMarek Vasut 	rcar_gyroadc_hw_init(priv);
537059c53b3SMarek Vasut 	rcar_gyroadc_hw_start(priv);
538059c53b3SMarek Vasut 
539059c53b3SMarek Vasut 	ret = iio_device_register(indio_dev);
540059c53b3SMarek Vasut 	if (ret) {
541059c53b3SMarek Vasut 		dev_err(dev, "Couldn't register IIO device.\n");
542059c53b3SMarek Vasut 		goto err_iio_device_register;
543059c53b3SMarek Vasut 	}
544059c53b3SMarek Vasut 
545059c53b3SMarek Vasut 	pm_runtime_put_sync(dev);
546059c53b3SMarek Vasut 
547059c53b3SMarek Vasut 	return 0;
548059c53b3SMarek Vasut 
549059c53b3SMarek Vasut err_iio_device_register:
550059c53b3SMarek Vasut 	rcar_gyroadc_hw_stop(priv);
551059c53b3SMarek Vasut 	pm_runtime_put_sync(dev);
552db9c6c2eSJonathan Cameron err_power_up:
553059c53b3SMarek Vasut 	pm_runtime_disable(dev);
554059c53b3SMarek Vasut 	pm_runtime_set_suspended(dev);
5551a732f42SMarek Vasut 	clk_disable_unprepare(priv->clk);
556059c53b3SMarek Vasut err_clk_if_enable:
557059c53b3SMarek Vasut 	rcar_gyroadc_deinit_supplies(indio_dev);
558059c53b3SMarek Vasut 
559059c53b3SMarek Vasut 	return ret;
560059c53b3SMarek Vasut }
561059c53b3SMarek Vasut 
rcar_gyroadc_remove(struct platform_device * pdev)562059c53b3SMarek Vasut static int rcar_gyroadc_remove(struct platform_device *pdev)
563059c53b3SMarek Vasut {
564059c53b3SMarek Vasut 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
565059c53b3SMarek Vasut 	struct rcar_gyroadc *priv = iio_priv(indio_dev);
566059c53b3SMarek Vasut 	struct device *dev = priv->dev;
567059c53b3SMarek Vasut 
568059c53b3SMarek Vasut 	iio_device_unregister(indio_dev);
569059c53b3SMarek Vasut 	pm_runtime_get_sync(dev);
570059c53b3SMarek Vasut 	rcar_gyroadc_hw_stop(priv);
571059c53b3SMarek Vasut 	pm_runtime_put_sync(dev);
572059c53b3SMarek Vasut 	pm_runtime_disable(dev);
573059c53b3SMarek Vasut 	pm_runtime_set_suspended(dev);
5741a732f42SMarek Vasut 	clk_disable_unprepare(priv->clk);
575059c53b3SMarek Vasut 	rcar_gyroadc_deinit_supplies(indio_dev);
576059c53b3SMarek Vasut 
577059c53b3SMarek Vasut 	return 0;
578059c53b3SMarek Vasut }
579059c53b3SMarek Vasut 
rcar_gyroadc_suspend(struct device * dev)580059c53b3SMarek Vasut static int rcar_gyroadc_suspend(struct device *dev)
581059c53b3SMarek Vasut {
582059c53b3SMarek Vasut 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
583059c53b3SMarek Vasut 	struct rcar_gyroadc *priv = iio_priv(indio_dev);
584059c53b3SMarek Vasut 
585059c53b3SMarek Vasut 	rcar_gyroadc_hw_stop(priv);
586059c53b3SMarek Vasut 
587059c53b3SMarek Vasut 	return 0;
588059c53b3SMarek Vasut }
589059c53b3SMarek Vasut 
rcar_gyroadc_resume(struct device * dev)590059c53b3SMarek Vasut static int rcar_gyroadc_resume(struct device *dev)
591059c53b3SMarek Vasut {
592059c53b3SMarek Vasut 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
593059c53b3SMarek Vasut 	struct rcar_gyroadc *priv = iio_priv(indio_dev);
594059c53b3SMarek Vasut 
595059c53b3SMarek Vasut 	rcar_gyroadc_hw_start(priv);
596059c53b3SMarek Vasut 
597059c53b3SMarek Vasut 	return 0;
598059c53b3SMarek Vasut }
599059c53b3SMarek Vasut 
600059c53b3SMarek Vasut static const struct dev_pm_ops rcar_gyroadc_pm_ops = {
60125d87707SJonathan Cameron 	RUNTIME_PM_OPS(rcar_gyroadc_suspend, rcar_gyroadc_resume, NULL)
602059c53b3SMarek Vasut };
603059c53b3SMarek Vasut 
604059c53b3SMarek Vasut static struct platform_driver rcar_gyroadc_driver = {
605059c53b3SMarek Vasut 	.probe          = rcar_gyroadc_probe,
606059c53b3SMarek Vasut 	.remove         = rcar_gyroadc_remove,
607059c53b3SMarek Vasut 	.driver         = {
608059c53b3SMarek Vasut 		.name		= DRIVER_NAME,
609059c53b3SMarek Vasut 		.of_match_table	= rcar_gyroadc_match,
61025d87707SJonathan Cameron 		.pm		= pm_ptr(&rcar_gyroadc_pm_ops),
611059c53b3SMarek Vasut 	},
612059c53b3SMarek Vasut };
613059c53b3SMarek Vasut 
614059c53b3SMarek Vasut module_platform_driver(rcar_gyroadc_driver);
615059c53b3SMarek Vasut 
616059c53b3SMarek Vasut MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
617059c53b3SMarek Vasut MODULE_DESCRIPTION("Renesas R-Car GyroADC driver");
618059c53b3SMarek Vasut MODULE_LICENSE("GPL");
619