drivers/iio/adc/berlin2-adc.c

Source file repositories/reference/linux-study-clean/drivers/iio/adc/berlin2-adc.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/berlin2-adc.c
Extension
.c
Size
10437 bytes
Lines
370
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 berlin2_adc_priv {
	struct regmap		*regmap;
	struct mutex		lock;
	wait_queue_head_t	wq;
	bool			data_available;
	int			data;
};

#define BERLIN2_ADC_CHANNEL(n, t)					\
	{								\
		.channel		= n,				\
		.datasheet_name		= "channel"#n,			\
		.type			= t,				\
		.indexed		= 1,				\
		.info_mask_separate	= BIT(IIO_CHAN_INFO_RAW),	\
	}

static const struct iio_chan_spec berlin2_adc_channels[] = {
	BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE),	/* external input */
	BERLIN2_ADC_CHANNEL(1, IIO_VOLTAGE),	/* external input */
	BERLIN2_ADC_CHANNEL(2, IIO_VOLTAGE),	/* external input */
	BERLIN2_ADC_CHANNEL(3, IIO_VOLTAGE),	/* external input */
	BERLIN2_ADC_CHANNEL(4, IIO_VOLTAGE),	/* reserved */
	BERLIN2_ADC_CHANNEL(5, IIO_VOLTAGE),	/* reserved */
	{					/* temperature sensor */
		.channel		= 6,
		.datasheet_name		= "channel6",
		.type			= IIO_TEMP,
		.indexed		= 0,
		.info_mask_separate	= BIT(IIO_CHAN_INFO_PROCESSED),
	},
	BERLIN2_ADC_CHANNEL(7, IIO_VOLTAGE),	/* reserved */
	IIO_CHAN_SOFT_TIMESTAMP(8),		/* timestamp */
};

static int berlin2_adc_read(struct iio_dev *indio_dev, int channel)
{
	struct berlin2_adc_priv *priv = iio_priv(indio_dev);
	int data, ret;

	mutex_lock(&priv->lock);

	/* Enable the interrupts */
	regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS,
		     BERLIN2_SM_ADC_STATUS_INT_EN(channel));

	/* Configure the ADC */
	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
			   BERLIN2_SM_CTRL_ADC_RESET |
			   BERLIN2_SM_CTRL_ADC_SEL_MASK |
			   BERLIN2_SM_CTRL_ADC_START,
			   BERLIN2_SM_CTRL_ADC_SEL(channel) |
			   BERLIN2_SM_CTRL_ADC_START);

	ret = wait_event_interruptible_timeout(priv->wq, priv->data_available,
					       msecs_to_jiffies(1000));

	/* Disable the interrupts */
	regmap_clear_bits(priv->regmap, BERLIN2_SM_ADC_STATUS,
			  BERLIN2_SM_ADC_STATUS_INT_EN(channel));

	if (ret == 0)
		ret = -ETIMEDOUT;
	if (ret < 0) {
		mutex_unlock(&priv->lock);
		return ret;
	}

	regmap_clear_bits(priv->regmap, BERLIN2_SM_CTRL,
			  BERLIN2_SM_CTRL_ADC_START);

	data = priv->data;
	priv->data_available = false;

	mutex_unlock(&priv->lock);

	return data;
}

static int berlin2_adc_tsen_read(struct iio_dev *indio_dev)
{
	struct berlin2_adc_priv *priv = iio_priv(indio_dev);
	int data, ret;

	mutex_lock(&priv->lock);

	/* Enable interrupts */
	regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS,
		     BERLIN2_SM_TSEN_STATUS_INT_EN);

Annotation

Implementation Notes