2 * omap-rng.c - RNG driver for TI OMAP CPU family
4 * Author: Deepak Saxena <dsaxena@plexity.net>
6 * Copyright 2005 (c) MontaVista Software, Inc.
8 * Mostly based on original driver:
10 * Copyright (C) 2005 Nokia Corporation
11 * Author: Juha Yrjölä <juha.yrjola@nokia.com>
13 * This file is licensed under the terms of the GNU General Public
14 * License version 2. This program is licensed "as is" without any
15 * warranty of any kind, whether express or implied.
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/random.h>
21 #include <linux/err.h>
22 #include <linux/platform_device.h>
23 #include <linux/hw_random.h>
24 #include <linux/delay.h>
25 #include <linux/slab.h>
26 #include <linux/pm_runtime.h>
28 #include <linux/of_device.h>
29 #include <linux/of_address.h>
33 #define RNG_OUT_REG 0x00 /* Output register */
34 #define RNG_STAT_REG 0x04 /* Status register
36 #define RNG_ALARM_REG 0x24 /* Alarm register
37 [7:0] = ALARM_COUNTER */
38 #define RNG_CONFIG_REG 0x28 /* Configuration register
41 [2:0] = RING1_DELAY */
42 #define RNG_REV_REG 0x3c /* Revision register
44 #define RNG_MASK_REG 0x40 /* Mask and reset register
48 #define RNG_SYSSTATUS 0x44 /* System status
52 * struct omap_rng_private_data - RNG IP block-specific data
53 * @base: virtual address of the beginning of the RNG IP block registers
54 * @mem_res: struct resource * for the IP block registers physical memory
56 struct omap_rng_private_data {
58 struct resource *mem_res;
61 static inline u32 omap_rng_read_reg(struct omap_rng_private_data *priv, int reg)
63 return __raw_readl(priv->base + reg);
66 static inline void omap_rng_write_reg(struct omap_rng_private_data *priv,
69 __raw_writel(val, priv->base + reg);
72 static int omap_rng_data_present(struct hwrng *rng, int wait)
74 struct omap_rng_private_data *priv;
77 priv = (struct omap_rng_private_data *)rng->priv;
79 for (i = 0; i < 20; i++) {
80 data = omap_rng_read_reg(priv, RNG_STAT_REG) ? 0 : 1;
83 /* RNG produces data fast enough (2+ MBit/sec, even
84 * during "rngtest" loads, that these delays don't
85 * seem to trigger. We *could* use the RNG IRQ, but
86 * that'd be higher overhead ... so why bother?
93 static int omap_rng_data_read(struct hwrng *rng, u32 *data)
95 struct omap_rng_private_data *priv;
97 priv = (struct omap_rng_private_data *)rng->priv;
99 *data = omap_rng_read_reg(priv, RNG_OUT_REG);
104 static struct hwrng omap_rng_ops = {
106 .data_present = omap_rng_data_present,
107 .data_read = omap_rng_data_read,
110 #if defined(CONFIG_OF)
111 static const struct of_device_id omap_rng_of_match[] = {
112 { .compatible = "ti,omap2-rng" },
115 MODULE_DEVICE_TABLE(of, omap_rng_of_match);
118 static int omap_rng_probe(struct platform_device *pdev)
120 struct omap_rng_private_data *priv;
123 priv = devm_kzalloc(&pdev->dev, sizeof(struct omap_rng_private_data),
126 dev_err(&pdev->dev, "could not allocate memory\n");
130 omap_rng_ops.priv = (unsigned long)priv;
131 platform_set_drvdata(pdev, priv);
133 priv->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
134 priv->base = devm_ioremap_resource(&pdev->dev, priv->mem_res);
135 if (IS_ERR(priv->base)) {
136 ret = PTR_ERR(priv->base);
140 pm_runtime_enable(&pdev->dev);
141 pm_runtime_get_sync(&pdev->dev);
143 ret = hwrng_register(&omap_rng_ops);
147 dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
148 omap_rng_read_reg(priv, RNG_REV_REG));
150 omap_rng_write_reg(priv, RNG_MASK_REG, 0x1);
156 pm_runtime_disable(&pdev->dev);
161 static int __exit omap_rng_remove(struct platform_device *pdev)
163 struct omap_rng_private_data *priv = platform_get_drvdata(pdev);
165 hwrng_unregister(&omap_rng_ops);
167 omap_rng_write_reg(priv, RNG_MASK_REG, 0x0);
169 pm_runtime_put_sync(&pdev->dev);
170 pm_runtime_disable(&pdev->dev);
175 #ifdef CONFIG_PM_SLEEP
177 static int omap_rng_suspend(struct device *dev)
179 struct omap_rng_private_data *priv = dev_get_drvdata(dev);
181 omap_rng_write_reg(priv, RNG_MASK_REG, 0x0);
182 pm_runtime_put_sync(dev);
187 static int omap_rng_resume(struct device *dev)
189 struct omap_rng_private_data *priv = dev_get_drvdata(dev);
191 pm_runtime_get_sync(dev);
192 omap_rng_write_reg(priv, RNG_MASK_REG, 0x1);
197 static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume);
198 #define OMAP_RNG_PM (&omap_rng_pm)
202 #define OMAP_RNG_PM NULL
206 static struct platform_driver omap_rng_driver = {
209 .owner = THIS_MODULE,
211 .of_match_table = of_match_ptr(omap_rng_of_match),
213 .probe = omap_rng_probe,
214 .remove = __exit_p(omap_rng_remove),
217 module_platform_driver(omap_rng_driver);
218 MODULE_ALIAS("platform:omap_rng");
219 MODULE_AUTHOR("Deepak Saxena (and others)");
220 MODULE_LICENSE("GPL");