drivers/iio/adc/ep93xx_adc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/ep93xx_adc.c
Extension
.c
Size
6800 bytes
Lines
249
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 ep93xx_adc_priv {
	struct clk *clk;
	void __iomem *base;
	int lastch;
	struct mutex lock;
};

#define EP93XX_ADC_CH(index, dname, swcfg) {			\
	.type = IIO_VOLTAGE,					\
	.indexed = 1,						\
	.channel = index,					\
	.address = swcfg,					\
	.datasheet_name = dname,				\
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) |	\
				   BIT(IIO_CHAN_INFO_OFFSET),	\
}

/*
 * Numbering scheme for channels 0..4 is defined in EP9301 and EP9302 datasheets.
 * EP9307, EP9312 and EP9312 have 3 channels more (total 8), but the numbering is
 * not defined. So the last three are numbered randomly, let's say.
 */
static const struct iio_chan_spec ep93xx_adc_channels[8] = {
	EP93XX_ADC_CH(0, "YM",	0x608),
	EP93XX_ADC_CH(1, "SXP",	0x680),
	EP93XX_ADC_CH(2, "SXM",	0x640),
	EP93XX_ADC_CH(3, "SYP",	0x620),
	EP93XX_ADC_CH(4, "SYM",	0x610),
	EP93XX_ADC_CH(5, "XP",	0x601),
	EP93XX_ADC_CH(6, "XM",	0x602),
	EP93XX_ADC_CH(7, "YP",	0x604),
};

static int ep93xx_read_raw(struct iio_dev *iiodev,
			   struct iio_chan_spec const *channel, int *value,
			   int *shift, long mask)
{
	struct ep93xx_adc_priv *priv = iio_priv(iiodev);
	unsigned long timeout;
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		mutex_lock(&priv->lock);
		if (priv->lastch != channel->channel) {
			priv->lastch = channel->channel;
			/*
			 * Switch register is software-locked, unlocking must be
			 * immediately followed by write
			 */
			local_irq_disable();
			writel_relaxed(0xAA, priv->base + EP93XX_ADC_SW_LOCK);
			writel_relaxed(channel->address,
				       priv->base + EP93XX_ADC_SWITCH);
			local_irq_enable();
			/*
			 * Settling delay depends on module clock and could be
			 * 2ms or 500us
			 */
			ep93xx_adc_delay(2000, 2000);
		}
		/* Start the conversion, eventually discarding old result */
		readl_relaxed(priv->base + EP93XX_ADC_RESULT);
		/* Ensure maximum conversion rate is not exceeded */
		ep93xx_adc_delay(DIV_ROUND_UP(1000000, 925),
				 DIV_ROUND_UP(1000000, 925));
		/* At this point conversion must be completed, but anyway... */
		ret = IIO_VAL_INT;
		timeout = jiffies + msecs_to_jiffies(1) + 1;
		while (1) {
			u32 t;

			t = readl_relaxed(priv->base + EP93XX_ADC_RESULT);
			if (t & EP93XX_ADC_SDR) {
				*value = sign_extend32(t, 15);
				break;
			}

			if (time_after(jiffies, timeout)) {
				dev_err(&iiodev->dev, "Conversion timeout\n");
				ret = -ETIMEDOUT;
				break;
			}

			cpu_relax();
		}
		mutex_unlock(&priv->lock);
		return ret;

Annotation

Implementation Notes