1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2006-2007 PA Semi, Inc
5 * Maintained by: Olof Johansson <olof@lixom.net>
7 * Driver for the PWRficient onchip rng
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/platform_device.h>
13 #include <linux/hw_random.h>
14 #include <linux/delay.h>
15 #include <linux/of_address.h>
16 #include <linux/of_platform.h>
19 #define SDCRNG_CTL_REG 0x00
20 #define SDCRNG_CTL_FVLD_M 0x0000f000
21 #define SDCRNG_CTL_FVLD_S 12
22 #define SDCRNG_CTL_KSZ 0x00000800
23 #define SDCRNG_CTL_RSRC_CRG 0x00000010
24 #define SDCRNG_CTL_RSRC_RRG 0x00000000
25 #define SDCRNG_CTL_CE 0x00000004
26 #define SDCRNG_CTL_RE 0x00000002
27 #define SDCRNG_CTL_DR 0x00000001
28 #define SDCRNG_CTL_SELECT_RRG_RNG (SDCRNG_CTL_RE | SDCRNG_CTL_RSRC_RRG)
29 #define SDCRNG_CTL_SELECT_CRG_RNG (SDCRNG_CTL_CE | SDCRNG_CTL_RSRC_CRG)
30 #define SDCRNG_VAL_REG 0x20
32 #define MODULE_NAME "pasemi_rng"
34 static int pasemi_rng_data_present(struct hwrng
*rng
, int wait
)
36 void __iomem
*rng_regs
= (void __iomem
*)rng
->priv
;
39 for (i
= 0; i
< 20; i
++) {
40 data
= (in_le32(rng_regs
+ SDCRNG_CTL_REG
)
41 & SDCRNG_CTL_FVLD_M
) ? 1 : 0;
49 static int pasemi_rng_data_read(struct hwrng
*rng
, u32
*data
)
51 void __iomem
*rng_regs
= (void __iomem
*)rng
->priv
;
52 *data
= in_le32(rng_regs
+ SDCRNG_VAL_REG
);
56 static int pasemi_rng_init(struct hwrng
*rng
)
58 void __iomem
*rng_regs
= (void __iomem
*)rng
->priv
;
61 ctl
= SDCRNG_CTL_DR
| SDCRNG_CTL_SELECT_RRG_RNG
| SDCRNG_CTL_KSZ
;
62 out_le32(rng_regs
+ SDCRNG_CTL_REG
, ctl
);
63 out_le32(rng_regs
+ SDCRNG_CTL_REG
, ctl
& ~SDCRNG_CTL_DR
);
68 static void pasemi_rng_cleanup(struct hwrng
*rng
)
70 void __iomem
*rng_regs
= (void __iomem
*)rng
->priv
;
73 ctl
= SDCRNG_CTL_RE
| SDCRNG_CTL_CE
;
74 out_le32(rng_regs
+ SDCRNG_CTL_REG
,
75 in_le32(rng_regs
+ SDCRNG_CTL_REG
) & ~ctl
);
78 static struct hwrng pasemi_rng
= {
80 .init
= pasemi_rng_init
,
81 .cleanup
= pasemi_rng_cleanup
,
82 .data_present
= pasemi_rng_data_present
,
83 .data_read
= pasemi_rng_data_read
,
86 static int rng_probe(struct platform_device
*pdev
)
88 void __iomem
*rng_regs
;
90 rng_regs
= devm_platform_ioremap_resource(pdev
, 0);
92 return PTR_ERR(rng_regs
);
94 pasemi_rng
.priv
= (unsigned long)rng_regs
;
96 pr_info("Registering PA Semi RNG\n");
97 return devm_hwrng_register(&pdev
->dev
, &pasemi_rng
);
100 static const struct of_device_id rng_match
[] = {
101 { .compatible
= "1682m-rng", },
102 { .compatible
= "pasemi,pwrficient-rng", },
105 MODULE_DEVICE_TABLE(of
, rng_match
);
107 static struct platform_driver rng_driver
= {
109 .name
= "pasemi-rng",
110 .of_match_table
= rng_match
,
115 module_platform_driver(rng_driver
);
117 MODULE_LICENSE("GPL");
118 MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>");
119 MODULE_DESCRIPTION("H/W RNG driver for PA Semi processor");