Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/char/hw_random/pasemi-rng.c
15112 views
1
/*
2
* Copyright (C) 2006-2007 PA Semi, Inc
3
*
4
* Maintained by: Olof Johansson <[email protected]>
5
*
6
* Driver for the PWRficient onchip rng
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2 as
10
* published by the Free Software Foundation.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
*/
21
22
#include <linux/module.h>
23
#include <linux/kernel.h>
24
#include <linux/platform_device.h>
25
#include <linux/hw_random.h>
26
#include <linux/delay.h>
27
#include <linux/of_platform.h>
28
#include <asm/io.h>
29
30
#define SDCRNG_CTL_REG 0x00
31
#define SDCRNG_CTL_FVLD_M 0x0000f000
32
#define SDCRNG_CTL_FVLD_S 12
33
#define SDCRNG_CTL_KSZ 0x00000800
34
#define SDCRNG_CTL_RSRC_CRG 0x00000010
35
#define SDCRNG_CTL_RSRC_RRG 0x00000000
36
#define SDCRNG_CTL_CE 0x00000004
37
#define SDCRNG_CTL_RE 0x00000002
38
#define SDCRNG_CTL_DR 0x00000001
39
#define SDCRNG_CTL_SELECT_RRG_RNG (SDCRNG_CTL_RE | SDCRNG_CTL_RSRC_RRG)
40
#define SDCRNG_CTL_SELECT_CRG_RNG (SDCRNG_CTL_CE | SDCRNG_CTL_RSRC_CRG)
41
#define SDCRNG_VAL_REG 0x20
42
43
#define MODULE_NAME "pasemi_rng"
44
45
static int pasemi_rng_data_present(struct hwrng *rng, int wait)
46
{
47
void __iomem *rng_regs = (void __iomem *)rng->priv;
48
int data, i;
49
50
for (i = 0; i < 20; i++) {
51
data = (in_le32(rng_regs + SDCRNG_CTL_REG)
52
& SDCRNG_CTL_FVLD_M) ? 1 : 0;
53
if (data || !wait)
54
break;
55
udelay(10);
56
}
57
return data;
58
}
59
60
static int pasemi_rng_data_read(struct hwrng *rng, u32 *data)
61
{
62
void __iomem *rng_regs = (void __iomem *)rng->priv;
63
*data = in_le32(rng_regs + SDCRNG_VAL_REG);
64
return 4;
65
}
66
67
static int pasemi_rng_init(struct hwrng *rng)
68
{
69
void __iomem *rng_regs = (void __iomem *)rng->priv;
70
u32 ctl;
71
72
ctl = SDCRNG_CTL_DR | SDCRNG_CTL_SELECT_RRG_RNG | SDCRNG_CTL_KSZ;
73
out_le32(rng_regs + SDCRNG_CTL_REG, ctl);
74
out_le32(rng_regs + SDCRNG_CTL_REG, ctl & ~SDCRNG_CTL_DR);
75
76
return 0;
77
}
78
79
static void pasemi_rng_cleanup(struct hwrng *rng)
80
{
81
void __iomem *rng_regs = (void __iomem *)rng->priv;
82
u32 ctl;
83
84
ctl = SDCRNG_CTL_RE | SDCRNG_CTL_CE;
85
out_le32(rng_regs + SDCRNG_CTL_REG,
86
in_le32(rng_regs + SDCRNG_CTL_REG) & ~ctl);
87
}
88
89
static struct hwrng pasemi_rng = {
90
.name = MODULE_NAME,
91
.init = pasemi_rng_init,
92
.cleanup = pasemi_rng_cleanup,
93
.data_present = pasemi_rng_data_present,
94
.data_read = pasemi_rng_data_read,
95
};
96
97
static int __devinit rng_probe(struct platform_device *ofdev)
98
{
99
void __iomem *rng_regs;
100
struct device_node *rng_np = ofdev->dev.of_node;
101
struct resource res;
102
int err = 0;
103
104
err = of_address_to_resource(rng_np, 0, &res);
105
if (err)
106
return -ENODEV;
107
108
rng_regs = ioremap(res.start, 0x100);
109
110
if (!rng_regs)
111
return -ENOMEM;
112
113
pasemi_rng.priv = (unsigned long)rng_regs;
114
115
printk(KERN_INFO "Registering PA Semi RNG\n");
116
117
err = hwrng_register(&pasemi_rng);
118
119
if (err)
120
iounmap(rng_regs);
121
122
return err;
123
}
124
125
static int __devexit rng_remove(struct platform_device *dev)
126
{
127
void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv;
128
129
hwrng_unregister(&pasemi_rng);
130
iounmap(rng_regs);
131
132
return 0;
133
}
134
135
static struct of_device_id rng_match[] = {
136
{ .compatible = "1682m-rng", },
137
{ .compatible = "pasemi,pwrficient-rng", },
138
{ },
139
};
140
141
static struct platform_driver rng_driver = {
142
.driver = {
143
.name = "pasemi-rng",
144
.owner = THIS_MODULE,
145
.of_match_table = rng_match,
146
},
147
.probe = rng_probe,
148
.remove = rng_remove,
149
};
150
151
static int __init rng_init(void)
152
{
153
return platform_driver_register(&rng_driver);
154
}
155
module_init(rng_init);
156
157
static void __exit rng_exit(void)
158
{
159
platform_driver_unregister(&rng_driver);
160
}
161
module_exit(rng_exit);
162
163
MODULE_LICENSE("GPL");
164
MODULE_AUTHOR("Egor Martovetsky <[email protected]>");
165
MODULE_DESCRIPTION("H/W RNG driver for PA Semi processor");
166
167