drivers/iio/adc/imx93_adc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/imx93_adc.c
Extension
.c
Size
12597 bytes
Lines
496
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 imx93_adc {
	struct device *dev;
	void __iomem *regs;
	struct clk *ipg_clk;
	int irq;
	struct regulator *vref;
	/* lock to protect against multiple access to the device */
	struct mutex lock;
	struct completion completion;
};

#define IMX93_ADC_CHAN(_idx) {					\
	.type = IIO_VOLTAGE,					\
	.indexed = 1,						\
	.channel = (_idx),					\
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
				BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
}

static const struct iio_chan_spec imx93_adc_iio_channels[] = {
	IMX93_ADC_CHAN(0),
	IMX93_ADC_CHAN(1),
	IMX93_ADC_CHAN(2),
	IMX93_ADC_CHAN(3),
	IMX93_ADC_CHAN(4),
	IMX93_ADC_CHAN(5),
	IMX93_ADC_CHAN(6),
	IMX93_ADC_CHAN(7),
};

static void imx93_adc_power_down(struct imx93_adc *adc)
{
	u32 mcr, msr;
	int ret;

	mcr = readl(adc->regs + IMX93_ADC_MCR);
	mcr |= FIELD_PREP(IMX93_ADC_MCR_PWDN_MASK, 1);
	writel(mcr, adc->regs + IMX93_ADC_MCR);

	ret = readl_poll_timeout(adc->regs + IMX93_ADC_MSR, msr,
				 ((msr & IMX93_ADC_MSR_ADCSTATUS_MASK) ==
				  IMX93_ADC_MSR_ADCSTATUS_POWER_DOWN),
				 1, 50);
	if (ret == -ETIMEDOUT)
		dev_warn(adc->dev,
			 "ADC do not in power down mode, current MSR is %x\n",
			 msr);
}

static void imx93_adc_power_up(struct imx93_adc *adc)
{
	u32 mcr;

	/* bring ADC out of power down state, in idle state */
	mcr = readl(adc->regs + IMX93_ADC_MCR);
	mcr &= ~FIELD_PREP(IMX93_ADC_MCR_PWDN_MASK, 1);
	writel(mcr, adc->regs + IMX93_ADC_MCR);
}

static void imx93_adc_config_ad_clk(struct imx93_adc *adc)
{
	u32 mcr;

	/* put adc in power down mode */
	imx93_adc_power_down(adc);

	/* config the AD_CLK equal to bus clock */
	mcr = readl(adc->regs + IMX93_ADC_MCR);
	mcr |= FIELD_PREP(IMX93_ADC_MCR_ADCLKSE_MASK, 1);
	writel(mcr, adc->regs + IMX93_ADC_MCR);

	imx93_adc_power_up(adc);
}

static int imx93_adc_calibration(struct imx93_adc *adc)
{
	u32 mcr, msr, calcfg;
	int ret;

	/* make sure ADC in power down mode */
	imx93_adc_power_down(adc);

	/* config SAR controller operating clock */
	mcr = readl(adc->regs + IMX93_ADC_MCR);
	mcr &= ~FIELD_PREP(IMX93_ADC_MCR_ADCLKSE_MASK, 1);
	writel(mcr, adc->regs + IMX93_ADC_MCR);

	imx93_adc_power_up(adc);

Annotation

Implementation Notes