Skip to content

Commit

Permalink
hwrng: mxc-rnga - Access data via structure
Browse files Browse the repository at this point in the history
In current driver, everytime we need to access the rng clock
,ie to enable or disable it, a call to clk_get is done.

This is not correct and the preferred way is to provide a rng data structure
that could be used for accessing rng resources.

Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Fabio Estevam authored and Herbert Xu committed Sep 6, 2012
1 parent a9ccb7b commit 821873a
Showing 1 changed file with 51 additions and 57 deletions.
108 changes: 51 additions & 57 deletions drivers/char/hw_random/mxc-rnga.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,21 @@
#define RNGA_STATUS_LAST_READ_STATUS 0x00000002
#define RNGA_STATUS_SECURITY_VIOLATION 0x00000001

static struct platform_device *rng_dev;
struct mxc_rng {
struct device *dev;
struct hwrng rng;
void __iomem *mem;
struct clk *clk;
};

static int mxc_rnga_data_present(struct hwrng *rng, int wait)
{
void __iomem *rng_base = (void __iomem *)rng->priv;
int i;
struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);

for (i = 0; i < 20; i++) {
/* how many random numbers are in FIFO? [0-16] */
int level = (__raw_readl(rng_base + RNGA_STATUS) &
int level = (__raw_readl(mxc_rng->mem + RNGA_STATUS) &
RNGA_STATUS_LEVEL_MASK) >> 8;
if (level || !wait)
return !!level;
Expand All @@ -81,20 +86,20 @@ static int mxc_rnga_data_read(struct hwrng *rng, u32 * data)
{
int err;
u32 ctrl;
void __iomem *rng_base = (void __iomem *)rng->priv;
struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);

/* retrieve a random number from FIFO */
*data = __raw_readl(rng_base + RNGA_OUTPUT_FIFO);
*data = __raw_readl(mxc_rng->mem + RNGA_OUTPUT_FIFO);

/* some error while reading this random number? */
err = __raw_readl(rng_base + RNGA_STATUS) & RNGA_STATUS_ERROR_INT;
err = __raw_readl(mxc_rng->mem + RNGA_STATUS) & RNGA_STATUS_ERROR_INT;

/* if error: clear error interrupt, but doesn't return random number */
if (err) {
dev_dbg(&rng_dev->dev, "Error while reading random number!\n");
ctrl = __raw_readl(rng_base + RNGA_CONTROL);
dev_dbg(mxc_rng->dev, "Error while reading random number!\n");
ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
__raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT,
rng_base + RNGA_CONTROL);
mxc_rng->mem + RNGA_CONTROL);
return 0;
} else
return 4;
Expand All @@ -103,63 +108,63 @@ static int mxc_rnga_data_read(struct hwrng *rng, u32 * data)
static int mxc_rnga_init(struct hwrng *rng)
{
u32 ctrl, osc;
void __iomem *rng_base = (void __iomem *)rng->priv;
struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);

/* wake up */
ctrl = __raw_readl(rng_base + RNGA_CONTROL);
__raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, rng_base + RNGA_CONTROL);
ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
__raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, mxc_rng->mem + RNGA_CONTROL);

/* verify if oscillator is working */
osc = __raw_readl(rng_base + RNGA_STATUS);
osc = __raw_readl(mxc_rng->mem + RNGA_STATUS);
if (osc & RNGA_STATUS_OSC_DEAD) {
dev_err(&rng_dev->dev, "RNGA Oscillator is dead!\n");
dev_err(mxc_rng->dev, "RNGA Oscillator is dead!\n");
return -ENODEV;
}

/* go running */
ctrl = __raw_readl(rng_base + RNGA_CONTROL);
__raw_writel(ctrl | RNGA_CONTROL_GO, rng_base + RNGA_CONTROL);
ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
__raw_writel(ctrl | RNGA_CONTROL_GO, mxc_rng->mem + RNGA_CONTROL);

return 0;
}

static void mxc_rnga_cleanup(struct hwrng *rng)
{
u32 ctrl;
void __iomem *rng_base = (void __iomem *)rng->priv;
struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);

ctrl = __raw_readl(rng_base + RNGA_CONTROL);
ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);

/* stop rnga */
__raw_writel(ctrl & ~RNGA_CONTROL_GO, rng_base + RNGA_CONTROL);
__raw_writel(ctrl & ~RNGA_CONTROL_GO, mxc_rng->mem + RNGA_CONTROL);
}

static struct hwrng mxc_rnga = {
.name = "mxc-rnga",
.init = mxc_rnga_init,
.cleanup = mxc_rnga_cleanup,
.data_present = mxc_rnga_data_present,
.data_read = mxc_rnga_data_read
};

static int __init mxc_rnga_probe(struct platform_device *pdev)
{
int err = -ENODEV;
struct clk *clk;
struct resource *res, *mem;
void __iomem *rng_base = NULL;

if (rng_dev)
return -EBUSY;

clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
struct mxc_rng *mxc_rng;

mxc_rng = devm_kzalloc(&pdev->dev, sizeof(struct mxc_rng),
GFP_KERNEL);
if (!mxc_rng)
return -ENOMEM;

mxc_rng->dev = &pdev->dev;
mxc_rng->rng.name = "mxc-rnga";
mxc_rng->rng.init = mxc_rnga_init;
mxc_rng->rng.cleanup = mxc_rnga_cleanup,
mxc_rng->rng.data_present = mxc_rnga_data_present,
mxc_rng->rng.data_read = mxc_rnga_data_read,

mxc_rng->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(mxc_rng->clk)) {
dev_err(&pdev->dev, "Could not get rng_clk!\n");
err = PTR_ERR(clk);
err = PTR_ERR(mxc_rng->clk);
goto out;
}

clk_prepare_enable(clk);
clk_prepare_enable(mxc_rng->clk);

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
Expand All @@ -173,36 +178,27 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
goto err_region;
}

rng_base = ioremap(res->start, resource_size(res));
if (!rng_base) {
mxc_rng->mem = ioremap(res->start, resource_size(res));
if (!mxc_rng->mem) {
err = -ENOMEM;
goto err_ioremap;
}

mxc_rnga.priv = (unsigned long)rng_base;

err = hwrng_register(&mxc_rnga);
err = hwrng_register(&mxc_rng->rng);
if (err) {
dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err);
goto err_register;
goto err_ioremap;
}

rng_dev = pdev;

dev_info(&pdev->dev, "MXC RNGA Registered.\n");

return 0;

err_register:
iounmap(rng_base);
rng_base = NULL;

err_ioremap:
release_mem_region(res->start, resource_size(res));

err_region:
clk_disable_unprepare(clk);
clk_put(clk);
clk_disable_unprepare(mxc_rng->clk);

out:
return err;
Expand All @@ -211,17 +207,15 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
static int __exit mxc_rnga_remove(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *rng_base = (void __iomem *)mxc_rnga.priv;
struct clk *clk = clk_get(&pdev->dev, NULL);
struct mxc_rng *mxc_rng = platform_get_drvdata(pdev);

hwrng_unregister(&mxc_rnga);
hwrng_unregister(&mxc_rng->rng);

iounmap(rng_base);
iounmap(mxc_rng->mem);

release_mem_region(res->start, resource_size(res));

clk_disable_unprepare(clk);
clk_put(clk);
clk_disable_unprepare(mxc_rng->clk);

return 0;
}
Expand Down

0 comments on commit 821873a

Please sign in to comment.