forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/char/hw_random/imx-rngc.c
....@@ -1,15 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * RNG driver for Freescale RNGC
34 *
45 * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
56 * Copyright (C) 2017 Martin Kaiser <martin@kaiser.cx>
6
- *
7
- * The code contained herein is licensed under the GNU General Public
8
- * License. You may obtain a copy of the GNU General Public License
9
- * Version 2 or later at the following locations:
10
- *
11
- * http://www.opensource.org/licenses/gpl-license.html
12
- * http://www.gnu.org/copyleft/gpl.html
137 */
148
159 #include <linux/module.h>
....@@ -24,11 +18,21 @@
2418 #include <linux/completion.h>
2519 #include <linux/io.h>
2620
21
+#define RNGC_VER_ID 0x0000
2722 #define RNGC_COMMAND 0x0004
2823 #define RNGC_CONTROL 0x0008
2924 #define RNGC_STATUS 0x000C
3025 #define RNGC_ERROR 0x0010
3126 #define RNGC_FIFO 0x0014
27
+
28
+/* the fields in the ver id register */
29
+#define RNGC_TYPE_SHIFT 28
30
+#define RNGC_VER_MAJ_SHIFT 8
31
+
32
+/* the rng_type field */
33
+#define RNGC_TYPE_RNGB 0x1
34
+#define RNGC_TYPE_RNGC 0x2
35
+
3236
3337 #define RNGC_CMD_CLR_ERR 0x00000020
3438 #define RNGC_CMD_CLR_INT 0x00000010
....@@ -37,6 +41,7 @@
3741
3842 #define RNGC_CTRL_MASK_ERROR 0x00000040
3943 #define RNGC_CTRL_MASK_DONE 0x00000020
44
+#define RNGC_CTRL_AUTO_SEED 0x00000010
4045
4146 #define RNGC_STATUS_ERROR 0x00010000
4247 #define RNGC_STATUS_FIFO_LEVEL_MASK 0x00000f00
....@@ -105,18 +110,12 @@
105110 cmd = readl(rngc->base + RNGC_COMMAND);
106111 writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND);
107112
108
- ret = wait_for_completion_timeout(&rngc->rng_op_done, RNGC_TIMEOUT);
109
- if (!ret) {
110
- imx_rngc_irq_mask_clear(rngc);
113
+ ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT));
114
+ imx_rngc_irq_mask_clear(rngc);
115
+ if (!ret)
111116 return -ETIMEDOUT;
112
- }
113117
114
- if (rngc->err_reg != 0) {
115
- imx_rngc_irq_mask_clear(rngc);
116
- return -EIO;
117
- }
118
-
119
- return 0;
118
+ return rngc->err_reg ? -EIO : 0;
120119 }
121120
122121 static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait)
....@@ -173,47 +172,74 @@
173172 static int imx_rngc_init(struct hwrng *rng)
174173 {
175174 struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
176
- u32 cmd;
175
+ u32 cmd, ctrl;
177176 int ret;
178177
179178 /* clear error */
180179 cmd = readl(rngc->base + RNGC_COMMAND);
181180 writel(cmd | RNGC_CMD_CLR_ERR, rngc->base + RNGC_COMMAND);
182181
182
+ imx_rngc_irq_unmask(rngc);
183
+
183184 /* create seed, repeat while there is some statistical error */
184185 do {
185
- imx_rngc_irq_unmask(rngc);
186
-
187186 /* seed creation */
188187 cmd = readl(rngc->base + RNGC_COMMAND);
189188 writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND);
190189
191
- ret = wait_for_completion_timeout(&rngc->rng_op_done,
192
- RNGC_TIMEOUT);
193
-
190
+ ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT));
194191 if (!ret) {
195
- imx_rngc_irq_mask_clear(rngc);
196
- return -ETIMEDOUT;
192
+ ret = -ETIMEDOUT;
193
+ goto err;
197194 }
198195
199196 } while (rngc->err_reg == RNGC_ERROR_STATUS_STAT_ERR);
200197
201
- return rngc->err_reg ? -EIO : 0;
198
+ if (rngc->err_reg) {
199
+ ret = -EIO;
200
+ goto err;
201
+ }
202
+
203
+ /*
204
+ * enable automatic seeding, the rngc creates a new seed automatically
205
+ * after serving 2^20 random 160-bit words
206
+ */
207
+ ctrl = readl(rngc->base + RNGC_CONTROL);
208
+ ctrl |= RNGC_CTRL_AUTO_SEED;
209
+ writel(ctrl, rngc->base + RNGC_CONTROL);
210
+
211
+ /*
212
+ * if initialisation was successful, we keep the interrupt
213
+ * unmasked until imx_rngc_cleanup is called
214
+ * we mask the interrupt ourselves if we return an error
215
+ */
216
+ return 0;
217
+
218
+err:
219
+ imx_rngc_irq_mask_clear(rngc);
220
+ return ret;
221
+}
222
+
223
+static void imx_rngc_cleanup(struct hwrng *rng)
224
+{
225
+ struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
226
+
227
+ imx_rngc_irq_mask_clear(rngc);
202228 }
203229
204230 static int imx_rngc_probe(struct platform_device *pdev)
205231 {
206232 struct imx_rngc *rngc;
207
- struct resource *res;
208233 int ret;
209234 int irq;
235
+ u32 ver_id;
236
+ u8 rng_type;
210237
211238 rngc = devm_kzalloc(&pdev->dev, sizeof(*rngc), GFP_KERNEL);
212239 if (!rngc)
213240 return -ENOMEM;
214241
215
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
216
- rngc->base = devm_ioremap_resource(&pdev->dev, res);
242
+ rngc->base = devm_platform_ioremap_resource(pdev, 0);
217243 if (IS_ERR(rngc->base))
218244 return PTR_ERR(rngc->base);
219245
....@@ -233,10 +259,14 @@
233259 if (ret)
234260 return ret;
235261
236
- ret = devm_request_irq(&pdev->dev,
237
- irq, imx_rngc_irq, 0, pdev->name, (void *)rngc);
238
- if (ret) {
239
- dev_err(rngc->dev, "Can't get interrupt working.\n");
262
+ ver_id = readl(rngc->base + RNGC_VER_ID);
263
+ rng_type = ver_id >> RNGC_TYPE_SHIFT;
264
+ /*
265
+ * This driver supports only RNGC and RNGB. (There's a different
266
+ * driver for RNGA.)
267
+ */
268
+ if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) {
269
+ ret = -ENODEV;
240270 goto err;
241271 }
242272
....@@ -245,27 +275,39 @@
245275 rngc->rng.name = pdev->name;
246276 rngc->rng.init = imx_rngc_init;
247277 rngc->rng.read = imx_rngc_read;
278
+ rngc->rng.cleanup = imx_rngc_cleanup;
279
+ rngc->rng.quality = 19;
248280
249281 rngc->dev = &pdev->dev;
250282 platform_set_drvdata(pdev, rngc);
251283
252284 imx_rngc_irq_mask_clear(rngc);
253285
286
+ ret = devm_request_irq(&pdev->dev,
287
+ irq, imx_rngc_irq, 0, pdev->name, (void *)rngc);
288
+ if (ret) {
289
+ dev_err(rngc->dev, "Can't get interrupt working.\n");
290
+ return ret;
291
+ }
292
+
254293 if (self_test) {
255294 ret = imx_rngc_self_test(rngc);
256295 if (ret) {
257
- dev_err(rngc->dev, "FSL RNGC self test failed.\n");
296
+ dev_err(rngc->dev, "self test failed\n");
258297 goto err;
259298 }
260299 }
261300
262301 ret = hwrng_register(&rngc->rng);
263302 if (ret) {
264
- dev_err(&pdev->dev, "FSL RNGC registering failed (%d)\n", ret);
303
+ dev_err(&pdev->dev, "hwrng registration failed\n");
265304 goto err;
266305 }
267306
268
- dev_info(&pdev->dev, "Freescale RNGC registered.\n");
307
+ dev_info(&pdev->dev,
308
+ "Freescale RNG%c registered (HW revision %d.%02d)\n",
309
+ rng_type == RNGC_TYPE_RNGB ? 'B' : 'C',
310
+ (ver_id >> RNGC_VER_MAJ_SHIFT) & 0xff, ver_id & 0xff);
269311 return 0;
270312
271313 err: