drivers/iio/adc/rcar-gyroadc.c

Source file repositories/reference/linux-study-clean/drivers/iio/adc/rcar-gyroadc.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/rcar-gyroadc.c
Extension
.c
Size
14847 bytes
Lines
605
Domain
Driver Families
Bucket
drivers/iio
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct rcar_gyroadc {
	struct device			*dev;
	void __iomem			*regs;
	struct clk			*clk;
	struct regulator		*vref[8];
	unsigned int			num_channels;
	enum rcar_gyroadc_model		model;
	unsigned int			mode;
	unsigned int			sample_width;
};

static void rcar_gyroadc_hw_init(struct rcar_gyroadc *priv)
{
	const unsigned long clk_mhz = clk_get_rate(priv->clk) / 1000000;
	const unsigned long clk_mul =
		(priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) ? 10 : 5;
	unsigned long clk_len = clk_mhz * clk_mul;

	/*
	 * According to the R-Car Gen2 datasheet Rev. 1.01, Sept 08 2014,
	 * page 77-7, clock length must be even number. If it's odd number,
	 * add one.
	 */
	if (clk_len & 1)
		clk_len++;

	/* Stop the GyroADC. */
	writel(0, priv->regs + RCAR_GYROADC_START_STOP);

	/* Disable IRQ on V2H. */
	if (priv->model == RCAR_GYROADC_MODEL_R8A7792)
		writel(0, priv->regs + RCAR_GYROADC_INTENR);

	/* Set mode and timing. */
	writel(priv->mode, priv->regs + RCAR_GYROADC_MODE_SELECT);
	writel(clk_len, priv->regs + RCAR_GYROADC_CLOCK_LENGTH);
	writel(clk_mhz * 1250, priv->regs + RCAR_GYROADC_1_25MS_LENGTH);
}

static void rcar_gyroadc_hw_start(struct rcar_gyroadc *priv)
{
	/* Start sampling. */
	writel(RCAR_GYROADC_START_STOP_START,
	       priv->regs + RCAR_GYROADC_START_STOP);

	/*
	 * Wait for the first conversion to complete. This is longer than
	 * the 1.25 mS in the datasheet because 1.25 mS is not enough for
	 * the hardware to deliver the first sample and the hardware does
	 * then return zeroes instead of valid data.
	 */
	mdelay(3);
}

static void rcar_gyroadc_hw_stop(struct rcar_gyroadc *priv)
{
	/* Stop the GyroADC. */
	writel(0, priv->regs + RCAR_GYROADC_START_STOP);
}

#define RCAR_GYROADC_CHAN(_idx) {				\
	.type			= IIO_VOLTAGE,			\
	.indexed		= 1,				\
	.channel		= (_idx),			\
	.info_mask_separate	= BIT(IIO_CHAN_INFO_RAW) |	\
				  BIT(IIO_CHAN_INFO_SCALE),	\
	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
}

static const struct iio_chan_spec rcar_gyroadc_iio_channels_1[] = {
	RCAR_GYROADC_CHAN(0),
	RCAR_GYROADC_CHAN(1),
	RCAR_GYROADC_CHAN(2),
	RCAR_GYROADC_CHAN(3),
};

static const struct iio_chan_spec rcar_gyroadc_iio_channels_2[] = {
	RCAR_GYROADC_CHAN(0),
	RCAR_GYROADC_CHAN(1),
	RCAR_GYROADC_CHAN(2),
	RCAR_GYROADC_CHAN(3),
	RCAR_GYROADC_CHAN(4),
	RCAR_GYROADC_CHAN(5),
	RCAR_GYROADC_CHAN(6),
	RCAR_GYROADC_CHAN(7),
};

static const struct iio_chan_spec rcar_gyroadc_iio_channels_3[] = {
	RCAR_GYROADC_CHAN(0),
	RCAR_GYROADC_CHAN(1),

Annotation

Implementation Notes