drivers/clocksource/arm_arch_timer_mmio.c
Source file repositories/reference/linux-study-clean/drivers/clocksource/arm_arch_timer_mmio.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clocksource/arm_arch_timer_mmio.c- Extension
.c- Size
- 11074 bytes
- Lines
- 443
- 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.
- 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/clockchips.hlinux/interrupt.hlinux/io-64-nonatomic-lo-hi.hlinux/of_irq.hlinux/of_address.hlinux/platform_device.hclocksource/arm_arch_timer.h
Detected Declarations
struct arch_timerenum arch_timer_accessfunction arch_timer_mmio_writefunction arch_timer_mmio_readfunction arch_counter_mmio_get_cntfunction arch_mmio_counter_readfunction arch_timer_mmio_shutdownfunction arch_timer_mmio_set_next_eventfunction arch_timer_mmio_handlerfunction arch_timer_mmio_setupfunction arch_timer_mmio_frame_registerfunction of_populate_gt_blockfunction for_each_available_child_of_node_scopedfunction arch_timer_mmio_probe
Annotated Snippet
struct arch_timer {
struct clock_event_device evt;
struct clocksource cs;
struct arch_timer_mem *gt_block;
void __iomem *base;
enum arch_timer_access access;
u32 rate;
};
#define evt_to_arch_timer(e) container_of(e, struct arch_timer, evt)
#define cs_to_arch_timer(c) container_of(c, struct arch_timer, cs)
static void arch_timer_mmio_write(struct arch_timer *timer,
enum arch_timer_reg reg, u64 val)
{
switch (timer->access) {
case PHYS_ACCESS:
switch (reg) {
case ARCH_TIMER_REG_CTRL:
writel_relaxed((u32)val, timer->base + CNTP_CTL);
return;
case ARCH_TIMER_REG_CVAL:
/*
* Not guaranteed to be atomic, so the timer
* must be disabled at this point.
*/
writeq_relaxed(val, timer->base + CNTP_CVAL_LO);
return;
}
break;
case VIRT_ACCESS:
switch (reg) {
case ARCH_TIMER_REG_CTRL:
writel_relaxed((u32)val, timer->base + CNTV_CTL);
return;
case ARCH_TIMER_REG_CVAL:
/* Same restriction as above */
writeq_relaxed(val, timer->base + CNTV_CVAL_LO);
return;
}
break;
}
/* Should never be here */
WARN_ON_ONCE(1);
}
static u32 arch_timer_mmio_read(struct arch_timer *timer, enum arch_timer_reg reg)
{
switch (timer->access) {
case PHYS_ACCESS:
switch (reg) {
case ARCH_TIMER_REG_CTRL:
return readl_relaxed(timer->base + CNTP_CTL);
default:
break;
}
break;
case VIRT_ACCESS:
switch (reg) {
case ARCH_TIMER_REG_CTRL:
return readl_relaxed(timer->base + CNTV_CTL);
default:
break;
}
break;
}
/* Should never be here */
WARN_ON_ONCE(1);
return 0;
}
static noinstr u64 arch_counter_mmio_get_cnt(struct arch_timer *t)
{
int offset_lo = t->access == VIRT_ACCESS ? CNTVCT_LO : CNTPCT_LO;
u32 cnt_lo, cnt_hi, tmp_hi;
do {
cnt_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));
cnt_lo = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo));
tmp_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));
} while (cnt_hi != tmp_hi);
return ((u64) cnt_hi << 32) | cnt_lo;
}
static u64 arch_mmio_counter_read(struct clocksource *cs)
{
struct arch_timer *at = cs_to_arch_timer(cs);
Annotation
- Immediate include surface: `linux/clockchips.h`, `linux/interrupt.h`, `linux/io-64-nonatomic-lo-hi.h`, `linux/of_irq.h`, `linux/of_address.h`, `linux/platform_device.h`, `clocksource/arm_arch_timer.h`.
- Detected declarations: `struct arch_timer`, `enum arch_timer_access`, `function arch_timer_mmio_write`, `function arch_timer_mmio_read`, `function arch_counter_mmio_get_cnt`, `function arch_mmio_counter_read`, `function arch_timer_mmio_shutdown`, `function arch_timer_mmio_set_next_event`, `function arch_timer_mmio_handler`, `function arch_timer_mmio_setup`.
- 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.