xref: /linux/drivers/char/hw_random/imx-rngc.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * RNG driver for Freescale RNGC
4  *
5  * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
6  * Copyright (C) 2017 Martin Kaiser <martin@kaiser.cx>
7  */
8 
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/kernel.h>
12 #include <linux/clk.h>
13 #include <linux/err.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/interrupt.h>
18 #include <linux/hw_random.h>
19 #include <linux/completion.h>
20 #include <linux/io.h>
21 #include <linux/bitfield.h>
22 
23 #define RNGC_VER_ID			0x0000
24 #define RNGC_COMMAND			0x0004
25 #define RNGC_CONTROL			0x0008
26 #define RNGC_STATUS			0x000C
27 #define RNGC_ERROR			0x0010
28 #define RNGC_FIFO			0x0014
29 
30 /* the fields in the ver id register */
31 #define RNG_TYPE			GENMASK(31, 28)
32 #define RNGC_VER_MAJ_SHIFT		8
33 
34 /* the rng_type field */
35 #define RNGC_TYPE_RNGB			0x1
36 #define RNGC_TYPE_RNGC			0x2
37 
38 
39 #define RNGC_CMD_CLR_ERR		BIT(5)
40 #define RNGC_CMD_CLR_INT		BIT(4)
41 #define RNGC_CMD_SEED			BIT(1)
42 #define RNGC_CMD_SELF_TEST		BIT(0)
43 
44 #define RNGC_CTRL_MASK_ERROR		BIT(6)
45 #define RNGC_CTRL_MASK_DONE		BIT(5)
46 #define RNGC_CTRL_AUTO_SEED		BIT(4)
47 
48 #define RNGC_STATUS_ERROR		BIT(16)
49 #define RNGC_STATUS_FIFO_LEVEL_MASK	GENMASK(11, 8)
50 #define RNGC_STATUS_SEED_DONE		BIT(5)
51 #define RNGC_STATUS_ST_DONE		BIT(4)
52 
53 #define RNGC_ERROR_STATUS_STAT_ERR	0x00000008
54 
55 #define RNGC_SELFTEST_TIMEOUT 2500 /* us */
56 #define RNGC_SEED_TIMEOUT      200 /* ms */
57 #define RNGC_PM_TIMEOUT        500 /* ms */
58 
59 static bool self_test = true;
60 module_param(self_test, bool, 0);
61 
62 struct imx_rngc {
63 	struct device		*dev;
64 	struct clk		*clk;
65 	void __iomem		*base;
66 	struct hwrng		rng;
67 	struct completion	rng_op_done;
68 	/*
69 	 * err_reg is written only by the irq handler and read only
70 	 * when interrupts are masked, we need no spinlock
71 	 */
72 	u32			err_reg;
73 };
74 
75 
76 static inline void imx_rngc_irq_mask_clear(struct imx_rngc *rngc)
77 {
78 	u32 ctrl, cmd;
79 
80 	/* mask interrupts */
81 	ctrl = readl(rngc->base + RNGC_CONTROL);
82 	ctrl |= RNGC_CTRL_MASK_DONE | RNGC_CTRL_MASK_ERROR;
83 	writel(ctrl, rngc->base + RNGC_CONTROL);
84 
85 	/*
86 	 * CLR_INT clears the interrupt only if there's no error
87 	 * CLR_ERR clear the interrupt and the error register if there
88 	 * is an error
89 	 */
90 	cmd = readl(rngc->base + RNGC_COMMAND);
91 	cmd |= RNGC_CMD_CLR_INT | RNGC_CMD_CLR_ERR;
92 	writel(cmd, rngc->base + RNGC_COMMAND);
93 }
94 
95 static inline void imx_rngc_irq_unmask(struct imx_rngc *rngc)
96 {
97 	u32 ctrl;
98 
99 	ctrl = readl(rngc->base + RNGC_CONTROL);
100 	ctrl &= ~(RNGC_CTRL_MASK_DONE | RNGC_CTRL_MASK_ERROR);
101 	writel(ctrl, rngc->base + RNGC_CONTROL);
102 }
103 
104 static int imx_rngc_self_test(struct imx_rngc *rngc)
105 {
106 	u32 cmd;
107 	int ret;
108 
109 	imx_rngc_irq_unmask(rngc);
110 
111 	/* run self test */
112 	cmd = readl(rngc->base + RNGC_COMMAND);
113 	writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND);
114 
115 	ret = wait_for_completion_timeout(&rngc->rng_op_done,
116 					  usecs_to_jiffies(RNGC_SELFTEST_TIMEOUT));
117 	imx_rngc_irq_mask_clear(rngc);
118 	if (!ret)
119 		return -ETIMEDOUT;
120 
121 	return rngc->err_reg ? -EIO : 0;
122 }
123 
124 static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait)
125 {
126 	struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
127 	unsigned int status;
128 	int err, retval = 0;
129 
130 	err = pm_runtime_resume_and_get(rngc->dev);
131 	if (err)
132 		return err;
133 
134 	while (max >= sizeof(u32)) {
135 		status = readl(rngc->base + RNGC_STATUS);
136 
137 		/* is there some error while reading this random number? */
138 		if (status & RNGC_STATUS_ERROR)
139 			break;
140 
141 		if (status & RNGC_STATUS_FIFO_LEVEL_MASK) {
142 			/* retrieve a random number from FIFO */
143 			*(u32 *)data = readl(rngc->base + RNGC_FIFO);
144 
145 			retval += sizeof(u32);
146 			data += sizeof(u32);
147 			max -= sizeof(u32);
148 		}
149 	}
150 	pm_runtime_mark_last_busy(rngc->dev);
151 	pm_runtime_put(rngc->dev);
152 
153 	return retval ? retval : -EIO;
154 }
155 
156 static irqreturn_t imx_rngc_irq(int irq, void *priv)
157 {
158 	struct imx_rngc *rngc = (struct imx_rngc *)priv;
159 	u32 status;
160 
161 	/*
162 	 * clearing the interrupt will also clear the error register
163 	 * read error and status before clearing
164 	 */
165 	status = readl(rngc->base + RNGC_STATUS);
166 	rngc->err_reg = readl(rngc->base + RNGC_ERROR);
167 
168 	imx_rngc_irq_mask_clear(rngc);
169 
170 	if (status & (RNGC_STATUS_SEED_DONE | RNGC_STATUS_ST_DONE))
171 		complete(&rngc->rng_op_done);
172 
173 	return IRQ_HANDLED;
174 }
175 
176 static int imx_rngc_init(struct hwrng *rng)
177 {
178 	struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
179 	u32 cmd, ctrl;
180 	int ret, err;
181 
182 	err = pm_runtime_resume_and_get(rngc->dev);
183 	if (err)
184 		return err;
185 
186 	/* clear error */
187 	cmd = readl(rngc->base + RNGC_COMMAND);
188 	writel(cmd | RNGC_CMD_CLR_ERR, rngc->base + RNGC_COMMAND);
189 
190 	imx_rngc_irq_unmask(rngc);
191 
192 	/* create seed, repeat while there is some statistical error */
193 	do {
194 		/* seed creation */
195 		cmd = readl(rngc->base + RNGC_COMMAND);
196 		writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND);
197 
198 		ret = wait_for_completion_timeout(&rngc->rng_op_done,
199 						  msecs_to_jiffies(RNGC_SEED_TIMEOUT));
200 		if (!ret) {
201 			err = -ETIMEDOUT;
202 			goto out;
203 		}
204 
205 	} while (rngc->err_reg == RNGC_ERROR_STATUS_STAT_ERR);
206 
207 	if (rngc->err_reg) {
208 		err = -EIO;
209 		goto out;
210 	}
211 
212 	/*
213 	 * enable automatic seeding, the rngc creates a new seed automatically
214 	 * after serving 2^20 random 160-bit words
215 	 */
216 	ctrl = readl(rngc->base + RNGC_CONTROL);
217 	ctrl |= RNGC_CTRL_AUTO_SEED;
218 	writel(ctrl, rngc->base + RNGC_CONTROL);
219 
220 out:
221 	/*
222 	 * if initialisation was successful, we keep the interrupt
223 	 * unmasked until imx_rngc_cleanup is called
224 	 * we mask the interrupt ourselves if we return an error
225 	 */
226 	if (err)
227 		imx_rngc_irq_mask_clear(rngc);
228 
229 	pm_runtime_put(rngc->dev);
230 	return err;
231 }
232 
233 static void imx_rngc_cleanup(struct hwrng *rng)
234 {
235 	struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
236 	int err;
237 
238 	err = pm_runtime_resume_and_get(rngc->dev);
239 	if (!err) {
240 		imx_rngc_irq_mask_clear(rngc);
241 		pm_runtime_put(rngc->dev);
242 	}
243 }
244 
245 static int __init imx_rngc_probe(struct platform_device *pdev)
246 {
247 	struct imx_rngc *rngc;
248 	int ret;
249 	int irq;
250 	u32 ver_id;
251 	u8  rng_type;
252 
253 	rngc = devm_kzalloc(&pdev->dev, sizeof(*rngc), GFP_KERNEL);
254 	if (!rngc)
255 		return -ENOMEM;
256 
257 	rngc->base = devm_platform_ioremap_resource(pdev, 0);
258 	if (IS_ERR(rngc->base))
259 		return PTR_ERR(rngc->base);
260 
261 	rngc->clk = devm_clk_get(&pdev->dev, NULL);
262 	if (IS_ERR(rngc->clk))
263 		return dev_err_probe(&pdev->dev, PTR_ERR(rngc->clk), "Cannot get rng_clk\n");
264 
265 	irq = platform_get_irq(pdev, 0);
266 	if (irq < 0)
267 		return irq;
268 
269 	clk_prepare_enable(rngc->clk);
270 
271 	ver_id = readl(rngc->base + RNGC_VER_ID);
272 	rng_type = FIELD_GET(RNG_TYPE, ver_id);
273 	/*
274 	 * This driver supports only RNGC and RNGB. (There's a different
275 	 * driver for RNGA.)
276 	 */
277 	if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) {
278 		clk_disable_unprepare(rngc->clk);
279 		return -ENODEV;
280 	}
281 
282 	init_completion(&rngc->rng_op_done);
283 
284 	rngc->rng.name = pdev->name;
285 	rngc->rng.init = imx_rngc_init;
286 	rngc->rng.read = imx_rngc_read;
287 	rngc->rng.cleanup = imx_rngc_cleanup;
288 	rngc->rng.quality = 19;
289 
290 	rngc->dev = &pdev->dev;
291 	platform_set_drvdata(pdev, rngc);
292 
293 	imx_rngc_irq_mask_clear(rngc);
294 
295 	ret = devm_request_irq(&pdev->dev,
296 			irq, imx_rngc_irq, 0, pdev->name, (void *)rngc);
297 	if (ret) {
298 		clk_disable_unprepare(rngc->clk);
299 		return ret;
300 	}
301 
302 	if (self_test) {
303 		ret = imx_rngc_self_test(rngc);
304 		if (ret) {
305 			clk_disable_unprepare(rngc->clk);
306 			return dev_err_probe(&pdev->dev, ret, "self test failed\n");
307 		}
308 	}
309 
310 	pm_runtime_set_autosuspend_delay(&pdev->dev, RNGC_PM_TIMEOUT);
311 	pm_runtime_use_autosuspend(&pdev->dev);
312 	pm_runtime_set_active(&pdev->dev);
313 	devm_pm_runtime_enable(&pdev->dev);
314 
315 	ret = devm_hwrng_register(&pdev->dev, &rngc->rng);
316 	if (ret) {
317 		clk_disable_unprepare(rngc->clk);
318 		return dev_err_probe(&pdev->dev, ret, "hwrng registration failed\n");
319 	}
320 
321 	dev_info(&pdev->dev,
322 		"Freescale RNG%c registered (HW revision %d.%02d)\n",
323 		rng_type == RNGC_TYPE_RNGB ? 'B' : 'C',
324 		(ver_id >> RNGC_VER_MAJ_SHIFT) & 0xff, ver_id & 0xff);
325 	return 0;
326 }
327 
328 static int imx_rngc_suspend(struct device *dev)
329 {
330 	struct imx_rngc *rngc = dev_get_drvdata(dev);
331 
332 	clk_disable_unprepare(rngc->clk);
333 
334 	return 0;
335 }
336 
337 static int imx_rngc_resume(struct device *dev)
338 {
339 	struct imx_rngc *rngc = dev_get_drvdata(dev);
340 
341 	clk_prepare_enable(rngc->clk);
342 
343 	return 0;
344 }
345 
346 static const struct dev_pm_ops imx_rngc_pm_ops = {
347 	SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
348 	RUNTIME_PM_OPS(imx_rngc_suspend, imx_rngc_resume, NULL)
349 };
350 
351 static const struct of_device_id imx_rngc_dt_ids[] = {
352 	{ .compatible = "fsl,imx25-rngb" },
353 	{ /* sentinel */ }
354 };
355 MODULE_DEVICE_TABLE(of, imx_rngc_dt_ids);
356 
357 static struct platform_driver imx_rngc_driver = {
358 	.driver = {
359 		.name = KBUILD_MODNAME,
360 		.pm = pm_ptr(&imx_rngc_pm_ops),
361 		.of_match_table = imx_rngc_dt_ids,
362 	},
363 };
364 
365 module_platform_driver_probe(imx_rngc_driver, imx_rngc_probe);
366 
367 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
368 MODULE_DESCRIPTION("H/W RNGC driver for i.MX");
369 MODULE_LICENSE("GPL");
370