drivers/char/hw_random/jh7110-trng.c

Source file repositories/reference/linux-study-clean/drivers/char/hw_random/jh7110-trng.c

File Facts

System
Linux kernel
Corpus path
drivers/char/hw_random/jh7110-trng.c
Extension
.c
Size
10221 bytes
Lines
401
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct starfive_trng {
	struct device		*dev;
	void __iomem		*base;
	struct clk		*hclk;
	struct clk		*ahb;
	struct reset_control	*rst;
	struct hwrng		rng;
	struct completion	random_done;
	struct completion	reseed_done;
	u32			mode;
	u32			mission;
	u32			reseed;
	/* protects against concurrent write to ctrl register */
	spinlock_t		write_lock;
};

static u16 autoreq;
module_param(autoreq, ushort, 0);
MODULE_PARM_DESC(autoreq, "Auto-reseeding after random number requests by host reaches specified counter:\n"
				" 0 - disable counter\n"
				" other - reload value for internal counter");

static u16 autoage;
module_param(autoage, ushort, 0);
MODULE_PARM_DESC(autoage, "Auto-reseeding after specified timer countdowns to 0:\n"
				" 0 - disable timer\n"
				" other - reload value for internal timer");

static inline int starfive_trng_wait_idle(struct starfive_trng *trng)
{
	u32 stat;

	return readl_relaxed_poll_timeout(trng->base + STARFIVE_STAT, stat,
					  !(stat & (STARFIVE_STAT_RAND_GENERATING |
						    STARFIVE_STAT_RAND_SEEDING)),
					  10, 100000);
}

static inline void starfive_trng_irq_mask_clear(struct starfive_trng *trng)
{
	/* clear register: ISTAT */
	u32 data = readl(trng->base + STARFIVE_ISTAT);

	writel(data, trng->base + STARFIVE_ISTAT);
}

static int starfive_trng_cmd(struct starfive_trng *trng, u32 cmd, bool wait)
{
	int wait_time = 1000;

	/* allow up to 40 us for wait == 0 */
	if (!wait)
		wait_time = 40;

	switch (cmd) {
	case STARFIVE_CTRL_GENE_RANDNUM:
		reinit_completion(&trng->random_done);
		spin_lock_irq(&trng->write_lock);
		writel(cmd, trng->base + STARFIVE_CTRL);
		spin_unlock_irq(&trng->write_lock);
		if (!wait_for_completion_timeout(&trng->random_done, usecs_to_jiffies(wait_time)))
			return -ETIMEDOUT;
		break;
	case STARFIVE_CTRL_EXEC_RANDRESEED:
		reinit_completion(&trng->reseed_done);
		spin_lock_irq(&trng->write_lock);
		writel(cmd, trng->base + STARFIVE_CTRL);
		spin_unlock_irq(&trng->write_lock);
		if (!wait_for_completion_timeout(&trng->reseed_done, usecs_to_jiffies(wait_time)))
			return -ETIMEDOUT;
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int starfive_trng_init(struct hwrng *rng)
{
	struct starfive_trng *trng = to_trng(rng);
	u32 mode, intr = 0;

	/* setup Auto Request/Age register */
	writel(autoage, trng->base + STARFIVE_AUTO_AGE);
	writel(autoreq, trng->base + STARFIVE_AUTO_RQSTS);

	/* clear register: ISTAT */
	starfive_trng_irq_mask_clear(trng);

Annotation

Implementation Notes