Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
c6a97c4
Documentation
arch
block
certs
crypto
drivers
accessibility
acpi
amba
android
ata
atm
auxdisplay
base
bcma
block
bluetooth
bus
cdrom
char
agp
hw_random
Kconfig
Makefile
amd-rng.c
atmel-rng.c
bcm2835-rng.c
bcm63xx-rng.c
core.c
exynos-rng.c
geode-rng.c
intel-rng.c
iproc-rng200.c
ixp4xx-rng.c
msm-rng.c
mxc-rnga.c
n2-asm.S
n2-drv.c
n2rng.h
nomadik-rng.c
octeon-rng.c
omap-rng.c
omap3-rom-rng.c
pasemi-rng.c
powernv-rng.c
ppc4xx-rng.c
pseries-rng.c
st-rng.c
stm32-rng.c
timeriomem-rng.c
tpm-rng.c
tx4939-rng.c
via-rng.c
virtio-rng.c
xgene-rng.c
ipmi
mwave
pcmcia
tpm
xilinx_hwicap
xillybus
Kconfig
Makefile
apm-emulation.c
applicom.c
applicom.h
bfin-otp.c
bsr.c
ds1302.c
ds1620.c
dsp56k.c
dtlk.c
efirtc.c
generic_nvram.c
genrtc.c
hangcheck-timer.c
hpet.c
lp.c
mbcs.c
mbcs.h
mem.c
misc.c
mmtimer.c
mspec.c
nsc_gpio.c
nvram.c
nwbutton.c
nwbutton.h
nwflash.c
pc8736x_gpio.c
ppdev.c
ps3flash.c
random.c
raw.c
rtc.c
scx200_gpio.c
snsc.c
snsc.h
snsc_event.c
sonypi.c
tb0219.c
tile-srom.c
tlclk.c
toshiba.c
ttyprintk.c
uv_mmtimer.c
virtio_console.c
clk
clocksource
connector
cpufreq
cpuidle
crypto
dca
devfreq
dio
dma-buf
dma
edac
eisa
extcon
firewire
firmware
fmc
gpio
gpu
hid
hsi
hv
hwmon
hwspinlock
hwtracing
i2c
ide
idle
iio
infiniband
input
iommu
ipack
irqchip
isdn
leds
lguest
macintosh
mailbox
mcb
md
media
memory
memstick
message
mfd
misc
mmc
mtd
net
nfc
ntb
nubus
nvdimm
nvmem
of
oprofile
parisc
parport
pci
pcmcia
perf
phy
pinctrl
platform
pnp
power
powercap
pps
ps3
ptp
pwm
rapidio
ras
regulator
remoteproc
reset
rpmsg
rtc
s390
sbus
scsi
sfi
sh
sn
soc
spi
spmi
ssb
staging
target
tc
thermal
thunderbolt
tty
uio
usb
uwb
vfio
vhost
video
virt
virtio
vlynq
vme
w1
watchdog
xen
zorro
Kconfig
Makefile
firmware
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
usr
virt
.get_maintainer.ignore
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
REPORTING-BUGS
Breadcrumbs
linux
/
drivers
/
char
/
hw_random
/
stm32-rng.c
Blame
Blame
Latest commit
History
History
202 lines (160 loc) · 4.89 KB
Breadcrumbs
linux
/
drivers
/
char
/
hw_random
/
stm32-rng.c
Top
File metadata and controls
Code
Blame
202 lines (160 loc) · 4.89 KB
Raw
/* * Copyright (c) 2015, Daniel Thompson * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <linux/clk.h> #include <linux/delay.h> #include <linux/hw_random.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/pm_runtime.h> #include <linux/slab.h> #define RNG_CR 0x00 #define RNG_CR_RNGEN BIT(2) #define RNG_SR 0x04 #define RNG_SR_SEIS BIT(6) #define RNG_SR_CEIS BIT(5) #define RNG_SR_DRDY BIT(0) #define RNG_DR 0x08 /* * It takes 40 cycles @ 48MHz to generate each random number (e.g. <1us). * At the time of writing STM32 parts max out at ~200MHz meaning a timeout * of 500 leaves us a very comfortable margin for error. The loop to which * the timeout applies takes at least 4 instructions per iteration so the * timeout is enough to take us up to multi-GHz parts! */ #define RNG_TIMEOUT 500 struct stm32_rng_private { struct hwrng rng; void __iomem *base; struct clk *clk; }; static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) { struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng); u32 sr; int retval = 0; pm_runtime_get_sync((struct device *) priv->rng.priv); while (max > sizeof(u32)) { sr = readl_relaxed(priv->base + RNG_SR); if (!sr && wait) { unsigned int timeout = RNG_TIMEOUT; do { cpu_relax(); sr = readl_relaxed(priv->base + RNG_SR); } while (!sr && --timeout); } /* If error detected or data not ready... */ if (sr != RNG_SR_DRDY) break; *(u32 *)data = readl_relaxed(priv->base + RNG_DR); retval += sizeof(u32); data += sizeof(u32); max -= sizeof(u32); } if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS), "bad RNG status - %x\n", sr)) writel_relaxed(0, priv->base + RNG_SR); pm_runtime_mark_last_busy((struct device *) priv->rng.priv); pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv); return retval || !wait ? retval : -EIO; } static int stm32_rng_init(struct hwrng *rng) { struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng); int err; err = clk_prepare_enable(priv->clk); if (err) return err; writel_relaxed(RNG_CR_RNGEN, priv->base + RNG_CR); /* clear error indicators */ writel_relaxed(0, priv->base + RNG_SR); return 0; } static void stm32_rng_cleanup(struct hwrng *rng) { struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng); writel_relaxed(0, priv->base + RNG_CR); clk_disable_unprepare(priv->clk); } static int stm32_rng_probe(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; struct device_node *np = ofdev->dev.of_node; struct stm32_rng_private *priv; struct resource res; int err; priv = devm_kzalloc(dev, sizeof(struct stm32_rng_private), GFP_KERNEL); if (!priv) return -ENOMEM; err = of_address_to_resource(np, 0, &res); if (err) return err; priv->base = devm_ioremap_resource(dev, &res); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); priv->clk = devm_clk_get(&ofdev->dev, NULL); if (IS_ERR(priv->clk)) return PTR_ERR(priv->clk); dev_set_drvdata(dev, priv); priv->rng.name = dev_driver_string(dev), #ifndef CONFIG_PM priv->rng.init = stm32_rng_init, priv->rng.cleanup = stm32_rng_cleanup, #endif priv->rng.read = stm32_rng_read, priv->rng.priv = (unsigned long) dev; pm_runtime_set_autosuspend_delay(dev, 100); pm_runtime_use_autosuspend(dev); pm_runtime_enable(dev); return devm_hwrng_register(dev, &priv->rng); } #ifdef CONFIG_PM static int stm32_rng_runtime_suspend(struct device *dev) { struct stm32_rng_private *priv = dev_get_drvdata(pdev); stm32_rng_cleanup(&priv->rng); return 0; } static int stm32_rng_runtime_resume(struct device *dev) { struct stm32_rng_private *priv = dev_get_drvdata(pdev); return stm32_rng_init(&priv->rng); } #endif static UNIVERSAL_DEV_PM_OPS(stm32_rng_pm_ops, stm32_rng_runtime_suspend, stm32_rng_runtime_resume, NULL); static const struct of_device_id stm32_rng_match[] = { { .compatible = "st,stm32-rng", }, {}, }; MODULE_DEVICE_TABLE(of, stm32_rng_match); static struct platform_driver stm32_rng_driver = { .driver = { .name = "stm32-rng", .pm = &stm32_rng_pm_ops, .of_match_table = stm32_rng_match, }, .probe = stm32_rng_probe, }; module_platform_driver(stm32_rng_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Daniel Thompson <daniel.thompson@linaro.org>"); MODULE_DESCRIPTION("STMicroelectronics STM32 RNG device driver");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
You can’t perform that action at this time.