drivers/input/touchscreen/imx6ul_tsc.c
Source file repositories/reference/linux-study-clean/drivers/input/touchscreen/imx6ul_tsc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/input/touchscreen/imx6ul_tsc.c- Extension
.c- Size
- 14979 bytes
- Lines
- 602
- Domain
- Driver Families
- Bucket
- drivers/input
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/errno.hlinux/kernel.hlinux/module.hlinux/bitfield.hlinux/gpio/consumer.hlinux/input.hlinux/slab.hlinux/completion.hlinux/delay.hlinux/of.hlinux/interrupt.hlinux/platform_device.hlinux/clk.hlinux/io.hlinux/log2.h
Detected Declarations
struct imx6ul_tscfunction imx6ul_adc_initfunction imx6ul_tsc_channel_configfunction imx6ul_tsc_setfunction imx6ul_tsc_initfunction imx6ul_tsc_disablefunction tsc_wait_detect_modefunction tsc_irq_fnfunction adc_irq_fnfunction imx6ul_tsc_startfunction imx6ul_tsc_stopfunction imx6ul_tsc_openfunction imx6ul_tsc_closefunction imx6ul_tsc_probefunction imx6ul_tsc_suspendfunction imx6ul_tsc_resume
Annotated Snippet
struct imx6ul_tsc {
struct device *dev;
struct input_dev *input;
void __iomem *tsc_regs;
void __iomem *adc_regs;
struct clk *tsc_clk;
struct clk *adc_clk;
struct gpio_desc *xnur_gpio;
u32 measure_delay_time;
u32 pre_charge_time;
bool average_enable;
u32 average_select;
u32 de_glitch;
struct completion completion;
};
/*
* TSC module need ADC to get the measure value. So
* before config TSC, we should initialize ADC module.
*/
static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
{
u32 adc_hc = 0;
u32 adc_gc;
u32 adc_gs;
u32 adc_cfg;
unsigned long timeout;
reinit_completion(&tsc->completion);
adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG);
adc_cfg &= ~(ADC_CONV_MODE_MASK | ADC_INPUT_CLK_MASK);
adc_cfg |= FIELD_PREP(ADC_CONV_MODE_MASK, ADC_12BIT_MODE) |
FIELD_PREP(ADC_INPUT_CLK_MASK, ADC_IPG_CLK);
adc_cfg &= ~(ADC_CLK_DIV_MASK | ADC_SAMPLE_MODE);
adc_cfg |= FIELD_PREP(ADC_CLK_DIV_MASK, ADC_CLK_DIV_8);
if (tsc->average_enable) {
adc_cfg &= ~ADC_AVGS_MASK;
adc_cfg |= FIELD_PREP(ADC_AVGS_MASK, tsc->average_select);
}
adc_cfg &= ~ADC_HARDWARE_TRIGGER;
writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG);
/* enable calibration interrupt */
adc_hc |= ADC_AIEN;
adc_hc |= FIELD_PREP(ADC_ADCH_MASK, ADC_CONV_DISABLE);
writel(adc_hc, tsc->adc_regs + REG_ADC_HC0);
/* start ADC calibration */
adc_gc = readl(tsc->adc_regs + REG_ADC_GC);
adc_gc |= ADC_CAL;
if (tsc->average_enable)
adc_gc |= ADC_AVGE;
writel(adc_gc, tsc->adc_regs + REG_ADC_GC);
timeout = wait_for_completion_timeout
(&tsc->completion, ADC_TIMEOUT);
if (timeout == 0) {
dev_err(tsc->dev, "Timeout for adc calibration\n");
return -ETIMEDOUT;
}
adc_gs = readl(tsc->adc_regs + REG_ADC_GS);
if (adc_gs & ADC_CALF) {
dev_err(tsc->dev, "ADC calibration failed\n");
return -EINVAL;
}
/* TSC need the ADC work in hardware trigger */
adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG);
adc_cfg |= ADC_HARDWARE_TRIGGER;
writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG);
return 0;
}
/*
* This is a TSC workaround. Currently TSC misconnect two
* ADC channels, this function remap channel configure for
* hardware trigger.
*/
static void imx6ul_tsc_channel_config(struct imx6ul_tsc *tsc)
{
u32 adc_hc0, adc_hc1, adc_hc2, adc_hc3, adc_hc4;
adc_hc0 = FIELD_PREP(ADC_AIEN, 0);
writel(adc_hc0, tsc->adc_regs + REG_ADC_HC0);
Annotation
- Immediate include surface: `linux/errno.h`, `linux/kernel.h`, `linux/module.h`, `linux/bitfield.h`, `linux/gpio/consumer.h`, `linux/input.h`, `linux/slab.h`, `linux/completion.h`.
- Detected declarations: `struct imx6ul_tsc`, `function imx6ul_adc_init`, `function imx6ul_tsc_channel_config`, `function imx6ul_tsc_set`, `function imx6ul_tsc_init`, `function imx6ul_tsc_disable`, `function tsc_wait_detect_mode`, `function tsc_irq_fn`, `function adc_irq_fn`, `function imx6ul_tsc_start`.
- Atlas domain: Driver Families / drivers/input.
- Implementation status: source implementation candidate.
- 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.