drivers/clocksource/exynos_mct.c
Source file repositories/reference/linux-study-clean/drivers/clocksource/exynos_mct.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clocksource/exynos_mct.c- Extension
.c- Size
- 18461 bytes
- Lines
- 701
- Domain
- Driver Families
- Bucket
- drivers/clocksource
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/interrupt.hlinux/irq.hlinux/err.hlinux/clk.hlinux/clockchips.hlinux/cpu.hlinux/delay.hlinux/percpu.hlinux/of.hlinux/of_irq.hlinux/of_address.hlinux/clocksource.hlinux/sched_clock.h
Detected Declarations
struct mct_clock_event_devicefunction exynos4_mct_writefunction exynos4_mct_frc_startfunction slowfunction counterfunction exynos4_frc_readfunction exynos4_frc_resumefunction exynos4_read_sched_clockfunction exynos4_read_current_timerfunction exynos4_clocksource_initfunction exynos4_mct_comp0_stopfunction exynos4_mct_comp0_startfunction exynos4_comp_set_next_eventfunction mct_set_state_shutdownfunction mct_set_state_periodicfunction exynos4_mct_comp_isrfunction exynos4_clockevent_initfunction exynos4_mct_tick_stopfunction exynos4_mct_tick_startfunction exynos4_mct_tick_clearfunction exynos4_tick_set_next_eventfunction set_state_shutdownfunction set_state_periodicfunction exynos4_mct_tick_isrfunction exynos4_mct_starting_cpufunction exynos4_mct_dying_cpufunction exynos4_timer_resourcesfunction exynos4_timer_interruptsfunction for_each_possible_cpufunction for_each_possible_cpufunction for_each_possible_cpufunction mct_init_dtfunction mct_init_spifunction mct_init_ppi
Annotated Snippet
struct mct_clock_event_device {
struct clock_event_device evt;
unsigned long base;
/**
* The length of the name must be adjusted if number of
* local timer interrupts grow over two digits
*/
char name[11];
};
static void exynos4_mct_write(unsigned int value, unsigned long offset)
{
unsigned long stat_addr;
u32 mask;
u32 i;
writel_relaxed(value, reg_base + offset);
if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
stat_addr = (offset & EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
switch (offset & ~EXYNOS4_MCT_L_MASK) {
case MCT_L_TCON_OFFSET:
mask = 1 << 3; /* L_TCON write status */
break;
case MCT_L_ICNTB_OFFSET:
mask = 1 << 1; /* L_ICNTB write status */
break;
case MCT_L_TCNTB_OFFSET:
mask = 1 << 0; /* L_TCNTB write status */
break;
default:
return;
}
} else {
switch (offset) {
case EXYNOS4_MCT_G_TCON:
stat_addr = EXYNOS4_MCT_G_WSTAT;
mask = 1 << 16; /* G_TCON write status */
break;
case EXYNOS4_MCT_G_COMP0_L:
stat_addr = EXYNOS4_MCT_G_WSTAT;
mask = 1 << 0; /* G_COMP0_L write status */
break;
case EXYNOS4_MCT_G_COMP0_U:
stat_addr = EXYNOS4_MCT_G_WSTAT;
mask = 1 << 1; /* G_COMP0_U write status */
break;
case EXYNOS4_MCT_G_COMP0_ADD_INCR:
stat_addr = EXYNOS4_MCT_G_WSTAT;
mask = 1 << 2; /* G_COMP0_ADD_INCR w status */
break;
case EXYNOS4_MCT_G_CNT_L:
stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
mask = 1 << 0; /* G_CNT_L write status */
break;
case EXYNOS4_MCT_G_CNT_U:
stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
mask = 1 << 1; /* G_CNT_U write status */
break;
default:
return;
}
}
/* Wait maximum 1 ms until written values are applied */
for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
if (readl_relaxed(reg_base + stat_addr) & mask) {
writel_relaxed(mask, reg_base + stat_addr);
return;
}
panic("MCT hangs after writing %d (offset:0x%lx)\n", value, offset);
}
/* Clocksource handling */
static void exynos4_mct_frc_start(void)
{
u32 reg;
reg = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
reg |= MCT_G_TCON_START;
exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
}
/**
* exynos4_read_count_64 - Read all 64-bits of the global counter
*
* This will read all 64-bits of the global counter taking care to make sure
* that the upper and lower half match. Note that reading the MCT can be quite
* slow (hundreds of nanoseconds) so you should use the 32-bit (lower half
Annotation
- Immediate include surface: `linux/interrupt.h`, `linux/irq.h`, `linux/err.h`, `linux/clk.h`, `linux/clockchips.h`, `linux/cpu.h`, `linux/delay.h`, `linux/percpu.h`.
- Detected declarations: `struct mct_clock_event_device`, `function exynos4_mct_write`, `function exynos4_mct_frc_start`, `function slow`, `function counter`, `function exynos4_frc_read`, `function exynos4_frc_resume`, `function exynos4_read_sched_clock`, `function exynos4_read_current_timer`, `function exynos4_clocksource_init`.
- Atlas domain: Driver Families / drivers/clocksource.
- 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.