162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Renesas R-Car GyroADC driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2016 Marek Vasut <marek.vasut@gmail.com>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/platform_device.h>
1062306a36Sopenharmony_ci#include <linux/delay.h>
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/slab.h>
1362306a36Sopenharmony_ci#include <linux/io.h>
1462306a36Sopenharmony_ci#include <linux/clk.h>
1562306a36Sopenharmony_ci#include <linux/of.h>
1662306a36Sopenharmony_ci#include <linux/of_irq.h>
1762306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
1862306a36Sopenharmony_ci#include <linux/of_platform.h>
1962306a36Sopenharmony_ci#include <linux/err.h>
2062306a36Sopenharmony_ci#include <linux/pm_runtime.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <linux/iio/iio.h>
2362306a36Sopenharmony_ci#include <linux/iio/sysfs.h>
2462306a36Sopenharmony_ci#include <linux/iio/trigger.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define DRIVER_NAME				"rcar-gyroadc"
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/* GyroADC registers. */
2962306a36Sopenharmony_ci#define RCAR_GYROADC_MODE_SELECT		0x00
3062306a36Sopenharmony_ci#define RCAR_GYROADC_MODE_SELECT_1_MB88101A	0x0
3162306a36Sopenharmony_ci#define RCAR_GYROADC_MODE_SELECT_2_ADCS7476	0x1
3262306a36Sopenharmony_ci#define RCAR_GYROADC_MODE_SELECT_3_MAX1162	0x3
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define RCAR_GYROADC_START_STOP			0x04
3562306a36Sopenharmony_ci#define RCAR_GYROADC_START_STOP_START		BIT(0)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define RCAR_GYROADC_CLOCK_LENGTH		0x08
3862306a36Sopenharmony_ci#define RCAR_GYROADC_1_25MS_LENGTH		0x0c
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define RCAR_GYROADC_REALTIME_DATA(ch)		(0x10 + ((ch) * 4))
4162306a36Sopenharmony_ci#define RCAR_GYROADC_100MS_ADDED_DATA(ch)	(0x30 + ((ch) * 4))
4262306a36Sopenharmony_ci#define RCAR_GYROADC_10MS_AVG_DATA(ch)		(0x50 + ((ch) * 4))
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define RCAR_GYROADC_FIFO_STATUS		0x70
4562306a36Sopenharmony_ci#define RCAR_GYROADC_FIFO_STATUS_EMPTY(ch)	BIT(0 + (4 * (ch)))
4662306a36Sopenharmony_ci#define RCAR_GYROADC_FIFO_STATUS_FULL(ch)	BIT(1 + (4 * (ch)))
4762306a36Sopenharmony_ci#define RCAR_GYROADC_FIFO_STATUS_ERROR(ch)	BIT(2 + (4 * (ch)))
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define RCAR_GYROADC_INTR			0x74
5062306a36Sopenharmony_ci#define RCAR_GYROADC_INTR_INT			BIT(0)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define RCAR_GYROADC_INTENR			0x78
5362306a36Sopenharmony_ci#define RCAR_GYROADC_INTENR_INTEN		BIT(0)
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define RCAR_GYROADC_SAMPLE_RATE		800	/* Hz */
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define RCAR_GYROADC_RUNTIME_PM_DELAY_MS	2000
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cienum rcar_gyroadc_model {
6062306a36Sopenharmony_ci	RCAR_GYROADC_MODEL_DEFAULT,
6162306a36Sopenharmony_ci	RCAR_GYROADC_MODEL_R8A7792,
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistruct rcar_gyroadc {
6562306a36Sopenharmony_ci	struct device			*dev;
6662306a36Sopenharmony_ci	void __iomem			*regs;
6762306a36Sopenharmony_ci	struct clk			*clk;
6862306a36Sopenharmony_ci	struct regulator		*vref[8];
6962306a36Sopenharmony_ci	unsigned int			num_channels;
7062306a36Sopenharmony_ci	enum rcar_gyroadc_model		model;
7162306a36Sopenharmony_ci	unsigned int			mode;
7262306a36Sopenharmony_ci	unsigned int			sample_width;
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic void rcar_gyroadc_hw_init(struct rcar_gyroadc *priv)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	const unsigned long clk_mhz = clk_get_rate(priv->clk) / 1000000;
7862306a36Sopenharmony_ci	const unsigned long clk_mul =
7962306a36Sopenharmony_ci		(priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) ? 10 : 5;
8062306a36Sopenharmony_ci	unsigned long clk_len = clk_mhz * clk_mul;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	/*
8362306a36Sopenharmony_ci	 * According to the R-Car Gen2 datasheet Rev. 1.01, Sept 08 2014,
8462306a36Sopenharmony_ci	 * page 77-7, clock length must be even number. If it's odd number,
8562306a36Sopenharmony_ci	 * add one.
8662306a36Sopenharmony_ci	 */
8762306a36Sopenharmony_ci	if (clk_len & 1)
8862306a36Sopenharmony_ci		clk_len++;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	/* Stop the GyroADC. */
9162306a36Sopenharmony_ci	writel(0, priv->regs + RCAR_GYROADC_START_STOP);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	/* Disable IRQ on V2H. */
9462306a36Sopenharmony_ci	if (priv->model == RCAR_GYROADC_MODEL_R8A7792)
9562306a36Sopenharmony_ci		writel(0, priv->regs + RCAR_GYROADC_INTENR);
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	/* Set mode and timing. */
9862306a36Sopenharmony_ci	writel(priv->mode, priv->regs + RCAR_GYROADC_MODE_SELECT);
9962306a36Sopenharmony_ci	writel(clk_len, priv->regs + RCAR_GYROADC_CLOCK_LENGTH);
10062306a36Sopenharmony_ci	writel(clk_mhz * 1250, priv->regs + RCAR_GYROADC_1_25MS_LENGTH);
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic void rcar_gyroadc_hw_start(struct rcar_gyroadc *priv)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	/* Start sampling. */
10662306a36Sopenharmony_ci	writel(RCAR_GYROADC_START_STOP_START,
10762306a36Sopenharmony_ci	       priv->regs + RCAR_GYROADC_START_STOP);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/*
11062306a36Sopenharmony_ci	 * Wait for the first conversion to complete. This is longer than
11162306a36Sopenharmony_ci	 * the 1.25 mS in the datasheet because 1.25 mS is not enough for
11262306a36Sopenharmony_ci	 * the hardware to deliver the first sample and the hardware does
11362306a36Sopenharmony_ci	 * then return zeroes instead of valid data.
11462306a36Sopenharmony_ci	 */
11562306a36Sopenharmony_ci	mdelay(3);
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistatic void rcar_gyroadc_hw_stop(struct rcar_gyroadc *priv)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	/* Stop the GyroADC. */
12162306a36Sopenharmony_ci	writel(0, priv->regs + RCAR_GYROADC_START_STOP);
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#define RCAR_GYROADC_CHAN(_idx) {				\
12562306a36Sopenharmony_ci	.type			= IIO_VOLTAGE,			\
12662306a36Sopenharmony_ci	.indexed		= 1,				\
12762306a36Sopenharmony_ci	.channel		= (_idx),			\
12862306a36Sopenharmony_ci	.info_mask_separate	= BIT(IIO_CHAN_INFO_RAW) |	\
12962306a36Sopenharmony_ci				  BIT(IIO_CHAN_INFO_SCALE),	\
13062306a36Sopenharmony_ci	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic const struct iio_chan_spec rcar_gyroadc_iio_channels_1[] = {
13462306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(0),
13562306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(1),
13662306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(2),
13762306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(3),
13862306a36Sopenharmony_ci};
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic const struct iio_chan_spec rcar_gyroadc_iio_channels_2[] = {
14162306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(0),
14262306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(1),
14362306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(2),
14462306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(3),
14562306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(4),
14662306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(5),
14762306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(6),
14862306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(7),
14962306a36Sopenharmony_ci};
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic const struct iio_chan_spec rcar_gyroadc_iio_channels_3[] = {
15262306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(0),
15362306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(1),
15462306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(2),
15562306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(3),
15662306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(4),
15762306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(5),
15862306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(6),
15962306a36Sopenharmony_ci	RCAR_GYROADC_CHAN(7),
16062306a36Sopenharmony_ci};
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic int rcar_gyroadc_set_power(struct rcar_gyroadc *priv, bool on)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct device *dev = priv->dev;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	if (on) {
16762306a36Sopenharmony_ci		return pm_runtime_resume_and_get(dev);
16862306a36Sopenharmony_ci	} else {
16962306a36Sopenharmony_ci		pm_runtime_mark_last_busy(dev);
17062306a36Sopenharmony_ci		return pm_runtime_put_autosuspend(dev);
17162306a36Sopenharmony_ci	}
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic int rcar_gyroadc_read_raw(struct iio_dev *indio_dev,
17562306a36Sopenharmony_ci				 struct iio_chan_spec const *chan,
17662306a36Sopenharmony_ci				 int *val, int *val2, long mask)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	struct rcar_gyroadc *priv = iio_priv(indio_dev);
17962306a36Sopenharmony_ci	struct regulator *consumer;
18062306a36Sopenharmony_ci	unsigned int datareg = RCAR_GYROADC_REALTIME_DATA(chan->channel);
18162306a36Sopenharmony_ci	unsigned int vref;
18262306a36Sopenharmony_ci	int ret;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	/*
18562306a36Sopenharmony_ci	 * MB88101 is special in that it has only single regulator for
18662306a36Sopenharmony_ci	 * all four channels.
18762306a36Sopenharmony_ci	 */
18862306a36Sopenharmony_ci	if (priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A)
18962306a36Sopenharmony_ci		consumer = priv->vref[0];
19062306a36Sopenharmony_ci	else
19162306a36Sopenharmony_ci		consumer = priv->vref[chan->channel];
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	switch (mask) {
19462306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
19562306a36Sopenharmony_ci		if (chan->type != IIO_VOLTAGE)
19662306a36Sopenharmony_ci			return -EINVAL;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci		/* Channel not connected. */
19962306a36Sopenharmony_ci		if (!consumer)
20062306a36Sopenharmony_ci			return -EINVAL;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci		ret = iio_device_claim_direct_mode(indio_dev);
20362306a36Sopenharmony_ci		if (ret)
20462306a36Sopenharmony_ci			return ret;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci		ret = rcar_gyroadc_set_power(priv, true);
20762306a36Sopenharmony_ci		if (ret < 0) {
20862306a36Sopenharmony_ci			iio_device_release_direct_mode(indio_dev);
20962306a36Sopenharmony_ci			return ret;
21062306a36Sopenharmony_ci		}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci		*val = readl(priv->regs + datareg);
21362306a36Sopenharmony_ci		*val &= BIT(priv->sample_width) - 1;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci		ret = rcar_gyroadc_set_power(priv, false);
21662306a36Sopenharmony_ci		iio_device_release_direct_mode(indio_dev);
21762306a36Sopenharmony_ci		if (ret < 0)
21862306a36Sopenharmony_ci			return ret;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci		return IIO_VAL_INT;
22162306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
22262306a36Sopenharmony_ci		/* Channel not connected. */
22362306a36Sopenharmony_ci		if (!consumer)
22462306a36Sopenharmony_ci			return -EINVAL;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci		vref = regulator_get_voltage(consumer);
22762306a36Sopenharmony_ci		*val = vref / 1000;
22862306a36Sopenharmony_ci		*val2 = 1 << priv->sample_width;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci		return IIO_VAL_FRACTIONAL;
23162306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
23262306a36Sopenharmony_ci		*val = RCAR_GYROADC_SAMPLE_RATE;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci		return IIO_VAL_INT;
23562306a36Sopenharmony_ci	default:
23662306a36Sopenharmony_ci		return -EINVAL;
23762306a36Sopenharmony_ci	}
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic int rcar_gyroadc_reg_access(struct iio_dev *indio_dev,
24162306a36Sopenharmony_ci				   unsigned int reg, unsigned int writeval,
24262306a36Sopenharmony_ci				   unsigned int *readval)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	struct rcar_gyroadc *priv = iio_priv(indio_dev);
24562306a36Sopenharmony_ci	unsigned int maxreg = RCAR_GYROADC_FIFO_STATUS;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	if (readval == NULL)
24862306a36Sopenharmony_ci		return -EINVAL;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	if (reg % 4)
25162306a36Sopenharmony_ci		return -EINVAL;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	/* Handle the V2H case with extra interrupt block. */
25462306a36Sopenharmony_ci	if (priv->model == RCAR_GYROADC_MODEL_R8A7792)
25562306a36Sopenharmony_ci		maxreg = RCAR_GYROADC_INTENR;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	if (reg > maxreg)
25862306a36Sopenharmony_ci		return -EINVAL;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	*readval = readl(priv->regs + reg);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	return 0;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic const struct iio_info rcar_gyroadc_iio_info = {
26662306a36Sopenharmony_ci	.read_raw		= rcar_gyroadc_read_raw,
26762306a36Sopenharmony_ci	.debugfs_reg_access	= rcar_gyroadc_reg_access,
26862306a36Sopenharmony_ci};
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic const struct of_device_id rcar_gyroadc_match[] = {
27162306a36Sopenharmony_ci	{
27262306a36Sopenharmony_ci		/* R-Car compatible GyroADC */
27362306a36Sopenharmony_ci		.compatible	= "renesas,rcar-gyroadc",
27462306a36Sopenharmony_ci		.data		= (void *)RCAR_GYROADC_MODEL_DEFAULT,
27562306a36Sopenharmony_ci	}, {
27662306a36Sopenharmony_ci		/* R-Car V2H specialty with interrupt registers. */
27762306a36Sopenharmony_ci		.compatible	= "renesas,r8a7792-gyroadc",
27862306a36Sopenharmony_ci		.data		= (void *)RCAR_GYROADC_MODEL_R8A7792,
27962306a36Sopenharmony_ci	}, {
28062306a36Sopenharmony_ci		/* sentinel */
28162306a36Sopenharmony_ci	}
28262306a36Sopenharmony_ci};
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rcar_gyroadc_match);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_cistatic const struct of_device_id rcar_gyroadc_child_match[] __maybe_unused = {
28762306a36Sopenharmony_ci	/* Mode 1 ADCs */
28862306a36Sopenharmony_ci	{
28962306a36Sopenharmony_ci		.compatible	= "fujitsu,mb88101a",
29062306a36Sopenharmony_ci		.data		= (void *)RCAR_GYROADC_MODE_SELECT_1_MB88101A,
29162306a36Sopenharmony_ci	},
29262306a36Sopenharmony_ci	/* Mode 2 ADCs */
29362306a36Sopenharmony_ci	{
29462306a36Sopenharmony_ci		.compatible	= "ti,adcs7476",
29562306a36Sopenharmony_ci		.data		= (void *)RCAR_GYROADC_MODE_SELECT_2_ADCS7476,
29662306a36Sopenharmony_ci	}, {
29762306a36Sopenharmony_ci		.compatible	= "ti,adc121",
29862306a36Sopenharmony_ci		.data		= (void *)RCAR_GYROADC_MODE_SELECT_2_ADCS7476,
29962306a36Sopenharmony_ci	}, {
30062306a36Sopenharmony_ci		.compatible	= "adi,ad7476",
30162306a36Sopenharmony_ci		.data		= (void *)RCAR_GYROADC_MODE_SELECT_2_ADCS7476,
30262306a36Sopenharmony_ci	},
30362306a36Sopenharmony_ci	/* Mode 3 ADCs */
30462306a36Sopenharmony_ci	{
30562306a36Sopenharmony_ci		.compatible	= "maxim,max1162",
30662306a36Sopenharmony_ci		.data		= (void *)RCAR_GYROADC_MODE_SELECT_3_MAX1162,
30762306a36Sopenharmony_ci	}, {
30862306a36Sopenharmony_ci		.compatible	= "maxim,max11100",
30962306a36Sopenharmony_ci		.data		= (void *)RCAR_GYROADC_MODE_SELECT_3_MAX1162,
31062306a36Sopenharmony_ci	},
31162306a36Sopenharmony_ci	{ /* sentinel */ }
31262306a36Sopenharmony_ci};
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_cistatic int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
31562306a36Sopenharmony_ci{
31662306a36Sopenharmony_ci	const struct of_device_id *of_id;
31762306a36Sopenharmony_ci	const struct iio_chan_spec *channels;
31862306a36Sopenharmony_ci	struct rcar_gyroadc *priv = iio_priv(indio_dev);
31962306a36Sopenharmony_ci	struct device *dev = priv->dev;
32062306a36Sopenharmony_ci	struct device_node *np = dev->of_node;
32162306a36Sopenharmony_ci	struct device_node *child;
32262306a36Sopenharmony_ci	struct regulator *vref;
32362306a36Sopenharmony_ci	unsigned int reg;
32462306a36Sopenharmony_ci	unsigned int adcmode = -1, childmode;
32562306a36Sopenharmony_ci	unsigned int sample_width;
32662306a36Sopenharmony_ci	unsigned int num_channels;
32762306a36Sopenharmony_ci	int ret, first = 1;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	for_each_child_of_node(np, child) {
33062306a36Sopenharmony_ci		of_id = of_match_node(rcar_gyroadc_child_match, child);
33162306a36Sopenharmony_ci		if (!of_id) {
33262306a36Sopenharmony_ci			dev_err(dev, "Ignoring unsupported ADC \"%pOFn\".",
33362306a36Sopenharmony_ci				child);
33462306a36Sopenharmony_ci			continue;
33562306a36Sopenharmony_ci		}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci		childmode = (uintptr_t)of_id->data;
33862306a36Sopenharmony_ci		switch (childmode) {
33962306a36Sopenharmony_ci		case RCAR_GYROADC_MODE_SELECT_1_MB88101A:
34062306a36Sopenharmony_ci			sample_width = 12;
34162306a36Sopenharmony_ci			channels = rcar_gyroadc_iio_channels_1;
34262306a36Sopenharmony_ci			num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_1);
34362306a36Sopenharmony_ci			break;
34462306a36Sopenharmony_ci		case RCAR_GYROADC_MODE_SELECT_2_ADCS7476:
34562306a36Sopenharmony_ci			sample_width = 15;
34662306a36Sopenharmony_ci			channels = rcar_gyroadc_iio_channels_2;
34762306a36Sopenharmony_ci			num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_2);
34862306a36Sopenharmony_ci			break;
34962306a36Sopenharmony_ci		case RCAR_GYROADC_MODE_SELECT_3_MAX1162:
35062306a36Sopenharmony_ci			sample_width = 16;
35162306a36Sopenharmony_ci			channels = rcar_gyroadc_iio_channels_3;
35262306a36Sopenharmony_ci			num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_3);
35362306a36Sopenharmony_ci			break;
35462306a36Sopenharmony_ci		default:
35562306a36Sopenharmony_ci			goto err_e_inval;
35662306a36Sopenharmony_ci		}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci		/*
35962306a36Sopenharmony_ci		 * MB88101 is special in that it's only a single chip taking
36062306a36Sopenharmony_ci		 * up all the CHS lines. Thus, the DT binding is also special
36162306a36Sopenharmony_ci		 * and has no reg property. If we run into such ADC, handle
36262306a36Sopenharmony_ci		 * it here.
36362306a36Sopenharmony_ci		 */
36462306a36Sopenharmony_ci		if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) {
36562306a36Sopenharmony_ci			reg = 0;
36662306a36Sopenharmony_ci		} else {
36762306a36Sopenharmony_ci			ret = of_property_read_u32(child, "reg", &reg);
36862306a36Sopenharmony_ci			if (ret) {
36962306a36Sopenharmony_ci				dev_err(dev,
37062306a36Sopenharmony_ci					"Failed to get child reg property of ADC \"%pOFn\".\n",
37162306a36Sopenharmony_ci					child);
37262306a36Sopenharmony_ci				goto err_of_node_put;
37362306a36Sopenharmony_ci			}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci			/* Channel number is too high. */
37662306a36Sopenharmony_ci			if (reg >= num_channels) {
37762306a36Sopenharmony_ci				dev_err(dev,
37862306a36Sopenharmony_ci					"Only %i channels supported with %pOFn, but reg = <%i>.\n",
37962306a36Sopenharmony_ci					num_channels, child, reg);
38062306a36Sopenharmony_ci				goto err_e_inval;
38162306a36Sopenharmony_ci			}
38262306a36Sopenharmony_ci		}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci		/* Child node selected different mode than the rest. */
38562306a36Sopenharmony_ci		if (!first && (adcmode != childmode)) {
38662306a36Sopenharmony_ci			dev_err(dev,
38762306a36Sopenharmony_ci				"Channel %i uses different ADC mode than the rest.\n",
38862306a36Sopenharmony_ci				reg);
38962306a36Sopenharmony_ci			goto err_e_inval;
39062306a36Sopenharmony_ci		}
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci		/* Channel is valid, grab the regulator. */
39362306a36Sopenharmony_ci		dev->of_node = child;
39462306a36Sopenharmony_ci		vref = devm_regulator_get(dev, "vref");
39562306a36Sopenharmony_ci		dev->of_node = np;
39662306a36Sopenharmony_ci		if (IS_ERR(vref)) {
39762306a36Sopenharmony_ci			dev_dbg(dev, "Channel %i 'vref' supply not connected.\n",
39862306a36Sopenharmony_ci				reg);
39962306a36Sopenharmony_ci			ret = PTR_ERR(vref);
40062306a36Sopenharmony_ci			goto err_of_node_put;
40162306a36Sopenharmony_ci		}
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci		priv->vref[reg] = vref;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci		if (!first)
40662306a36Sopenharmony_ci			continue;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci		/* First child node which passed sanity tests. */
40962306a36Sopenharmony_ci		adcmode = childmode;
41062306a36Sopenharmony_ci		first = 0;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci		priv->num_channels = num_channels;
41362306a36Sopenharmony_ci		priv->mode = childmode;
41462306a36Sopenharmony_ci		priv->sample_width = sample_width;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci		indio_dev->channels = channels;
41762306a36Sopenharmony_ci		indio_dev->num_channels = num_channels;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci		/*
42062306a36Sopenharmony_ci		 * MB88101 is special and we only have one such device
42162306a36Sopenharmony_ci		 * attached to the GyroADC at a time, so if we found it,
42262306a36Sopenharmony_ci		 * we can stop parsing here.
42362306a36Sopenharmony_ci		 */
42462306a36Sopenharmony_ci		if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) {
42562306a36Sopenharmony_ci			of_node_put(child);
42662306a36Sopenharmony_ci			break;
42762306a36Sopenharmony_ci		}
42862306a36Sopenharmony_ci	}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	if (first) {
43162306a36Sopenharmony_ci		dev_err(dev, "No valid ADC channels found, aborting.\n");
43262306a36Sopenharmony_ci		return -EINVAL;
43362306a36Sopenharmony_ci	}
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	return 0;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_cierr_e_inval:
43862306a36Sopenharmony_ci	ret = -EINVAL;
43962306a36Sopenharmony_cierr_of_node_put:
44062306a36Sopenharmony_ci	of_node_put(child);
44162306a36Sopenharmony_ci	return ret;
44262306a36Sopenharmony_ci}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_cistatic void rcar_gyroadc_deinit_supplies(struct iio_dev *indio_dev)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	struct rcar_gyroadc *priv = iio_priv(indio_dev);
44762306a36Sopenharmony_ci	unsigned int i;
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	for (i = 0; i < priv->num_channels; i++) {
45062306a36Sopenharmony_ci		if (!priv->vref[i])
45162306a36Sopenharmony_ci			continue;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci		regulator_disable(priv->vref[i]);
45462306a36Sopenharmony_ci	}
45562306a36Sopenharmony_ci}
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_cistatic int rcar_gyroadc_init_supplies(struct iio_dev *indio_dev)
45862306a36Sopenharmony_ci{
45962306a36Sopenharmony_ci	struct rcar_gyroadc *priv = iio_priv(indio_dev);
46062306a36Sopenharmony_ci	struct device *dev = priv->dev;
46162306a36Sopenharmony_ci	unsigned int i;
46262306a36Sopenharmony_ci	int ret;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	for (i = 0; i < priv->num_channels; i++) {
46562306a36Sopenharmony_ci		if (!priv->vref[i])
46662306a36Sopenharmony_ci			continue;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci		ret = regulator_enable(priv->vref[i]);
46962306a36Sopenharmony_ci		if (ret) {
47062306a36Sopenharmony_ci			dev_err(dev, "Failed to enable regulator %i (ret=%i)\n",
47162306a36Sopenharmony_ci				i, ret);
47262306a36Sopenharmony_ci			goto err;
47362306a36Sopenharmony_ci		}
47462306a36Sopenharmony_ci	}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	return 0;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_cierr:
47962306a36Sopenharmony_ci	rcar_gyroadc_deinit_supplies(indio_dev);
48062306a36Sopenharmony_ci	return ret;
48162306a36Sopenharmony_ci}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic int rcar_gyroadc_probe(struct platform_device *pdev)
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
48662306a36Sopenharmony_ci	struct rcar_gyroadc *priv;
48762306a36Sopenharmony_ci	struct iio_dev *indio_dev;
48862306a36Sopenharmony_ci	int ret;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
49162306a36Sopenharmony_ci	if (!indio_dev)
49262306a36Sopenharmony_ci		return -ENOMEM;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	priv = iio_priv(indio_dev);
49562306a36Sopenharmony_ci	priv->dev = dev;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	priv->regs = devm_platform_ioremap_resource(pdev, 0);
49862306a36Sopenharmony_ci	if (IS_ERR(priv->regs))
49962306a36Sopenharmony_ci		return PTR_ERR(priv->regs);
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	priv->clk = devm_clk_get(dev, "fck");
50262306a36Sopenharmony_ci	if (IS_ERR(priv->clk))
50362306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(priv->clk),
50462306a36Sopenharmony_ci				     "Failed to get IF clock\n");
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	ret = rcar_gyroadc_parse_subdevs(indio_dev);
50762306a36Sopenharmony_ci	if (ret)
50862306a36Sopenharmony_ci		return ret;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	ret = rcar_gyroadc_init_supplies(indio_dev);
51162306a36Sopenharmony_ci	if (ret)
51262306a36Sopenharmony_ci		return ret;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	priv->model = (uintptr_t)of_device_get_match_data(&pdev->dev);
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	platform_set_drvdata(pdev, indio_dev);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	indio_dev->name = DRIVER_NAME;
51962306a36Sopenharmony_ci	indio_dev->info = &rcar_gyroadc_iio_info;
52062306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	ret = clk_prepare_enable(priv->clk);
52362306a36Sopenharmony_ci	if (ret) {
52462306a36Sopenharmony_ci		dev_err(dev, "Could not prepare or enable the IF clock.\n");
52562306a36Sopenharmony_ci		goto err_clk_if_enable;
52662306a36Sopenharmony_ci	}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	pm_runtime_set_autosuspend_delay(dev, RCAR_GYROADC_RUNTIME_PM_DELAY_MS);
52962306a36Sopenharmony_ci	pm_runtime_use_autosuspend(dev);
53062306a36Sopenharmony_ci	pm_runtime_enable(dev);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(dev);
53362306a36Sopenharmony_ci	if (ret)
53462306a36Sopenharmony_ci		goto err_power_up;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	rcar_gyroadc_hw_init(priv);
53762306a36Sopenharmony_ci	rcar_gyroadc_hw_start(priv);
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	ret = iio_device_register(indio_dev);
54062306a36Sopenharmony_ci	if (ret) {
54162306a36Sopenharmony_ci		dev_err(dev, "Couldn't register IIO device.\n");
54262306a36Sopenharmony_ci		goto err_iio_device_register;
54362306a36Sopenharmony_ci	}
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	pm_runtime_put_sync(dev);
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	return 0;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_cierr_iio_device_register:
55062306a36Sopenharmony_ci	rcar_gyroadc_hw_stop(priv);
55162306a36Sopenharmony_ci	pm_runtime_put_sync(dev);
55262306a36Sopenharmony_cierr_power_up:
55362306a36Sopenharmony_ci	pm_runtime_disable(dev);
55462306a36Sopenharmony_ci	pm_runtime_set_suspended(dev);
55562306a36Sopenharmony_ci	clk_disable_unprepare(priv->clk);
55662306a36Sopenharmony_cierr_clk_if_enable:
55762306a36Sopenharmony_ci	rcar_gyroadc_deinit_supplies(indio_dev);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	return ret;
56062306a36Sopenharmony_ci}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_cistatic int rcar_gyroadc_remove(struct platform_device *pdev)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
56562306a36Sopenharmony_ci	struct rcar_gyroadc *priv = iio_priv(indio_dev);
56662306a36Sopenharmony_ci	struct device *dev = priv->dev;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	iio_device_unregister(indio_dev);
56962306a36Sopenharmony_ci	pm_runtime_get_sync(dev);
57062306a36Sopenharmony_ci	rcar_gyroadc_hw_stop(priv);
57162306a36Sopenharmony_ci	pm_runtime_put_sync(dev);
57262306a36Sopenharmony_ci	pm_runtime_disable(dev);
57362306a36Sopenharmony_ci	pm_runtime_set_suspended(dev);
57462306a36Sopenharmony_ci	clk_disable_unprepare(priv->clk);
57562306a36Sopenharmony_ci	rcar_gyroadc_deinit_supplies(indio_dev);
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	return 0;
57862306a36Sopenharmony_ci}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_cistatic int rcar_gyroadc_suspend(struct device *dev)
58162306a36Sopenharmony_ci{
58262306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
58362306a36Sopenharmony_ci	struct rcar_gyroadc *priv = iio_priv(indio_dev);
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	rcar_gyroadc_hw_stop(priv);
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	return 0;
58862306a36Sopenharmony_ci}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_cistatic int rcar_gyroadc_resume(struct device *dev)
59162306a36Sopenharmony_ci{
59262306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
59362306a36Sopenharmony_ci	struct rcar_gyroadc *priv = iio_priv(indio_dev);
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	rcar_gyroadc_hw_start(priv);
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	return 0;
59862306a36Sopenharmony_ci}
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_cistatic const struct dev_pm_ops rcar_gyroadc_pm_ops = {
60162306a36Sopenharmony_ci	RUNTIME_PM_OPS(rcar_gyroadc_suspend, rcar_gyroadc_resume, NULL)
60262306a36Sopenharmony_ci};
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_cistatic struct platform_driver rcar_gyroadc_driver = {
60562306a36Sopenharmony_ci	.probe          = rcar_gyroadc_probe,
60662306a36Sopenharmony_ci	.remove         = rcar_gyroadc_remove,
60762306a36Sopenharmony_ci	.driver         = {
60862306a36Sopenharmony_ci		.name		= DRIVER_NAME,
60962306a36Sopenharmony_ci		.of_match_table	= rcar_gyroadc_match,
61062306a36Sopenharmony_ci		.pm		= pm_ptr(&rcar_gyroadc_pm_ops),
61162306a36Sopenharmony_ci	},
61262306a36Sopenharmony_ci};
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_cimodule_platform_driver(rcar_gyroadc_driver);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ciMODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
61762306a36Sopenharmony_ciMODULE_DESCRIPTION("Renesas R-Car GyroADC driver");
61862306a36Sopenharmony_ciMODULE_LICENSE("GPL");
619