drivers/staging/iio/frequency/ad9832.c

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

File Facts

System
Linux kernel
Corpus path
drivers/staging/iio/frequency/ad9832.c
Extension
.c
Size
11354 bytes
Lines
399
Domain
Driver Families
Bucket
drivers/staging
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 ad9832_state {
	struct spi_device		*spi;
	struct clk			*mclk;
	unsigned short			ctrl_fp;
	unsigned short			ctrl_ss;
	unsigned short			ctrl_src;
	struct spi_transfer		xfer;
	struct spi_message		msg;
	struct spi_transfer		freq_xfer[4];
	struct spi_message		freq_msg;
	struct spi_transfer		phase_xfer[2];
	struct spi_message		phase_msg;
	struct mutex			lock;	/* protect sensor state */
	/*
	 * DMA (thus cache coherency maintenance) requires the
	 * transfer buffers to live in their own cache lines.
	 */
	union {
		__be16			freq_data[4];
		__be16			phase_data[2];
		__be16			data;
	} __aligned(IIO_DMA_MINALIGN);
};

static unsigned long ad9832_calc_freqreg(unsigned long mclk, unsigned long fout)
{
	unsigned long long freqreg = (u64)fout *
				     (u64)((u64)1L << AD9832_FREQ_BITS);
	do_div(freqreg, mclk);
	return freqreg;
}

static int ad9832_write_frequency(struct ad9832_state *st,
				  unsigned int addr, unsigned long fout)
{
	unsigned long clk_freq;
	unsigned long regval;
	u8 regval_bytes[4];
	u16 freq_cmd;

	clk_freq = clk_get_rate(st->mclk);

	if (!clk_freq || fout > (clk_freq / 2))
		return -EINVAL;

	regval = ad9832_calc_freqreg(clk_freq, fout);
	put_unaligned_be32(regval, regval_bytes);

	for (int i = 0; i < ARRAY_SIZE(regval_bytes); i++) {
		freq_cmd = (i % 2 == 0) ? AD9832_CMD_FRE8BITSW : AD9832_CMD_FRE16BITSW;

		st->freq_data[i] = cpu_to_be16(FIELD_PREP(AD9832_CMD_MSK, freq_cmd) |
			FIELD_PREP(AD9832_ADD_MSK, addr - i) |
			FIELD_PREP(AD9832_DAT_MSK, regval_bytes[i]));
	}

	return spi_sync(st->spi, &st->freq_msg);
}

static int ad9832_write_phase(struct ad9832_state *st,
			      unsigned long addr, unsigned long phase)
{
	u8 phase_bytes[2];
	u16 phase_cmd;

	if (phase >= BIT(AD9832_PHASE_BITS))
		return -EINVAL;

	put_unaligned_be16(phase, phase_bytes);

	for (int i = 0; i < ARRAY_SIZE(phase_bytes); i++) {
		phase_cmd = (i % 2 == 0) ? AD9832_CMD_PHA8BITSW : AD9832_CMD_PHA16BITSW;

		st->phase_data[i] = cpu_to_be16(FIELD_PREP(AD9832_CMD_MSK, phase_cmd) |
			FIELD_PREP(AD9832_ADD_MSK, addr - i) |
			FIELD_PREP(AD9832_DAT_MSK, phase_bytes[i]));
	}

	return spi_sync(st->spi, &st->phase_msg);
}

static ssize_t ad9832_write(struct device *dev, struct device_attribute *attr,
			    const char *buf, size_t len)
{
	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
	struct ad9832_state *st = iio_priv(indio_dev);
	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
	int ret;
	unsigned long val;

Annotation

Implementation Notes