drivers/clocksource/timer-clint.c
Source file repositories/reference/linux-study-clean/drivers/clocksource/timer-clint.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clocksource/timer-clint.c- Extension
.c- Size
- 6904 bytes
- Lines
- 278
- 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/bitops.hlinux/clocksource.hlinux/clockchips.hlinux/cpu.hlinux/delay.hlinux/module.hlinux/of_address.hlinux/sched_clock.hlinux/io-64-nonatomic-lo-hi.hlinux/interrupt.hlinux/irq.hlinux/irqchip/chained_irq.hlinux/irqdomain.hlinux/of_irq.hlinux/smp.hlinux/timex.hasm/clint.h
Detected Declarations
function clint_send_ipifunction clint_clear_ipifunction clint_ipi_interruptfunction clint_get_cycles64function clint_get_cycles64function clint_rdtimefunction clint_clock_next_eventfunction clint_timer_starting_cpufunction clint_timer_dying_cpufunction clint_timer_interruptfunction clint_timer_init_dtexport clint_time_val
Annotated Snippet
if (of_irq_parse_one(np, i, &oirq)) {
pr_err("%pOFP: failed to parse irq %d.\n", np, i);
continue;
}
if ((oirq.args_count != 1) ||
(oirq.args[0] != RV_IRQ_TIMER &&
oirq.args[0] != RV_IRQ_SOFT)) {
pr_err("%pOFP: invalid irq %d (hwirq %d)\n",
np, i, oirq.args[0]);
return -ENODEV;
}
/* Find parent irq domain and map ipi irq */
if (!clint_ipi_irq &&
oirq.args[0] == RV_IRQ_SOFT &&
irq_find_host(oirq.np))
clint_ipi_irq = irq_of_parse_and_map(np, i);
/* Find parent irq domain and map timer irq */
if (!clint_timer_irq &&
oirq.args[0] == RV_IRQ_TIMER &&
irq_find_host(oirq.np))
clint_timer_irq = irq_of_parse_and_map(np, i);
}
/* If CLINT ipi or timer irq not found then fail */
if (!clint_ipi_irq || !clint_timer_irq) {
pr_err("%pOFP: ipi/timer irq not found\n", np);
return -ENODEV;
}
base = of_iomap(np, 0);
if (!base) {
pr_err("%pOFP: could not map registers\n", np);
return -ENODEV;
}
clint_ipi_base = base + CLINT_IPI_OFF;
clint_timer_cmp = base + CLINT_TIMER_CMP_OFF;
clint_timer_val = base + CLINT_TIMER_VAL_OFF;
clint_timer_freq = riscv_timebase;
#ifdef CONFIG_RISCV_M_MODE
/*
* Yes, that's an odd naming scheme. time_val is public, but hopefully
* will die in favor of something cleaner.
*/
clint_time_val = clint_timer_val;
#endif
pr_info("%pOFP: timer running at %ld Hz\n", np, clint_timer_freq);
rc = clocksource_register_hz(&clint_clocksource, clint_timer_freq);
if (rc) {
pr_err("%pOFP: clocksource register failed [%d]\n", np, rc);
goto fail_iounmap;
}
sched_clock_register(clint_get_cycles64, 64, clint_timer_freq);
rc = request_percpu_irq(clint_timer_irq, clint_timer_interrupt,
"clint-timer", &clint_clock_event);
if (rc) {
pr_err("registering percpu irq failed [%d]\n", rc);
goto fail_iounmap;
}
#ifdef CONFIG_SMP
rc = ipi_mux_create(BITS_PER_BYTE, clint_send_ipi);
if (rc <= 0) {
pr_err("unable to create muxed IPIs\n");
rc = (rc < 0) ? rc : -ENODEV;
goto fail_free_irq;
}
irq_set_chained_handler(clint_ipi_irq, clint_ipi_interrupt);
riscv_ipi_set_virq_range(rc, BITS_PER_BYTE);
clint_clear_ipi();
#endif
rc = cpuhp_setup_state(CPUHP_AP_CLINT_TIMER_STARTING,
"clockevents/clint/timer:starting",
clint_timer_starting_cpu,
clint_timer_dying_cpu);
if (rc) {
pr_err("%pOFP: cpuhp setup state failed [%d]\n", np, rc);
goto fail_free_irq;
}
Annotation
- Immediate include surface: `linux/bitops.h`, `linux/clocksource.h`, `linux/clockchips.h`, `linux/cpu.h`, `linux/delay.h`, `linux/module.h`, `linux/of_address.h`, `linux/sched_clock.h`.
- Detected declarations: `function clint_send_ipi`, `function clint_clear_ipi`, `function clint_ipi_interrupt`, `function clint_get_cycles64`, `function clint_get_cycles64`, `function clint_rdtime`, `function clint_clock_next_event`, `function clint_timer_starting_cpu`, `function clint_timer_dying_cpu`, `function clint_timer_interrupt`.
- 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.