drivers/iio/adc/bcm_iproc_adc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/bcm_iproc_adc.c
Extension
.c
Size
17594 bytes
Lines
624
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 iproc_adc_priv {
	struct regmap *regmap;
	struct clk *adc_clk;
	struct mutex mutex;
	int  irqno;
	int chan_val;
	int chan_id;
	struct completion completion;
};

static void iproc_adc_reg_dump(struct iio_dev *indio_dev)
{
	struct device *dev = &indio_dev->dev;
	struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);

	iproc_adc_dbg_reg(dev, adc_priv, IPROC_REGCTL1);
	iproc_adc_dbg_reg(dev, adc_priv, IPROC_REGCTL2);
	iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_THRES);
	iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_MASK);
	iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_STATUS);
	iproc_adc_dbg_reg(dev, adc_priv, IPROC_CONTROLLER_STATUS);
	iproc_adc_dbg_reg(dev, adc_priv, IPROC_ANALOG_CONTROL);
	iproc_adc_dbg_reg(dev, adc_priv, IPROC_AUX_DATA);
	iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_CONTROL);
	iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_DATA);
}

static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
{
	u32 channel_intr_status;
	u32 intr_status;
	u32 intr_mask;
	struct iio_dev *indio_dev = data;
	struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);

	/*
	 * This interrupt is shared with the touchscreen driver.
	 * Make sure this interrupt is intended for us.
	 * Handle only ADC channel specific interrupts.
	 */
	regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status);
	regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &intr_mask);
	intr_status = intr_status & intr_mask;
	channel_intr_status = (intr_status & IPROC_ADC_INTR_MASK) >>
				IPROC_ADC_INTR;
	if (channel_intr_status)
		return IRQ_WAKE_THREAD;

	return IRQ_NONE;
}

static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
{
	irqreturn_t retval = IRQ_NONE;
	struct iproc_adc_priv *adc_priv;
	struct iio_dev *indio_dev = data;
	unsigned int valid_entries;
	u32 intr_status;
	u32 intr_channels;
	u32 channel_status;
	u32 ch_intr_status;

	adc_priv = iio_priv(indio_dev);

	regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status);
	dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_handler(),INTRPT_STS:%x\n",
			intr_status);

	intr_channels = (intr_status & IPROC_ADC_INTR_MASK) >> IPROC_ADC_INTR;
	if (intr_channels) {
		regmap_read(adc_priv->regmap,
			    IPROC_ADC_CHANNEL_INTERRUPT_STATUS +
			    IPROC_ADC_CHANNEL_OFFSET * adc_priv->chan_id,
			    &ch_intr_status);

		if (ch_intr_status & IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK) {
			regmap_read(adc_priv->regmap,
					IPROC_ADC_CHANNEL_STATUS +
					IPROC_ADC_CHANNEL_OFFSET *
					adc_priv->chan_id,
					&channel_status);

			valid_entries = ((channel_status &
				IPROC_ADC_CHANNEL_VALID_ENTERIES_MASK) >>
				IPROC_ADC_CHANNEL_VALID_ENTERIES);
			if (valid_entries >= 1) {
				regmap_read(adc_priv->regmap,
					IPROC_ADC_CHANNEL_DATA +
					IPROC_ADC_CHANNEL_OFFSET *
					adc_priv->chan_id,

Annotation

Implementation Notes