drivers/iio/adc/sun20i-gpadc-iio.c
Source file repositories/reference/linux-study-clean/drivers/iio/adc/sun20i-gpadc-iio.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iio/adc/sun20i-gpadc-iio.c- Extension
.c- Size
- 7231 bytes
- Lines
- 263
- 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.
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/clk.hlinux/completion.hlinux/interrupt.hlinux/io.hlinux/mod_devicetable.hlinux/module.hlinux/platform_device.hlinux/property.hlinux/reset.hlinux/iio/adc-helpers.hlinux/iio/iio.h
Detected Declarations
struct sun20i_gpadc_iiofunction sun20i_gpadc_adc_readfunction timefunction sun20i_gpadc_read_rawfunction sun20i_gpadc_irq_handlerfunction sun20i_gpadc_reset_assertfunction sun20i_gpadc_alloc_channelsfunction sun20i_gpadc_probe
Annotated Snippet
struct sun20i_gpadc_iio {
void __iomem *regs;
struct completion completion;
int last_channel;
/*
* Lock to protect the device state during a potential concurrent
* read access from userspace. Reading a raw value requires a sequence
* of register writes, then a wait for a completion callback,
* and finally a register read, during which userspace could issue
* another read request. This lock protects a read access from
* occurring before another one has finished.
*/
struct mutex lock;
};
static int sun20i_gpadc_adc_read(struct sun20i_gpadc_iio *info,
struct iio_chan_spec const *chan, int *val)
{
u32 ctrl;
int ret = IIO_VAL_INT;
mutex_lock(&info->lock);
reinit_completion(&info->completion);
if (info->last_channel != chan->channel) {
info->last_channel = chan->channel;
/* enable the analog input channel */
writel(SUN20I_GPADC_CS_EN_ADC_CH(chan->channel),
info->regs + SUN20I_GPADC_CS_EN);
/* enable the data irq for input channel */
writel(SUN20I_GPADC_DATA_INTC_CH_DATA_IRQ_EN(chan->channel),
info->regs + SUN20I_GPADC_DATA_INTC);
}
/* enable the ADC function */
ctrl = readl(info->regs + SUN20I_GPADC_CTRL);
ctrl |= FIELD_PREP(SUN20I_GPADC_CTRL_ADC_EN_MASK, 1);
writel(ctrl, info->regs + SUN20I_GPADC_CTRL);
/*
* According to the datasheet maximum acquire time(TACQ) can be
* (65535+1)/24Mhz and conversion time(CONV_TIME) is always constant
* and equal to 14/24Mhz, so (TACQ+CONV_TIME) <= 2.73125ms.
* A 10ms delay should be enough to make sure an interrupt occurs in
* normal conditions. If it doesn't occur, then there is a timeout.
*/
if (!wait_for_completion_timeout(&info->completion, msecs_to_jiffies(10))) {
ret = -ETIMEDOUT;
goto err_unlock;
}
/* read the ADC data */
*val = readl(info->regs + SUN20I_GPADC_CH_DATA(chan->channel));
err_unlock:
mutex_unlock(&info->lock);
return ret;
}
static int sun20i_gpadc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
{
struct sun20i_gpadc_iio *info = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
return sun20i_gpadc_adc_read(info, chan, val);
case IIO_CHAN_INFO_SCALE:
/* value in mv = 1800mV / 4096 raw */
*val = 1800;
*val2 = 12;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
static irqreturn_t sun20i_gpadc_irq_handler(int irq, void *data)
{
struct sun20i_gpadc_iio *info = data;
/* clear data interrupt status register */
writel(GENMASK(31, 0), info->regs + SUN20I_GPADC_DATA_INTS);
complete(&info->completion);
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/completion.h`, `linux/interrupt.h`, `linux/io.h`, `linux/mod_devicetable.h`, `linux/module.h`, `linux/platform_device.h`.
- Detected declarations: `struct sun20i_gpadc_iio`, `function sun20i_gpadc_adc_read`, `function time`, `function sun20i_gpadc_read_raw`, `function sun20i_gpadc_irq_handler`, `function sun20i_gpadc_reset_assert`, `function sun20i_gpadc_alloc_channels`, `function sun20i_gpadc_probe`.
- Atlas domain: Driver Families / drivers/iio.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.