drivers/char/hw_random/omap-rng.c

Source file repositories/reference/linux-study-clean/drivers/char/hw_random/omap-rng.c

File Facts

System
Linux kernel
Corpus path
drivers/char/hw_random/omap-rng.c
Extension
.c
Size
14479 bytes
Lines
569
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 omap_rng_pdata {
	u16	*regs;
	u32	data_size;
	u32	(*data_present)(struct omap_rng_dev *priv);
	int	(*init)(struct omap_rng_dev *priv);
	void	(*cleanup)(struct omap_rng_dev *priv);
};

struct omap_rng_dev {
	void __iomem			*base;
	struct device			*dev;
	const struct omap_rng_pdata	*pdata;
	struct hwrng rng;
	struct clk 			*clk;
	struct clk			*clk_reg;
};

static inline u32 omap_rng_read(struct omap_rng_dev *priv, u16 reg)
{
	return __raw_readl(priv->base + priv->pdata->regs[reg]);
}

static inline void omap_rng_write(struct omap_rng_dev *priv, u16 reg,
				      u32 val)
{
	__raw_writel(val, priv->base + priv->pdata->regs[reg]);
}


static int omap_rng_do_read(struct hwrng *rng, void *data, size_t max,
			    bool wait)
{
	struct omap_rng_dev *priv;
	int i, present;

	priv = (struct omap_rng_dev *)rng->priv;

	if (max < priv->pdata->data_size)
		return 0;

	for (i = 0; i < RNG_DATA_FILL_TIMEOUT; i++) {
		present = priv->pdata->data_present(priv);
		if (present || !wait)
			break;

		udelay(10);
	}
	if (!present)
		return 0;

	memcpy_fromio(data, priv->base + priv->pdata->regs[RNG_OUTPUT_0_REG],
		      priv->pdata->data_size);

	if (priv->pdata->regs[RNG_INTACK_REG])
		omap_rng_write(priv, RNG_INTACK_REG, RNG_REG_INTACK_RDY_MASK);

	return priv->pdata->data_size;
}

static int omap_rng_init(struct hwrng *rng)
{
	struct omap_rng_dev *priv;

	priv = (struct omap_rng_dev *)rng->priv;
	return priv->pdata->init(priv);
}

static void omap_rng_cleanup(struct hwrng *rng)
{
	struct omap_rng_dev *priv;

	priv = (struct omap_rng_dev *)rng->priv;
	priv->pdata->cleanup(priv);
}


static inline u32 omap2_rng_data_present(struct omap_rng_dev *priv)
{
	return omap_rng_read(priv, RNG_STATUS_REG) ? 0 : 1;
}

static int omap2_rng_init(struct omap_rng_dev *priv)
{
	omap_rng_write(priv, RNG_SYSCONFIG_REG, 0x1);
	return 0;
}

static void omap2_rng_cleanup(struct omap_rng_dev *priv)
{
	omap_rng_write(priv, RNG_SYSCONFIG_REG, 0x0);

Annotation

Implementation Notes