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", ®);
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