drivers/iio/dac/adi-axi-dac.c

Source file repositories/reference/linux-study-clean/drivers/iio/dac/adi-axi-dac.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/dac/adi-axi-dac.c
Extension
.c
Size
27784 bytes
Lines
1043
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 axi_dac_info {
	unsigned int version;
	const struct iio_backend_info *backend_info;
	bool has_dac_clk;
	bool has_child_nodes;
};

struct axi_dac_state {
	struct regmap *regmap;
	struct device *dev;
	/*
	 * lock to protect multiple accesses to the device registers and global
	 * data/variables.
	 */
	struct mutex lock;
	const struct axi_dac_info *info;
	u64 dac_clk;
	u32 reg_config;
	int dac_clk_rate;
};

static int axi_dac_enable(struct iio_backend *back)
{
	struct axi_dac_state *st = iio_backend_get_priv(back);
	unsigned int __val;
	int ret;

	guard(mutex)(&st->lock);
	ret = regmap_set_bits(st->regmap, AXI_DAC_RSTN_REG,
			      AXI_DAC_RSTN_MMCM_RSTN);
	if (ret)
		return ret;
	/*
	 * Make sure the DRP (Dynamic Reconfiguration Port) is locked. Not all
	 * designs really use it but if they don't we still get the lock bit
	 * set. So let's do it all the time so the code is generic.
	 */
	ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_DRP_STATUS_REG,
				       __val,
				       __val & AXI_DAC_DRP_STATUS_DRP_LOCKED,
				       100, 1000);
	if (ret)
		return ret;

	return regmap_set_bits(st->regmap, AXI_DAC_RSTN_REG,
			       AXI_DAC_RSTN_RSTN | AXI_DAC_RSTN_MMCM_RSTN);
}

static void axi_dac_disable(struct iio_backend *back)
{
	struct axi_dac_state *st = iio_backend_get_priv(back);

	guard(mutex)(&st->lock);
	regmap_write(st->regmap, AXI_DAC_RSTN_REG, 0);
}

static struct iio_buffer *axi_dac_request_buffer(struct iio_backend *back,
						 struct iio_dev *indio_dev)
{
	struct axi_dac_state *st = iio_backend_get_priv(back);
	const char *dma_name;

	if (device_property_read_string(st->dev, "dma-names", &dma_name))
		dma_name = "tx";

	return iio_dmaengine_buffer_setup_ext(st->dev, indio_dev, dma_name,
					      IIO_BUFFER_DIRECTION_OUT);
}

static void axi_dac_free_buffer(struct iio_backend *back,
				struct iio_buffer *buffer)
{
	iio_dmaengine_buffer_teardown(buffer);
}

enum {
	AXI_DAC_FREQ_TONE_1,
	AXI_DAC_FREQ_TONE_2,
	AXI_DAC_SCALE_TONE_1,
	AXI_DAC_SCALE_TONE_2,
	AXI_DAC_PHASE_TONE_1,
	AXI_DAC_PHASE_TONE_2,
};

static int __axi_dac_frequency_get(struct axi_dac_state *st, unsigned int chan,
				   unsigned int tone_2, unsigned int *freq)
{
	u32 reg, raw;
	int ret;

Annotation

Implementation Notes