drivers/iio/adc/spear_adc.c
Source file repositories/reference/linux-study-clean/drivers/iio/adc/spear_adc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iio/adc/spear_adc.c- Extension
.c- Size
- 9169 bytes
- Lines
- 365
- 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/mod_devicetable.hlinux/module.hlinux/platform_device.hlinux/property.hlinux/interrupt.hlinux/device.hlinux/kernel.hlinux/slab.hlinux/io.hlinux/bitfield.hlinux/clk.hlinux/err.hlinux/completion.hlinux/iio/iio.hlinux/iio/sysfs.h
Detected Declarations
struct adc_regs_spear3xxstruct chan_datastruct adc_regs_spear6xxstruct spear_adc_statefunction variantsfunction spear_adc_set_clkfunction spear_adc_set_ctrlfunction spear_adc_get_averagefunction spear_adc_set_scanratefunction spear_adc_read_rawfunction spear_adc_write_rawfunction spear_adc_isrfunction spear_adc_configurefunction spear_adc_probe
Annotated Snippet
struct adc_regs_spear3xx {
u32 status;
u32 average;
u32 scan_rate;
u32 clk; /* Not avail for 1340 & 1310 */
u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
u32 ch_data[SPEAR_ADC_CHANNEL_NUM];
};
struct chan_data {
u32 lsb;
u32 msb;
};
struct adc_regs_spear6xx {
u32 status;
u32 pad[2];
u32 clk;
u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
struct chan_data ch_data[SPEAR_ADC_CHANNEL_NUM];
u32 scan_rate_lo;
u32 scan_rate_hi;
struct chan_data average;
};
struct spear_adc_state {
struct device *dev;
struct adc_regs_spear3xx __iomem *adc_base_spear3xx;
struct adc_regs_spear6xx __iomem *adc_base_spear6xx;
struct clk *clk;
struct completion completion;
/*
* 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;
u32 current_clk;
u32 sampling_freq;
u32 avg_samples;
u32 vref_external;
u32 value;
};
/*
* Functions to access some SPEAr ADC register. Abstracted into
* static inline functions, because of different register offsets
* on different SoC variants (SPEAr300 vs SPEAr600 etc).
*/
static void spear_adc_set_status(struct spear_adc_state *st, u32 val)
{
__raw_writel(val, &st->adc_base_spear6xx->status);
}
static void spear_adc_set_clk(struct spear_adc_state *st, u32 val)
{
u32 clk_high, clk_low, count;
u32 apb_clk = clk_get_rate(st->clk);
count = DIV_ROUND_UP(apb_clk, val);
clk_low = count / 2;
clk_high = count - clk_low;
st->current_clk = apb_clk / count;
__raw_writel(SPEAR_ADC_CLK_LOW(clk_low) | SPEAR_ADC_CLK_HIGH(clk_high),
&st->adc_base_spear6xx->clk);
}
static void spear_adc_set_ctrl(struct spear_adc_state *st, int n,
u32 val)
{
__raw_writel(val, &st->adc_base_spear6xx->ch_ctrl[n]);
}
static u32 spear_adc_get_average(struct spear_adc_state *st)
{
if (device_is_compatible(st->dev, "st,spear600-adc")) {
return __raw_readl(&st->adc_base_spear6xx->average.msb) &
SPEAR_ADC_DATA_MASK;
} else {
return __raw_readl(&st->adc_base_spear3xx->average) &
SPEAR_ADC_DATA_MASK;
}
}
static void spear_adc_set_scanrate(struct spear_adc_state *st, u32 rate)
{
Annotation
- Immediate include surface: `linux/mod_devicetable.h`, `linux/module.h`, `linux/platform_device.h`, `linux/property.h`, `linux/interrupt.h`, `linux/device.h`, `linux/kernel.h`, `linux/slab.h`.
- Detected declarations: `struct adc_regs_spear3xx`, `struct chan_data`, `struct adc_regs_spear6xx`, `struct spear_adc_state`, `function variants`, `function spear_adc_set_clk`, `function spear_adc_set_ctrl`, `function spear_adc_get_average`, `function spear_adc_set_scanrate`, `function spear_adc_read_raw`.
- 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.