aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hw_random
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2012-09-23 19:28:26 -0400
committerPaul Walmsley <paul@pwsan.com>2012-09-23 19:28:26 -0400
commit02666360c92af7885c47163f936b58dc86213a53 (patch)
treefea4b51900b0d7612d01cfaa695ebc57c55f291a /drivers/char/hw_random
parente9b0a2fb0af562092aab1b56abf9d13f1abc7381 (diff)
hwrng: OMAP: store per-device data in per-device variables, not file statics
Encapsulate all of the RNG per-device state into a single per-device structure record, as opposed to a set of per-driver file variables. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Matt Mackall <mpm@selenic.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/char/hw_random')
-rw-r--r--drivers/char/hw_random/omap-rng.c115
1 files changed, 77 insertions, 38 deletions
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 4fbdceb6f773..e0f0b9839862 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -23,6 +23,7 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/hw_random.h> 24#include <linux/hw_random.h>
25#include <linux/delay.h> 25#include <linux/delay.h>
26#include <linux/slab.h>
26 27
27#include <asm/io.h> 28#include <asm/io.h>
28 29
@@ -46,26 +47,38 @@
46#define RNG_SYSSTATUS 0x44 /* System status 47#define RNG_SYSSTATUS 0x44 /* System status
47 [0] = RESETDONE */ 48 [0] = RESETDONE */
48 49
49static void __iomem *rng_base; 50/**
50static struct clk *rng_ick; 51 * struct omap_rng_private_data - RNG IP block-specific data
51static struct platform_device *rng_dev; 52 * @base: virtual address of the beginning of the RNG IP block registers
53 * @clk: RNG clock
54 * @mem_res: struct resource * for the IP block registers physical memory
55 */
56struct omap_rng_private_data {
57 void __iomem *base;
58 struct clk *clk;
59 struct resource *mem_res;
60};
52 61
53static inline u32 omap_rng_read_reg(int reg) 62static inline u32 omap_rng_read_reg(struct omap_rng_private_data *priv, int reg)
54{ 63{
55 return __raw_readl(rng_base + reg); 64 return __raw_readl(priv->base + reg);
56} 65}
57 66
58static inline void omap_rng_write_reg(int reg, u32 val) 67static inline void omap_rng_write_reg(struct omap_rng_private_data *priv,
68 int reg, u32 val)
59{ 69{
60 __raw_writel(val, rng_base + reg); 70 __raw_writel(val, priv->base + reg);
61} 71}
62 72
63static int omap_rng_data_present(struct hwrng *rng, int wait) 73static int omap_rng_data_present(struct hwrng *rng, int wait)
64{ 74{
75 struct omap_rng_private_data *priv;
65 int data, i; 76 int data, i;
66 77
78 priv = (struct omap_rng_private_data *)rng->priv;
79
67 for (i = 0; i < 20; i++) { 80 for (i = 0; i < 20; i++) {
68 data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1; 81 data = omap_rng_read_reg(priv, RNG_STAT_REG) ? 0 : 1;
69 if (data || !wait) 82 if (data || !wait)
70 break; 83 break;
71 /* RNG produces data fast enough (2+ MBit/sec, even 84 /* RNG produces data fast enough (2+ MBit/sec, even
@@ -80,9 +93,13 @@ static int omap_rng_data_present(struct hwrng *rng, int wait)
80 93
81static int omap_rng_data_read(struct hwrng *rng, u32 *data) 94static int omap_rng_data_read(struct hwrng *rng, u32 *data)
82{ 95{
83 *data = omap_rng_read_reg(RNG_OUT_REG); 96 struct omap_rng_private_data *priv;
97
98 priv = (struct omap_rng_private_data *)rng->priv;
99
100 *data = omap_rng_read_reg(priv, RNG_OUT_REG);
84 101
85 return 4; 102 return sizeof(u32);
86} 103}
87 104
88static struct hwrng omap_rng_ops = { 105static struct hwrng omap_rng_ops = {
@@ -93,69 +110,85 @@ static struct hwrng omap_rng_ops = {
93 110
94static int __devinit omap_rng_probe(struct platform_device *pdev) 111static int __devinit omap_rng_probe(struct platform_device *pdev)
95{ 112{
96 struct resource *res; 113 struct omap_rng_private_data *priv;
97 int ret; 114 int ret;
98 115
99 /* 116 priv = kzalloc(sizeof(struct omap_rng_private_data), GFP_KERNEL);
100 * A bit ugly, and it will never actually happen but there can 117 if (!priv) {
101 * be only one RNG and this catches any bork 118 dev_err(&pdev->dev, "could not allocate memory\n");
102 */ 119 return -ENOMEM;
103 if (rng_dev) 120 };
104 return -EBUSY; 121
122 omap_rng_ops.priv = (unsigned long)priv;
123 dev_set_drvdata(&pdev->dev, priv);
105 124
106 if (cpu_is_omap24xx()) { 125 if (cpu_is_omap24xx()) {
107 rng_ick = clk_get(&pdev->dev, "ick"); 126 priv->clk = clk_get(&pdev->dev, "ick");
108 if (IS_ERR(rng_ick)) { 127 if (IS_ERR(priv->clk)) {
109 dev_err(&pdev->dev, "Could not get rng_ick\n"); 128 dev_err(&pdev->dev, "Could not get rng_ick\n");
110 ret = PTR_ERR(rng_ick); 129 ret = PTR_ERR(priv->clk);
111 return ret; 130 return ret;
112 } else 131 } else {
113 clk_enable(rng_ick); 132 clk_enable(priv->clk);
133 }
114 } 134 }
115 135
116 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 136 priv->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
137 if (!priv->mem_res) {
138 ret = -ENOENT;
139 goto err_ioremap;
140 }
117 141
118 rng_base = devm_request_and_ioremap(&pdev->dev, res); 142 priv->base = devm_request_and_ioremap(&pdev->dev, priv->mem_res);
119 if (!rng_base) { 143 if (!priv->base) {
120 ret = -ENOMEM; 144 ret = -ENOMEM;
121 goto err_ioremap; 145 goto err_ioremap;
122 } 146 }
123 dev_set_drvdata(&pdev->dev, res); 147 dev_set_drvdata(&pdev->dev, priv);
124 148
125 ret = hwrng_register(&omap_rng_ops); 149 ret = hwrng_register(&omap_rng_ops);
126 if (ret) 150 if (ret)
127 goto err_register; 151 goto err_register;
128 152
129 dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n", 153 dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
130 omap_rng_read_reg(RNG_REV_REG)); 154 omap_rng_read_reg(priv, RNG_REV_REG));
131 omap_rng_write_reg(RNG_MASK_REG, 0x1); 155
132 156
133 rng_dev = pdev; 157 omap_rng_write_reg(priv, RNG_MASK_REG, 0x1);
134 158
135 return 0; 159 return 0;
136 160
137err_register: 161err_register:
138 rng_base = NULL; 162 priv->base = NULL;
139err_ioremap: 163err_ioremap:
140 if (cpu_is_omap24xx()) { 164 if (cpu_is_omap24xx()) {
141 clk_disable(rng_ick); 165 clk_disable(priv->clk);
142 clk_put(rng_ick); 166 clk_put(priv->clk);
143 } 167 }
168
169 kfree(priv);
170
144 return ret; 171 return ret;
145} 172}
146 173
147static int __exit omap_rng_remove(struct platform_device *pdev) 174static int __exit omap_rng_remove(struct platform_device *pdev)
148{ 175{
176 struct omap_rng_private_data *priv = dev_get_drvdata(&pdev->dev);
177
149 hwrng_unregister(&omap_rng_ops); 178 hwrng_unregister(&omap_rng_ops);
150 179
151 omap_rng_write_reg(RNG_MASK_REG, 0x0); 180 omap_rng_write_reg(priv, RNG_MASK_REG, 0x0);
181
182 iounmap(priv->base);
152 183
153 if (cpu_is_omap24xx()) { 184 if (cpu_is_omap24xx()) {
154 clk_disable(rng_ick); 185 clk_disable(priv->clk);
155 clk_put(rng_ick); 186 clk_put(priv->clk);
156 } 187 }
157 188
158 rng_base = NULL; 189 release_mem_region(priv->mem_res->start, resource_size(priv->mem_res));
190
191 kfree(priv);
159 192
160 return 0; 193 return 0;
161} 194}
@@ -164,13 +197,19 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
164 197
165static int omap_rng_suspend(struct device *dev) 198static int omap_rng_suspend(struct device *dev)
166{ 199{
167 omap_rng_write_reg(RNG_MASK_REG, 0x0); 200 struct omap_rng_private_data *priv = dev_get_drvdata(dev);
201
202 omap_rng_write_reg(priv, RNG_MASK_REG, 0x0);
203
168 return 0; 204 return 0;
169} 205}
170 206
171static int omap_rng_resume(struct device *dev) 207static int omap_rng_resume(struct device *dev)
172{ 208{
173 omap_rng_write_reg(RNG_MASK_REG, 0x1); 209 struct omap_rng_private_data *priv = dev_get_drvdata(dev);
210
211 omap_rng_write_reg(priv, RNG_MASK_REG, 0x1);
212
174 return 0; 213 return 0;
175} 214}
176 215