drivers/char/hw_random/xgene-rng.c
Source file repositories/reference/linux-study-clean/drivers/char/hw_random/xgene-rng.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/char/hw_random/xgene-rng.c- Extension
.c- Size
- 10764 bytes
- Lines
- 389
- Domain
- Driver Families
- Bucket
- drivers/char
- 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/acpi.hlinux/clk.hlinux/delay.hlinux/hw_random.hlinux/init.hlinux/interrupt.hlinux/io.hlinux/module.hlinux/mod_devicetable.hlinux/platform_device.hlinux/timer.h
Detected Declarations
struct xgene_rng_devfunction xgene_rng_expired_timerfunction xgene_rng_start_timerfunction oscillatorsfunction xgene_rng_chk_overflowfunction xgene_rng_irq_handlerfunction xgene_rng_data_presentfunction xgene_rng_data_readfunction xgene_rng_init_internalfunction xgene_rng_initfunction xgene_rng_probefunction xgene_rng_remove
Annotated Snippet
struct xgene_rng_dev {
u32 irq;
void __iomem *csr_base;
u32 revision;
u32 datum_size;
u32 failure_cnt; /* Failure count last minute */
unsigned long failure_ts;/* First failure timestamp */
struct timer_list failure_timer;
struct device *dev;
};
static void xgene_rng_expired_timer(struct timer_list *t)
{
struct xgene_rng_dev *ctx = timer_container_of(ctx, t, failure_timer);
/* Clear failure counter as timer expired */
disable_irq(ctx->irq);
ctx->failure_cnt = 0;
timer_delete(&ctx->failure_timer);
enable_irq(ctx->irq);
}
static void xgene_rng_start_timer(struct xgene_rng_dev *ctx)
{
ctx->failure_timer.expires = jiffies + 120 * HZ;
add_timer(&ctx->failure_timer);
}
/*
* Initialize or reinit free running oscillators (FROs)
*/
static void xgene_rng_init_fro(struct xgene_rng_dev *ctx, u32 fro_val)
{
writel(fro_val, ctx->csr_base + RNG_FRODETUNE);
writel(0x00000000, ctx->csr_base + RNG_ALARMMASK);
writel(0x00000000, ctx->csr_base + RNG_ALARMSTOP);
writel(0xFFFFFFFF, ctx->csr_base + RNG_FROENABLE);
}
static void xgene_rng_chk_overflow(struct xgene_rng_dev *ctx)
{
u32 val;
val = readl(ctx->csr_base + RNG_INTR_STS_ACK);
if (val & MONOBIT_FAIL_MASK)
/*
* LFSR detected an out-of-bounds number of 1s after
* checking 20,000 bits (test T1 as specified in the
* AIS-31 standard)
*/
dev_err(ctx->dev, "test monobit failure error 0x%08X\n", val);
if (val & POKER_FAIL_MASK)
/*
* LFSR detected an out-of-bounds value in at least one
* of the 16 poker_count_X counters or an out of bounds sum
* of squares value after checking 20,000 bits (test T2 as
* specified in the AIS-31 standard)
*/
dev_err(ctx->dev, "test poker failure error 0x%08X\n", val);
if (val & LONG_RUN_FAIL_MASK)
/*
* LFSR detected a sequence of 34 identical bits
* (test T4 as specified in the AIS-31 standard)
*/
dev_err(ctx->dev, "test long run failure error 0x%08X\n", val);
if (val & RUN_FAIL_MASK)
/*
* LFSR detected an outof-bounds value for at least one
* of the running counters after checking 20,000 bits
* (test T3 as specified in the AIS-31 standard)
*/
dev_err(ctx->dev, "test run failure error 0x%08X\n", val);
if (val & NOISE_FAIL_MASK)
/* LFSR detected a sequence of 48 identical bits */
dev_err(ctx->dev, "noise failure error 0x%08X\n", val);
if (val & STUCK_OUT_MASK)
/*
* Detected output data registers generated same value twice
* in a row
*/
dev_err(ctx->dev, "stuck out failure error 0x%08X\n", val);
if (val & SHUTDOWN_OFLO_MASK) {
u32 frostopped;
/* FROs shut down after a second error event. Try recover. */
if (++ctx->failure_cnt == 1) {
/* 1st time, just recover */
ctx->failure_ts = jiffies;
frostopped = readl(ctx->csr_base + RNG_ALARMSTOP);
Annotation
- Immediate include surface: `linux/acpi.h`, `linux/clk.h`, `linux/delay.h`, `linux/hw_random.h`, `linux/init.h`, `linux/interrupt.h`, `linux/io.h`, `linux/module.h`.
- Detected declarations: `struct xgene_rng_dev`, `function xgene_rng_expired_timer`, `function xgene_rng_start_timer`, `function oscillators`, `function xgene_rng_chk_overflow`, `function xgene_rng_irq_handler`, `function xgene_rng_data_present`, `function xgene_rng_data_read`, `function xgene_rng_init_internal`, `function xgene_rng_init`.
- Atlas domain: Driver Families / drivers/char.
- 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.