drivers/iio/adc/mt6360-adc.c
Source file repositories/reference/linux-study-clean/drivers/iio/adc/mt6360-adc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iio/adc/mt6360-adc.c- Extension
.c- Size
- 10047 bytes
- Lines
- 373
- 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/bits.hlinux/delay.hlinux/irq.hlinux/kernel.hlinux/ktime.hlinux/mod_devicetable.hlinux/module.hlinux/mutex.hlinux/platform_device.hlinux/regmap.hlinux/iio/buffer.hlinux/iio/iio.hlinux/iio/trigger_consumer.hlinux/iio/triggered_buffer.hlinux/unaligned.h
Detected Declarations
struct mt6360_adc_datafunction mt6360_adc_read_channelfunction mt6360_adc_read_scalefunction mt6360_adc_read_offsetfunction mt6360_adc_read_rawfunction mt6360_adc_read_labelfunction mt6360_adc_trigger_handlerfunction iio_for_each_active_channelfunction mt6360_adc_resetfunction mt6360_adc_probe
Annotated Snippet
struct mt6360_adc_data {
struct device *dev;
struct regmap *regmap;
/* Due to only one set of ADC control, this lock is used to prevent the race condition */
struct mutex adc_lock;
ktime_t last_off_timestamps[MT6360_CHAN_MAX];
};
static int mt6360_adc_read_channel(struct mt6360_adc_data *mad, int channel, int *val)
{
__be16 adc_enable;
u8 rpt[3];
ktime_t predict_end_t, timeout;
unsigned int pre_wait_time;
int ret;
mutex_lock(&mad->adc_lock);
/* Select the preferred ADC channel */
ret = regmap_update_bits(mad->regmap, MT6360_REG_PMUADCRPT1, MT6360_PREFERCH_MASK,
channel << MT6360_PREFERCH_SHFT);
if (ret)
goto out_adc_lock;
adc_enable = cpu_to_be16(MT6360_ADCEN_MASK | BIT(channel));
ret = regmap_raw_write(mad->regmap, MT6360_REG_PMUADCCFG, &adc_enable, sizeof(adc_enable));
if (ret)
goto out_adc_lock;
predict_end_t = ktime_add_ms(mad->last_off_timestamps[channel], 2 * ADC_WAIT_TIME_MS);
if (ktime_after(ktime_get(), predict_end_t))
pre_wait_time = ADC_WAIT_TIME_MS;
else
pre_wait_time = 3 * ADC_WAIT_TIME_MS;
if (msleep_interruptible(pre_wait_time)) {
ret = -ERESTARTSYS;
goto out_adc_conv;
}
timeout = ktime_add_ms(ktime_get(), ADC_CONV_TIMEOUT_MS);
while (true) {
ret = regmap_raw_read(mad->regmap, MT6360_REG_PMUADCRPT1, rpt, sizeof(rpt));
if (ret)
goto out_adc_conv;
/*
* There are two functions, ZCV and TypeC OTP, running ADC VBAT and TS in
* background, and ADC samples are taken on a fixed frequency no matter read the
* previous one or not.
* To avoid conflict, We set minimum time threshold after enable ADC and
* check report channel is the same.
* The worst case is run the same ADC twice and background function is also running,
* ADC conversion sequence is desire channel before start ADC, background ADC,
* desire channel after start ADC.
* So the minimum correct data is three times of typical conversion time.
*/
if ((rpt[0] & MT6360_RPTCH_MASK) == channel)
break;
if (ktime_compare(ktime_get(), timeout) > 0) {
ret = -ETIMEDOUT;
goto out_adc_conv;
}
usleep_range(ADC_LOOP_TIME_US / 2, ADC_LOOP_TIME_US);
}
*val = get_unaligned_be16(&rpt[1]);
ret = IIO_VAL_INT;
out_adc_conv:
/* Only keep ADC enable */
adc_enable = cpu_to_be16(MT6360_ADCEN_MASK);
regmap_raw_write(mad->regmap, MT6360_REG_PMUADCCFG, &adc_enable, sizeof(adc_enable));
mad->last_off_timestamps[channel] = ktime_get();
/* Config prefer channel to NO_PREFER */
regmap_update_bits(mad->regmap, MT6360_REG_PMUADCRPT1, MT6360_PREFERCH_MASK,
MT6360_NO_PREFER << MT6360_PREFERCH_SHFT);
out_adc_lock:
mutex_unlock(&mad->adc_lock);
return ret;
}
static int mt6360_adc_read_scale(struct mt6360_adc_data *mad, int channel, int *val, int *val2)
{
unsigned int regval;
int ret;
Annotation
- Immediate include surface: `linux/bits.h`, `linux/delay.h`, `linux/irq.h`, `linux/kernel.h`, `linux/ktime.h`, `linux/mod_devicetable.h`, `linux/module.h`, `linux/mutex.h`.
- Detected declarations: `struct mt6360_adc_data`, `function mt6360_adc_read_channel`, `function mt6360_adc_read_scale`, `function mt6360_adc_read_offset`, `function mt6360_adc_read_raw`, `function mt6360_adc_read_label`, `function mt6360_adc_trigger_handler`, `function iio_for_each_active_channel`, `function mt6360_adc_reset`, `function mt6360_adc_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.