drivers/iio/filter/admv8818.c

Source file repositories/reference/linux-study-clean/drivers/iio/filter/admv8818.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/filter/admv8818.c
Extension
.c
Size
20180 bytes
Lines
817
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 admv8818_state {
	struct spi_device	*spi;
	struct regmap		*regmap;
	struct clk		*clkin;
	struct notifier_block	nb;
	/* Protect against concurrent accesses to the device and data content*/
	struct mutex		lock;
	unsigned int		filter_mode;
	u64			cf_hz;
	u64			lpf_margin_hz;
	u64			hpf_margin_hz;
};

static const unsigned long long freq_range_hpf[5][2] = {
	{0ULL, 0ULL}, /* bypass */
	{1750000000ULL, 3550000000ULL},
	{3400000000ULL, 7250000000ULL},
	{6600000000, 12000000000},
	{12500000000, 19900000000}
};

static const unsigned long long freq_range_lpf[5][2] = {
	{U64_MAX, U64_MAX}, /* bypass */
	{2050000000ULL, 3850000000ULL},
	{3350000000ULL, 7250000000ULL},
	{7000000000, 13000000000},
	{12550000000, 18850000000}
};

static const struct regmap_config admv8818_regmap_config = {
	.reg_bits = 16,
	.val_bits = 8,
	.read_flag_mask = 0x80,
	.max_register = 0x1FF,
};

static const char * const admv8818_modes[] = {
	[0] = "auto",
	[1] = "manual",
	[2] = "bypass"
};

static int __admv8818_hpf_select(struct admv8818_state *st, u64 freq)
{
	int band, state, ret;
	unsigned int hpf_state = ADMV8818_STATE_MIN, hpf_band = ADMV8818_BAND_BYPASS;
	u64 freq_error, min_freq_error, freq_corner, freq_step;

	if (freq < freq_range_hpf[ADMV8818_BAND_MIN][ADMV8818_BAND_CORNER_LOW])
		goto hpf_write;

	if (freq >= freq_range_hpf[ADMV8818_BAND_MAX][ADMV8818_BAND_CORNER_HIGH]) {
		hpf_state = ADMV8818_STATE_MAX;
		hpf_band = ADMV8818_BAND_MAX;
		goto hpf_write;
	}

	/* Close HPF frequency gap between 12 and 12.5 GHz */
	if (freq >= 12000ULL * HZ_PER_MHZ && freq < 12500ULL * HZ_PER_MHZ) {
		hpf_state = ADMV8818_STATE_MAX;
		hpf_band = 3;
		goto hpf_write;
	}

	min_freq_error = U64_MAX;
	for (band = ADMV8818_BAND_MIN; band <= ADMV8818_BAND_MAX; band++) {
		/*
		 * This (and therefore all other ranges) have a corner
		 * frequency higher than the target frequency.
		 */
		if (freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW] > freq)
			break;

		freq_step = freq_range_hpf[band][ADMV8818_BAND_CORNER_HIGH] -
			    freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW];
		freq_step = div_u64(freq_step, ADMV8818_NUM_STATES - 1);

		for (state = ADMV8818_STATE_MIN; state <= ADMV8818_STATE_MAX; state++) {
			freq_corner = freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW] +
				      freq_step * state;

			/*
			 * This (and therefore all other states) have a corner
			 * frequency higher than the target frequency.
			 */
			if (freq_corner > freq)
				break;

			freq_error = freq - freq_corner;
			if (freq_error < min_freq_error) {

Annotation

Implementation Notes