drivers/iio/proximity/d3323aa.c

Source file repositories/reference/linux-study-clean/drivers/iio/proximity/d3323aa.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/proximity/d3323aa.c
Extension
.c
Size
23734 bytes
Lines
816
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 d3323aa_data {
	struct completion reset_completion;
	/*
	 *  Since the setup process always requires a complete write of _all_
	 *  the state variables, we need to synchronize them with a lock.
	 */
	struct mutex statevar_lock;

	struct device *dev;

	/* Supply voltage. */
	struct regulator *regulator_vdd;
	/* Input clock or output detection signal (Vout). */
	struct gpio_desc *gpiod_clkin_detectout;
	/* Input (setting) or output data. */
	struct gpio_desc *gpiod_data;

	/*
	 * We only need the low-pass cutoff frequency to unambiguously choose
	 * the type of band-pass filter. For example, both filter type B and C
	 * have 0.3 Hz as high-pass cutoff frequency (see
	 * d3323aa_hp_filter_freq).
	 */
	size_t lp_filter_freq_idx;
	size_t filter_gain_idx;
	u8 detect_thresh;
	u8 irq_reset_count;

	/* Indicator for operational mode (configuring or detecting). */
	bool detecting;
};

static int d3323aa_read_settings(struct iio_dev *indio_dev,
				 unsigned long *regbitmap)
{
	struct d3323aa_data *data = iio_priv(indio_dev);
	size_t i;
	int ret;

	/* Bit bang the clock and data pins. */
	ret = gpiod_direction_output(data->gpiod_clkin_detectout, 0);
	if (ret)
		return ret;

	ret = gpiod_direction_input(data->gpiod_data);
	if (ret)
		return ret;

	dev_dbg(data->dev, "Reading settings...\n");

	for (i = 0; i < D3323AA_REG_NR_BITS; ++i) {
		/* Clock frequency needs to be 1 kHz. */
		gpiod_set_value(data->gpiod_clkin_detectout, 1);
		udelay(500);

		/* The data seems to change when clock signal is high. */
		if (gpiod_get_value(data->gpiod_data))
			set_bit(i, regbitmap);

		gpiod_set_value(data->gpiod_clkin_detectout, 0);
		udelay(500);
	}

	/* The first bit (F37) is just dummy data. Discard it. */
	clear_bit(0, regbitmap);

	/* Datasheet says to wait 30 ms after reading the settings. */
	msleep(30);

	return 0;
}

static int d3323aa_write_settings(struct iio_dev *indio_dev,
				  unsigned long *written_regbitmap)
{
#define REGBITMAP_LEN \
	(D3323AA_REG_NR_BITS + D3323AA_SETTING_END_PATTERN_NR_BITS)
	DECLARE_BITMAP(regbitmap, REGBITMAP_LEN);
	struct d3323aa_data *data = iio_priv(indio_dev);
	size_t i;
	int ret;

	/* Build the register bitmap. */
	bitmap_zero(regbitmap, REGBITMAP_LEN);
	bitmap_write(regbitmap, data->detect_thresh, D3323AA_REG_BIT_DETLVLABS0,
		     D3323AA_REG_BIT_DETLVLABS7 - D3323AA_REG_BIT_DETLVLABS0 +
			     1);
	bitmap_write(regbitmap,
		     d3323aa_filter_gain_regval[data->filter_gain_idx],
		     D3323AA_REG_BIT_FSTEP0,

Annotation

Implementation Notes