diff options
Diffstat (limited to 'drivers/char/hw_random/atmel-rng.c')
| -rw-r--r-- | drivers/char/hw_random/atmel-rng.c | 38 |
1 files changed, 16 insertions, 22 deletions
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index f518b99f53f..851bc7e20ad 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c @@ -34,8 +34,15 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max, u32 *data = buf; /* data ready? */ - if (readl(trng->base + TRNG_ODATA) & 1) { + if (readl(trng->base + TRNG_ISR) & 1) { *data = readl(trng->base + TRNG_ODATA); + /* + ensure data ready is only set again AFTER the next data + word is ready in case it got set between checking ISR + and reading ODATA, so we don't risk re-reading the + same word + */ + readl(trng->base + TRNG_ISR); return 4; } else return 0; @@ -47,29 +54,22 @@ static int atmel_trng_probe(struct platform_device *pdev) struct resource *res; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EINVAL; - trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); if (!trng) return -ENOMEM; - if (!devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), pdev->name)) - return -EBUSY; - - trng->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!trng->base) - return -EBUSY; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + trng->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(trng->base)) + return PTR_ERR(trng->base); - trng->clk = clk_get(&pdev->dev, NULL); + trng->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(trng->clk)) return PTR_ERR(trng->clk); ret = clk_enable(trng->clk); if (ret) - goto err_enable; + return ret; writel(TRNG_KEY | 1, trng->base + TRNG_CR); trng->rng.name = pdev->name; @@ -85,13 +85,10 @@ static int atmel_trng_probe(struct platform_device *pdev) err_register: clk_disable(trng->clk); -err_enable: - clk_put(trng->clk); - return ret; } -static int __devexit atmel_trng_remove(struct platform_device *pdev) +static int atmel_trng_remove(struct platform_device *pdev) { struct atmel_trng *trng = platform_get_drvdata(pdev); @@ -99,9 +96,6 @@ static int __devexit atmel_trng_remove(struct platform_device *pdev) writel(TRNG_KEY, trng->base + TRNG_CR); clk_disable(trng->clk); - clk_put(trng->clk); - - platform_set_drvdata(pdev, NULL); return 0; } @@ -131,7 +125,7 @@ static const struct dev_pm_ops atmel_trng_pm_ops = { static struct platform_driver atmel_trng_driver = { .probe = atmel_trng_probe, - .remove = __devexit_p(atmel_trng_remove), + .remove = atmel_trng_remove, .driver = { .name = "atmel-trng", .owner = THIS_MODULE, |
