aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/hw_random/mxc-rnga.c108
1 files changed, 51 insertions, 57 deletions
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c
index 62c7efe375ab..f05d85713fd3 100644
--- a/drivers/char/hw_random/mxc-rnga.c
+++ b/drivers/char/hw_random/mxc-rnga.c
@@ -59,16 +59,21 @@
59#define RNGA_STATUS_LAST_READ_STATUS 0x00000002 59#define RNGA_STATUS_LAST_READ_STATUS 0x00000002
60#define RNGA_STATUS_SECURITY_VIOLATION 0x00000001 60#define RNGA_STATUS_SECURITY_VIOLATION 0x00000001
61 61
62static struct platform_device *rng_dev; 62struct mxc_rng {
63 struct device *dev;
64 struct hwrng rng;
65 void __iomem *mem;
66 struct clk *clk;
67};
63 68
64static int mxc_rnga_data_present(struct hwrng *rng, int wait) 69static int mxc_rnga_data_present(struct hwrng *rng, int wait)
65{ 70{
66 void __iomem *rng_base = (void __iomem *)rng->priv;
67 int i; 71 int i;
72 struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
68 73
69 for (i = 0; i < 20; i++) { 74 for (i = 0; i < 20; i++) {
70 /* how many random numbers are in FIFO? [0-16] */ 75 /* how many random numbers are in FIFO? [0-16] */
71 int level = (__raw_readl(rng_base + RNGA_STATUS) & 76 int level = (__raw_readl(mxc_rng->mem + RNGA_STATUS) &
72 RNGA_STATUS_LEVEL_MASK) >> 8; 77 RNGA_STATUS_LEVEL_MASK) >> 8;
73 if (level || !wait) 78 if (level || !wait)
74 return !!level; 79 return !!level;
@@ -81,20 +86,20 @@ static int mxc_rnga_data_read(struct hwrng *rng, u32 * data)
81{ 86{
82 int err; 87 int err;
83 u32 ctrl; 88 u32 ctrl;
84 void __iomem *rng_base = (void __iomem *)rng->priv; 89 struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
85 90
86 /* retrieve a random number from FIFO */ 91 /* retrieve a random number from FIFO */
87 *data = __raw_readl(rng_base + RNGA_OUTPUT_FIFO); 92 *data = __raw_readl(mxc_rng->mem + RNGA_OUTPUT_FIFO);
88 93
89 /* some error while reading this random number? */ 94 /* some error while reading this random number? */
90 err = __raw_readl(rng_base + RNGA_STATUS) & RNGA_STATUS_ERROR_INT; 95 err = __raw_readl(mxc_rng->mem + RNGA_STATUS) & RNGA_STATUS_ERROR_INT;
91 96
92 /* if error: clear error interrupt, but doesn't return random number */ 97 /* if error: clear error interrupt, but doesn't return random number */
93 if (err) { 98 if (err) {
94 dev_dbg(&rng_dev->dev, "Error while reading random number!\n"); 99 dev_dbg(mxc_rng->dev, "Error while reading random number!\n");
95 ctrl = __raw_readl(rng_base + RNGA_CONTROL); 100 ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
96 __raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT, 101 __raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT,
97 rng_base + RNGA_CONTROL); 102 mxc_rng->mem + RNGA_CONTROL);
98 return 0; 103 return 0;
99 } else 104 } else
100 return 4; 105 return 4;
@@ -103,22 +108,22 @@ static int mxc_rnga_data_read(struct hwrng *rng, u32 * data)
103static int mxc_rnga_init(struct hwrng *rng) 108static int mxc_rnga_init(struct hwrng *rng)
104{ 109{
105 u32 ctrl, osc; 110 u32 ctrl, osc;
106 void __iomem *rng_base = (void __iomem *)rng->priv; 111 struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
107 112
108 /* wake up */ 113 /* wake up */
109 ctrl = __raw_readl(rng_base + RNGA_CONTROL); 114 ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
110 __raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, rng_base + RNGA_CONTROL); 115 __raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, mxc_rng->mem + RNGA_CONTROL);
111 116
112 /* verify if oscillator is working */ 117 /* verify if oscillator is working */
113 osc = __raw_readl(rng_base + RNGA_STATUS); 118 osc = __raw_readl(mxc_rng->mem + RNGA_STATUS);
114 if (osc & RNGA_STATUS_OSC_DEAD) { 119 if (osc & RNGA_STATUS_OSC_DEAD) {
115 dev_err(&rng_dev->dev, "RNGA Oscillator is dead!\n"); 120 dev_err(mxc_rng->dev, "RNGA Oscillator is dead!\n");
116 return -ENODEV; 121 return -ENODEV;
117 } 122 }
118 123
119 /* go running */ 124 /* go running */
120 ctrl = __raw_readl(rng_base + RNGA_CONTROL); 125 ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
121 __raw_writel(ctrl | RNGA_CONTROL_GO, rng_base + RNGA_CONTROL); 126 __raw_writel(ctrl | RNGA_CONTROL_GO, mxc_rng->mem + RNGA_CONTROL);
122 127
123 return 0; 128 return 0;
124} 129}
@@ -126,40 +131,40 @@ static int mxc_rnga_init(struct hwrng *rng)
126static void mxc_rnga_cleanup(struct hwrng *rng) 131static void mxc_rnga_cleanup(struct hwrng *rng)
127{ 132{
128 u32 ctrl; 133 u32 ctrl;
129 void __iomem *rng_base = (void __iomem *)rng->priv; 134 struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
130 135
131 ctrl = __raw_readl(rng_base + RNGA_CONTROL); 136 ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
132 137
133 /* stop rnga */ 138 /* stop rnga */
134 __raw_writel(ctrl & ~RNGA_CONTROL_GO, rng_base + RNGA_CONTROL); 139 __raw_writel(ctrl & ~RNGA_CONTROL_GO, mxc_rng->mem + RNGA_CONTROL);
135} 140}
136 141
137static struct hwrng mxc_rnga = {
138 .name = "mxc-rnga",
139 .init = mxc_rnga_init,
140 .cleanup = mxc_rnga_cleanup,
141 .data_present = mxc_rnga_data_present,
142 .data_read = mxc_rnga_data_read
143};
144
145static int __init mxc_rnga_probe(struct platform_device *pdev) 142static int __init mxc_rnga_probe(struct platform_device *pdev)
146{ 143{
147 int err = -ENODEV; 144 int err = -ENODEV;
148 struct clk *clk;
149 struct resource *res, *mem; 145 struct resource *res, *mem;
150 void __iomem *rng_base = NULL; 146 struct mxc_rng *mxc_rng;
151 147
152 if (rng_dev) 148 mxc_rng = devm_kzalloc(&pdev->dev, sizeof(struct mxc_rng),
153 return -EBUSY; 149 GFP_KERNEL);
154 150 if (!mxc_rng)
155 clk = clk_get(&pdev->dev, NULL); 151 return -ENOMEM;
156 if (IS_ERR(clk)) { 152
153 mxc_rng->dev = &pdev->dev;
154 mxc_rng->rng.name = "mxc-rnga";
155 mxc_rng->rng.init = mxc_rnga_init;
156 mxc_rng->rng.cleanup = mxc_rnga_cleanup,
157 mxc_rng->rng.data_present = mxc_rnga_data_present,
158 mxc_rng->rng.data_read = mxc_rnga_data_read,
159
160 mxc_rng->clk = devm_clk_get(&pdev->dev, NULL);
161 if (IS_ERR(mxc_rng->clk)) {
157 dev_err(&pdev->dev, "Could not get rng_clk!\n"); 162 dev_err(&pdev->dev, "Could not get rng_clk!\n");
158 err = PTR_ERR(clk); 163 err = PTR_ERR(mxc_rng->clk);
159 goto out; 164 goto out;
160 } 165 }
161 166
162 clk_prepare_enable(clk); 167 clk_prepare_enable(mxc_rng->clk);
163 168
164 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 169 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
165 if (!res) { 170 if (!res) {
@@ -173,36 +178,27 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
173 goto err_region; 178 goto err_region;
174 } 179 }
175 180
176 rng_base = ioremap(res->start, resource_size(res)); 181 mxc_rng->mem = ioremap(res->start, resource_size(res));
177 if (!rng_base) { 182 if (!mxc_rng->mem) {
178 err = -ENOMEM; 183 err = -ENOMEM;
179 goto err_ioremap; 184 goto err_ioremap;
180 } 185 }
181 186
182 mxc_rnga.priv = (unsigned long)rng_base; 187 err = hwrng_register(&mxc_rng->rng);
183
184 err = hwrng_register(&mxc_rnga);
185 if (err) { 188 if (err) {
186 dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err); 189 dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err);
187 goto err_register; 190 goto err_ioremap;
188 } 191 }
189 192
190 rng_dev = pdev;
191
192 dev_info(&pdev->dev, "MXC RNGA Registered.\n"); 193 dev_info(&pdev->dev, "MXC RNGA Registered.\n");
193 194
194 return 0; 195 return 0;
195 196
196err_register:
197 iounmap(rng_base);
198 rng_base = NULL;
199
200err_ioremap: 197err_ioremap:
201 release_mem_region(res->start, resource_size(res)); 198 release_mem_region(res->start, resource_size(res));
202 199
203err_region: 200err_region:
204 clk_disable_unprepare(clk); 201 clk_disable_unprepare(mxc_rng->clk);
205 clk_put(clk);
206 202
207out: 203out:
208 return err; 204 return err;
@@ -211,17 +207,15 @@ out:
211static int __exit mxc_rnga_remove(struct platform_device *pdev) 207static int __exit mxc_rnga_remove(struct platform_device *pdev)
212{ 208{
213 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 209 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
214 void __iomem *rng_base = (void __iomem *)mxc_rnga.priv; 210 struct mxc_rng *mxc_rng = platform_get_drvdata(pdev);
215 struct clk *clk = clk_get(&pdev->dev, NULL);
216 211
217 hwrng_unregister(&mxc_rnga); 212 hwrng_unregister(&mxc_rng->rng);
218 213
219 iounmap(rng_base); 214 iounmap(mxc_rng->mem);
220 215
221 release_mem_region(res->start, resource_size(res)); 216 release_mem_region(res->start, resource_size(res));
222 217
223 clk_disable_unprepare(clk); 218 clk_disable_unprepare(mxc_rng->clk);
224 clk_put(clk);
225 219
226 return 0; 220 return 0;
227} 221}