drivers/char/hw_random/cctrng.c

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

File Facts

System
Linux kernel
Corpus path
drivers/char/hw_random/cctrng.c
Extension
.c
Size
17967 bytes
Lines
664
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 cctrng_drvdata {
	struct platform_device *pdev;
	void __iomem *cc_base;
	struct clk *clk;
	struct hwrng rng;
	u32 active_rosc;
	/* Sampling interval for each ring oscillator:
	 * count of ring oscillator cycles between consecutive bits sampling.
	 * Value of 0 indicates non-valid rosc
	 */
	u32 smpl_ratio[CC_TRNG_NUM_OF_ROSCS];

	u32 data_buf[CCTRNG_DATA_BUF_WORDS];
	struct circ_buf circ;
	struct work_struct compwork;
	struct work_struct startwork;

	/* pending_hw - 1 when HW is pending, 0 when it is idle */
	atomic_t pending_hw;

	/* protects against multiple concurrent consumers of data_buf */
	spinlock_t read_lock;
};


/* functions for write/read CC registers */
static inline void cc_iowrite(struct cctrng_drvdata *drvdata, u32 reg, u32 val)
{
	iowrite32(val, (drvdata->cc_base + reg));
}
static inline u32 cc_ioread(struct cctrng_drvdata *drvdata, u32 reg)
{
	return ioread32(drvdata->cc_base + reg);
}


static int cc_trng_pm_get(struct device *dev)
{
	int rc = 0;

	rc = pm_runtime_get_sync(dev);

	/* pm_runtime_get_sync() can return 1 as a valid return code */
	return (rc == 1 ? 0 : rc);
}

static void cc_trng_pm_put_suspend(struct device *dev)
{
	int rc = 0;

	rc = pm_runtime_put_autosuspend(dev);
	if (rc)
		dev_err(dev, "pm_runtime_put_autosuspend returned %x\n", rc);
}

static int cc_trng_pm_init(struct cctrng_drvdata *drvdata)
{
	struct device *dev = &(drvdata->pdev->dev);

	/* must be before the enabling to avoid redundant suspending */
	pm_runtime_set_autosuspend_delay(dev, CC_TRNG_SUSPEND_TIMEOUT);
	pm_runtime_use_autosuspend(dev);
	/* set us as active - note we won't do PM ops until cc_trng_pm_go()! */
	return pm_runtime_set_active(dev);
}

static void cc_trng_pm_go(struct cctrng_drvdata *drvdata)
{
	struct device *dev = &(drvdata->pdev->dev);

	/* enable the PM module*/
	pm_runtime_enable(dev);
}

static void cc_trng_pm_fini(struct cctrng_drvdata *drvdata)
{
	struct device *dev = &(drvdata->pdev->dev);

	pm_runtime_disable(dev);
}


static inline int cc_trng_parse_sampling_ratio(struct cctrng_drvdata *drvdata)
{
	struct device *dev = &(drvdata->pdev->dev);
	struct device_node *np = drvdata->pdev->dev.of_node;
	int rc;
	int i;
	/* ret will be set to 0 if at least one rosc has (sampling ratio > 0) */
	int ret = -EINVAL;

Annotation

Implementation Notes