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/mod_devicetable.h>
13 #include <linux/platform_device.h>
14 #include <linux/hw_random.h>
15 #include <linux/delay.h>
18 #define SDCRNG_CTL_REG 0x00
19 #define SDCRNG_CTL_FVLD_M 0x0000f000
20 #define SDCRNG_CTL_FVLD_S 12
21 #define SDCRNG_CTL_KSZ 0x00000800
22 #define SDCRNG_CTL_RSRC_CRG 0x00000010
23 #define SDCRNG_CTL_RSRC_RRG 0x00000000
24 #define SDCRNG_CTL_CE 0x00000004
25 #define SDCRNG_CTL_RE 0x00000002
26 #define SDCRNG_CTL_DR 0x00000001
27 #define SDCRNG_CTL_SELECT_RRG_RNG (SDCRNG_CTL_RE | SDCRNG_CTL_RSRC_RRG)
28 #define SDCRNG_CTL_SELECT_CRG_RNG (SDCRNG_CTL_CE | SDCRNG_CTL_RSRC_CRG)
29 #define SDCRNG_VAL_REG 0x20
31 #define MODULE_NAME "pasemi_rng"
33 static int pasemi_rng_data_present(struct hwrng
*rng
, int wait
)
35 void __iomem
*rng_regs
= (void __iomem
*)rng
->priv
;
38 for (i
= 0; i
< 20; i
++) {
39 data
= (in_le32(rng_regs
+ SDCRNG_CTL_REG
)
40 & SDCRNG_CTL_FVLD_M
) ? 1 : 0;
48 static int pasemi_rng_data_read(struct hwrng
*rng
, u32
*data
)
50 void __iomem
*rng_regs
= (void __iomem
*)rng
->priv
;
51 *data
= in_le32(rng_regs
+ SDCRNG_VAL_REG
);
55 static int pasemi_rng_init(struct hwrng
*rng
)
57 void __iomem
*rng_regs
= (void __iomem
*)rng
->priv
;
60 ctl
= SDCRNG_CTL_DR
| SDCRNG_CTL_SELECT_RRG_RNG
| SDCRNG_CTL_KSZ
;
61 out_le32(rng_regs
+ SDCRNG_CTL_REG
, ctl
);
62 out_le32(rng_regs
+ SDCRNG_CTL_REG
, ctl
& ~SDCRNG_CTL_DR
);
67 static void pasemi_rng_cleanup(struct hwrng
*rng
)
69 void __iomem
*rng_regs
= (void __iomem
*)rng
->priv
;
72 ctl
= SDCRNG_CTL_RE
| SDCRNG_CTL_CE
;
73 out_le32(rng_regs
+ SDCRNG_CTL_REG
,
74 in_le32(rng_regs
+ SDCRNG_CTL_REG
) & ~ctl
);
77 static struct hwrng pasemi_rng
= {
79 .init
= pasemi_rng_init
,
80 .cleanup
= pasemi_rng_cleanup
,
81 .data_present
= pasemi_rng_data_present
,
82 .data_read
= pasemi_rng_data_read
,
85 static int rng_probe(struct platform_device
*pdev
)
87 void __iomem
*rng_regs
;
89 rng_regs
= devm_platform_ioremap_resource(pdev
, 0);
91 return PTR_ERR(rng_regs
);
93 pasemi_rng
.priv
= (unsigned long)rng_regs
;
95 pr_info("Registering PA Semi RNG\n");
96 return devm_hwrng_register(&pdev
->dev
, &pasemi_rng
);
99 static const struct of_device_id rng_match
[] = {
100 { .compatible
= "1682m-rng", },
101 { .compatible
= "pasemi,pwrficient-rng", },
104 MODULE_DEVICE_TABLE(of
, rng_match
);
106 static struct platform_driver rng_driver
= {
108 .name
= "pasemi-rng",
109 .of_match_table
= rng_match
,
114 module_platform_driver(rng_driver
);
116 MODULE_LICENSE("GPL");
117 MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>");
118 MODULE_DESCRIPTION("H/W RNG driver for PA Semi processor");