drivers/iio/frequency/ad9523.c

Source file repositories/reference/linux-study-clean/drivers/iio/frequency/ad9523.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/frequency/ad9523.c
Extension
.c
Size
29416 bytes
Lines
1029
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 ad9523_state {
	struct spi_device		*spi;
	struct ad9523_platform_data	*pdata;
	struct iio_chan_spec		ad9523_channels[AD9523_NUM_CHAN];
	struct gpio_desc		*pwrdown_gpio;
	struct gpio_desc		*reset_gpio;
	struct gpio_desc		*sync_gpio;

	unsigned long		vcxo_freq;
	unsigned long		vco_freq;
	unsigned long		vco_out_freq[AD9523_NUM_CLK_SRC];
	unsigned char		vco_out_map[AD9523_NUM_CHAN_ALT_CLK_SRC];

	/*
	 * Lock for accessing device registers. Some operations require
	 * multiple consecutive R/W operations, during which the device
	 * shouldn't be interrupted.  The buffers are also shared across
	 * all operations so need to be protected on stand alone reads and
	 * writes.
	 */
	struct mutex		lock;

	/*
	 * DMA (thus cache coherency maintenance) may require that
	 * transfer buffers live in their own cache lines.
	 */
	union {
		__be32 d32;
		u8 d8[4];
	} data[2] __aligned(IIO_DMA_MINALIGN);
};

static int ad9523_read(struct iio_dev *indio_dev, unsigned int addr)
{
	struct ad9523_state *st = iio_priv(indio_dev);
	int ret;

	/* We encode the register size 1..3 bytes into the register address.
	 * On transfer we get the size from the register datum, and make sure
	 * the result is properly aligned.
	 */

	struct spi_transfer t[] = {
		{
			.tx_buf = &st->data[0].d8[2],
			.len = 2,
		}, {
			.rx_buf = &st->data[1].d8[4 - AD9523_TRANSF_LEN(addr)],
			.len = AD9523_TRANSF_LEN(addr),
		},
	};

	st->data[0].d32 = cpu_to_be32(AD9523_READ |
				      AD9523_CNT(AD9523_TRANSF_LEN(addr)) |
				      AD9523_ADDR(addr));

	ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
	if (ret < 0)
		dev_err(&indio_dev->dev, "read failed (%d)", ret);
	else
		ret = be32_to_cpu(st->data[1].d32) & (0xFFFFFF >>
				  (8 * (3 - AD9523_TRANSF_LEN(addr))));

	return ret;
};

static int ad9523_write(struct iio_dev *indio_dev,
		unsigned int addr, unsigned int val)
{
	struct ad9523_state *st = iio_priv(indio_dev);
	int ret;
	struct spi_transfer t[] = {
		{
			.tx_buf = &st->data[0].d8[2],
			.len = 2,
		}, {
			.tx_buf = &st->data[1].d8[4 - AD9523_TRANSF_LEN(addr)],
			.len = AD9523_TRANSF_LEN(addr),
		},
	};

	st->data[0].d32 = cpu_to_be32(AD9523_WRITE |
				      AD9523_CNT(AD9523_TRANSF_LEN(addr)) |
				      AD9523_ADDR(addr));
	st->data[1].d32 = cpu_to_be32(val);

	ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));

	if (ret < 0)
		dev_err(&indio_dev->dev, "write failed (%d)", ret);

Annotation

Implementation Notes