|
@@ -24,12 +24,22 @@
|
|
|
|
|
|
struct powernv_rng {
|
|
|
void __iomem *regs;
|
|
|
+ void __iomem *regs_real;
|
|
|
unsigned long mask;
|
|
|
};
|
|
|
|
|
|
static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
|
|
|
|
|
|
|
|
|
+int powernv_hwrng_present(void)
|
|
|
+{
|
|
|
+ struct powernv_rng *rng;
|
|
|
+
|
|
|
+ rng = get_cpu_var(powernv_rng);
|
|
|
+ put_cpu_var(rng);
|
|
|
+ return rng != NULL;
|
|
|
+}
|
|
|
+
|
|
|
static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
|
|
|
{
|
|
|
unsigned long parity;
|
|
@@ -46,6 +56,17 @@ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
|
|
|
return val;
|
|
|
}
|
|
|
|
|
|
+int powernv_get_random_real_mode(unsigned long *v)
|
|
|
+{
|
|
|
+ struct powernv_rng *rng;
|
|
|
+
|
|
|
+ rng = raw_cpu_read(powernv_rng);
|
|
|
+
|
|
|
+ *v = rng_whiten(rng, in_rm64(rng->regs_real));
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
int powernv_get_random_long(unsigned long *v)
|
|
|
{
|
|
|
struct powernv_rng *rng;
|
|
@@ -80,12 +101,20 @@ static __init void rng_init_per_cpu(struct powernv_rng *rng,
|
|
|
static __init int rng_create(struct device_node *dn)
|
|
|
{
|
|
|
struct powernv_rng *rng;
|
|
|
+ struct resource res;
|
|
|
unsigned long val;
|
|
|
|
|
|
rng = kzalloc(sizeof(*rng), GFP_KERNEL);
|
|
|
if (!rng)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ if (of_address_to_resource(dn, 0, &res)) {
|
|
|
+ kfree(rng);
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ rng->regs_real = (void __iomem *)res.start;
|
|
|
+
|
|
|
rng->regs = of_iomap(dn, 0);
|
|
|
if (!rng->regs) {
|
|
|
kfree(rng);
|