1 // SPDX-License-Identifier: GPL-2.0
3 * TRNG driver for the StarFive JH7110 SoC
5 * Copyright (C) 2022 StarFive Technology Co.
9 #include <linux/completion.h>
10 #include <linux/delay.h>
11 #include <linux/err.h>
12 #include <linux/hw_random.h>
13 #include <linux/interrupt.h>
15 #include <linux/iopoll.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/random.h>
22 #include <linux/reset.h>
24 /* trng register offset */
25 #define STARFIVE_CTRL 0x00
26 #define STARFIVE_STAT 0x04
27 #define STARFIVE_MODE 0x08
28 #define STARFIVE_SMODE 0x0C
29 #define STARFIVE_IE 0x10
30 #define STARFIVE_ISTAT 0x14
31 #define STARFIVE_RAND0 0x20
32 #define STARFIVE_RAND1 0x24
33 #define STARFIVE_RAND2 0x28
34 #define STARFIVE_RAND3 0x2C
35 #define STARFIVE_RAND4 0x30
36 #define STARFIVE_RAND5 0x34
37 #define STARFIVE_RAND6 0x38
38 #define STARFIVE_RAND7 0x3C
39 #define STARFIVE_AUTO_RQSTS 0x60
40 #define STARFIVE_AUTO_AGE 0x64
43 #define STARFIVE_CTRL_EXEC_NOP 0x0
44 #define STARFIVE_CTRL_GENE_RANDNUM 0x1
45 #define STARFIVE_CTRL_EXEC_RANDRESEED 0x2
48 #define STARFIVE_STAT_NONCE_MODE BIT(2)
49 #define STARFIVE_STAT_R256 BIT(3)
50 #define STARFIVE_STAT_MISSION_MODE BIT(8)
51 #define STARFIVE_STAT_SEEDED BIT(9)
52 #define STARFIVE_STAT_LAST_RESEED(x) ((x) << 16)
53 #define STARFIVE_STAT_SRVC_RQST BIT(27)
54 #define STARFIVE_STAT_RAND_GENERATING BIT(30)
55 #define STARFIVE_STAT_RAND_SEEDING BIT(31)
58 #define STARFIVE_MODE_R256 BIT(3)
61 #define STARFIVE_SMODE_NONCE_MODE BIT(2)
62 #define STARFIVE_SMODE_MISSION_MODE BIT(8)
63 #define STARFIVE_SMODE_MAX_REJECTS(x) ((x) << 16)
66 #define STARFIVE_IE_RAND_RDY_EN BIT(0)
67 #define STARFIVE_IE_SEED_DONE_EN BIT(1)
68 #define STARFIVE_IE_LFSR_LOCKUP_EN BIT(4)
69 #define STARFIVE_IE_GLBL_EN BIT(31)
71 #define STARFIVE_IE_ALL (STARFIVE_IE_GLBL_EN | \
72 STARFIVE_IE_RAND_RDY_EN | \
73 STARFIVE_IE_SEED_DONE_EN | \
74 STARFIVE_IE_LFSR_LOCKUP_EN)
77 #define STARFIVE_ISTAT_RAND_RDY BIT(0)
78 #define STARFIVE_ISTAT_SEED_DONE BIT(1)
79 #define STARFIVE_ISTAT_LFSR_LOCKUP BIT(4)
81 #define STARFIVE_RAND_LEN sizeof(u32)
83 #define to_trng(p) container_of(p, struct starfive_trng, rng)
95 struct starfive_trng
{
100 struct reset_control
*rst
;
102 struct completion random_done
;
103 struct completion reseed_done
;
107 /* protects against concurrent write to ctrl register */
108 spinlock_t write_lock
;
112 module_param(autoreq
, ushort
, 0);
113 MODULE_PARM_DESC(autoreq
, "Auto-reseeding after random number requests by host reaches specified counter:\n"
114 " 0 - disable counter\n"
115 " other - reload value for internal counter");
118 module_param(autoage
, ushort
, 0);
119 MODULE_PARM_DESC(autoage
, "Auto-reseeding after specified timer countdowns to 0:\n"
120 " 0 - disable timer\n"
121 " other - reload value for internal timer");
123 static inline int starfive_trng_wait_idle(struct starfive_trng
*trng
)
127 return readl_relaxed_poll_timeout(trng
->base
+ STARFIVE_STAT
, stat
,
128 !(stat
& (STARFIVE_STAT_RAND_GENERATING
|
129 STARFIVE_STAT_RAND_SEEDING
)),
133 static inline void starfive_trng_irq_mask_clear(struct starfive_trng
*trng
)
135 /* clear register: ISTAT */
136 u32 data
= readl(trng
->base
+ STARFIVE_ISTAT
);
138 writel(data
, trng
->base
+ STARFIVE_ISTAT
);
141 static int starfive_trng_cmd(struct starfive_trng
*trng
, u32 cmd
, bool wait
)
143 int wait_time
= 1000;
145 /* allow up to 40 us for wait == 0 */
150 case STARFIVE_CTRL_GENE_RANDNUM
:
151 reinit_completion(&trng
->random_done
);
152 spin_lock_irq(&trng
->write_lock
);
153 writel(cmd
, trng
->base
+ STARFIVE_CTRL
);
154 spin_unlock_irq(&trng
->write_lock
);
155 if (!wait_for_completion_timeout(&trng
->random_done
, usecs_to_jiffies(wait_time
)))
158 case STARFIVE_CTRL_EXEC_RANDRESEED
:
159 reinit_completion(&trng
->reseed_done
);
160 spin_lock_irq(&trng
->write_lock
);
161 writel(cmd
, trng
->base
+ STARFIVE_CTRL
);
162 spin_unlock_irq(&trng
->write_lock
);
163 if (!wait_for_completion_timeout(&trng
->reseed_done
, usecs_to_jiffies(wait_time
)))
173 static int starfive_trng_init(struct hwrng
*rng
)
175 struct starfive_trng
*trng
= to_trng(rng
);
178 /* setup Auto Request/Age register */
179 writel(autoage
, trng
->base
+ STARFIVE_AUTO_AGE
);
180 writel(autoreq
, trng
->base
+ STARFIVE_AUTO_RQSTS
);
182 /* clear register: ISTAT */
183 starfive_trng_irq_mask_clear(trng
);
185 intr
|= STARFIVE_IE_ALL
;
186 writel(intr
, trng
->base
+ STARFIVE_IE
);
188 mode
= readl(trng
->base
+ STARFIVE_MODE
);
190 switch (trng
->mode
) {
192 mode
&= ~STARFIVE_MODE_R256
;
195 mode
|= STARFIVE_MODE_R256
;
198 mode
|= STARFIVE_MODE_R256
;
202 writel(mode
, trng
->base
+ STARFIVE_MODE
);
204 return starfive_trng_cmd(trng
, STARFIVE_CTRL_EXEC_RANDRESEED
, 1);
207 static irqreturn_t
starfive_trng_irq(int irq
, void *priv
)
210 struct starfive_trng
*trng
= (struct starfive_trng
*)priv
;
212 status
= readl(trng
->base
+ STARFIVE_ISTAT
);
213 if (status
& STARFIVE_ISTAT_RAND_RDY
) {
214 writel(STARFIVE_ISTAT_RAND_RDY
, trng
->base
+ STARFIVE_ISTAT
);
215 complete(&trng
->random_done
);
218 if (status
& STARFIVE_ISTAT_SEED_DONE
) {
219 writel(STARFIVE_ISTAT_SEED_DONE
, trng
->base
+ STARFIVE_ISTAT
);
220 complete(&trng
->reseed_done
);
223 if (status
& STARFIVE_ISTAT_LFSR_LOCKUP
) {
224 writel(STARFIVE_ISTAT_LFSR_LOCKUP
, trng
->base
+ STARFIVE_ISTAT
);
225 /* SEU occurred, reseeding required*/
226 spin_lock(&trng
->write_lock
);
227 writel(STARFIVE_CTRL_EXEC_RANDRESEED
, trng
->base
+ STARFIVE_CTRL
);
228 spin_unlock(&trng
->write_lock
);
234 static void starfive_trng_cleanup(struct hwrng
*rng
)
236 struct starfive_trng
*trng
= to_trng(rng
);
238 writel(0, trng
->base
+ STARFIVE_CTRL
);
240 reset_control_assert(trng
->rst
);
241 clk_disable_unprepare(trng
->hclk
);
242 clk_disable_unprepare(trng
->ahb
);
245 static int starfive_trng_read(struct hwrng
*rng
, void *buf
, size_t max
, bool wait
)
247 struct starfive_trng
*trng
= to_trng(rng
);
250 pm_runtime_get_sync(trng
->dev
);
252 if (trng
->mode
== PRNG_256BIT
)
253 max
= min_t(size_t, max
, (STARFIVE_RAND_LEN
* 8));
255 max
= min_t(size_t, max
, (STARFIVE_RAND_LEN
* 4));
258 ret
= starfive_trng_wait_idle(trng
);
263 ret
= starfive_trng_cmd(trng
, STARFIVE_CTRL_GENE_RANDNUM
, wait
);
267 memcpy_fromio(buf
, trng
->base
+ STARFIVE_RAND0
, max
);
269 pm_runtime_put_sync_autosuspend(trng
->dev
);
274 static int starfive_trng_probe(struct platform_device
*pdev
)
278 struct starfive_trng
*trng
;
280 trng
= devm_kzalloc(&pdev
->dev
, sizeof(*trng
), GFP_KERNEL
);
284 platform_set_drvdata(pdev
, trng
);
285 trng
->dev
= &pdev
->dev
;
287 trng
->base
= devm_platform_ioremap_resource(pdev
, 0);
288 if (IS_ERR(trng
->base
))
289 return dev_err_probe(&pdev
->dev
, PTR_ERR(trng
->base
),
290 "Error remapping memory for platform device.\n");
292 irq
= platform_get_irq(pdev
, 0);
296 init_completion(&trng
->random_done
);
297 init_completion(&trng
->reseed_done
);
298 spin_lock_init(&trng
->write_lock
);
300 ret
= devm_request_irq(&pdev
->dev
, irq
, starfive_trng_irq
, 0, pdev
->name
,
303 return dev_err_probe(&pdev
->dev
, ret
,
304 "Failed to register interrupt handler\n");
306 trng
->hclk
= devm_clk_get(&pdev
->dev
, "hclk");
307 if (IS_ERR(trng
->hclk
))
308 return dev_err_probe(&pdev
->dev
, PTR_ERR(trng
->hclk
),
309 "Error getting hardware reference clock\n");
311 trng
->ahb
= devm_clk_get(&pdev
->dev
, "ahb");
312 if (IS_ERR(trng
->ahb
))
313 return dev_err_probe(&pdev
->dev
, PTR_ERR(trng
->ahb
),
314 "Error getting ahb reference clock\n");
316 trng
->rst
= devm_reset_control_get_shared(&pdev
->dev
, NULL
);
317 if (IS_ERR(trng
->rst
))
318 return dev_err_probe(&pdev
->dev
, PTR_ERR(trng
->rst
),
319 "Error getting hardware reset line\n");
321 clk_prepare_enable(trng
->hclk
);
322 clk_prepare_enable(trng
->ahb
);
323 reset_control_deassert(trng
->rst
);
325 trng
->rng
.name
= dev_driver_string(&pdev
->dev
);
326 trng
->rng
.init
= starfive_trng_init
;
327 trng
->rng
.cleanup
= starfive_trng_cleanup
;
328 trng
->rng
.read
= starfive_trng_read
;
330 trng
->mode
= PRNG_256BIT
;
332 trng
->reseed
= RANDOM_RESEED
;
334 pm_runtime_use_autosuspend(&pdev
->dev
);
335 pm_runtime_set_autosuspend_delay(&pdev
->dev
, 100);
336 pm_runtime_enable(&pdev
->dev
);
338 ret
= devm_hwrng_register(&pdev
->dev
, &trng
->rng
);
340 pm_runtime_disable(&pdev
->dev
);
342 reset_control_assert(trng
->rst
);
343 clk_disable_unprepare(trng
->ahb
);
344 clk_disable_unprepare(trng
->hclk
);
346 return dev_err_probe(&pdev
->dev
, ret
, "Failed to register hwrng\n");
352 static int __maybe_unused
starfive_trng_suspend(struct device
*dev
)
354 struct starfive_trng
*trng
= dev_get_drvdata(dev
);
356 clk_disable_unprepare(trng
->hclk
);
357 clk_disable_unprepare(trng
->ahb
);
362 static int __maybe_unused
starfive_trng_resume(struct device
*dev
)
364 struct starfive_trng
*trng
= dev_get_drvdata(dev
);
366 clk_prepare_enable(trng
->hclk
);
367 clk_prepare_enable(trng
->ahb
);
372 static const struct dev_pm_ops starfive_trng_pm_ops
= {
373 SET_SYSTEM_SLEEP_PM_OPS(starfive_trng_suspend
,
374 starfive_trng_resume
)
375 SET_RUNTIME_PM_OPS(starfive_trng_suspend
,
376 starfive_trng_resume
, NULL
)
379 static const struct of_device_id trng_dt_ids
[] __maybe_unused
= {
380 { .compatible
= "starfive,jh7110-trng" },
383 MODULE_DEVICE_TABLE(of
, trng_dt_ids
);
385 static struct platform_driver starfive_trng_driver
= {
386 .probe
= starfive_trng_probe
,
388 .name
= "jh7110-trng",
389 .pm
= &starfive_trng_pm_ops
,
390 .of_match_table
= of_match_ptr(trng_dt_ids
),
394 module_platform_driver(starfive_trng_driver
);
396 MODULE_LICENSE("GPL");
397 MODULE_DESCRIPTION("StarFive True Random Number Generator");