drivers/clocksource/timer-riscv.c
Source file repositories/reference/linux-study-clean/drivers/clocksource/timer-riscv.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clocksource/timer-riscv.c- Extension
.c- Size
- 6684 bytes
- Lines
- 255
- Domain
- Driver Families
- Bucket
- drivers/clocksource
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- 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/acpi.hlinux/clocksource.hlinux/clockchips.hlinux/cpu.hlinux/delay.hlinux/irq.hlinux/irqdomain.hlinux/module.hlinux/sched_clock.hlinux/io-64-nonatomic-lo-hi.hlinux/interrupt.hlinux/of_irq.hlinux/limits.hclocksource/timer-riscv.hasm/smp.hasm/cpufeature.hasm/sbi.hasm/timex.h
Detected Declarations
function riscv_clock_event_stopfunction riscv_clock_next_eventfunction riscv_clock_shutdownfunction riscv_clocksource_rdtimefunction riscv_sched_clockfunction riscv_timer_starting_cpufunction riscv_timer_dying_cpufunction riscv_cs_get_mult_shiftfunction riscv_timer_interruptfunction riscv_timer_init_commonfunction riscv_timer_init_dtfunction riscv_timer_acpi_initexport riscv_cs_get_mult_shift
Annotated Snippet
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2012 Regents of the University of California
* Copyright (C) 2017 SiFive
*
* All RISC-V systems have a timer attached to every hart. These timers can
* either be read from the "time" and "timeh" CSRs, and can use the SBI to
* setup events, or directly accessed using MMIO registers.
*/
#define pr_fmt(fmt) "riscv-timer: " fmt
#include <linux/acpi.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/cpu.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/sched_clock.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/interrupt.h>
#include <linux/of_irq.h>
#include <linux/limits.h>
#include <clocksource/timer-riscv.h>
#include <asm/smp.h>
#include <asm/cpufeature.h>
#include <asm/sbi.h>
#include <asm/timex.h>
static DEFINE_STATIC_KEY_FALSE(riscv_sstc_available);
static bool riscv_timer_cannot_wake_cpu;
static void riscv_clock_event_stop(void)
{
if (static_branch_likely(&riscv_sstc_available)) {
csr_write(CSR_STIMECMP, ULONG_MAX);
if (IS_ENABLED(CONFIG_32BIT))
csr_write(CSR_STIMECMPH, ULONG_MAX);
} else {
sbi_set_timer(U64_MAX);
}
}
static int riscv_clock_next_event(unsigned long delta,
struct clock_event_device *ce)
{
u64 next_tval = get_cycles64() + delta;
if (static_branch_likely(&riscv_sstc_available)) {
#if defined(CONFIG_32BIT)
csr_write(CSR_STIMECMP, ULONG_MAX);
csr_write(CSR_STIMECMPH, next_tval >> 32);
csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
#else
csr_write(CSR_STIMECMP, next_tval);
#endif
} else
sbi_set_timer(next_tval);
return 0;
}
static int riscv_clock_shutdown(struct clock_event_device *evt)
{
riscv_clock_event_stop();
return 0;
}
static unsigned int riscv_clock_event_irq;
static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = {
.name = "riscv_timer_clockevent",
.features = CLOCK_EVT_FEAT_ONESHOT,
.rating = 100,
.set_next_event = riscv_clock_next_event,
.set_state_shutdown = riscv_clock_shutdown,
};
/*
* It is guaranteed that all the timers across all the harts are synchronized
* within one tick of each other, so while this could technically go
* backwards when hopping between CPUs, practically it won't happen.
*/
static unsigned long long riscv_clocksource_rdtime(struct clocksource *cs)
{
return get_cycles64();
}
static u64 notrace riscv_sched_clock(void)
Annotation
- Immediate include surface: `linux/acpi.h`, `linux/clocksource.h`, `linux/clockchips.h`, `linux/cpu.h`, `linux/delay.h`, `linux/irq.h`, `linux/irqdomain.h`, `linux/module.h`.
- Detected declarations: `function riscv_clock_event_stop`, `function riscv_clock_next_event`, `function riscv_clock_shutdown`, `function riscv_clocksource_rdtime`, `function riscv_sched_clock`, `function riscv_timer_starting_cpu`, `function riscv_timer_dying_cpu`, `function riscv_cs_get_mult_shift`, `function riscv_timer_interrupt`, `function riscv_timer_init_common`.
- Atlas domain: Driver Families / drivers/clocksource.
- Implementation status: integration 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.