n2-drv.c revision 3f4528d6e91cffde49894f5252e6657d420d3d74
1ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller/* n2-drv.c: Niagara-2 RNG driver.
2ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
3ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
4ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller */
5ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
6ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/kernel.h>
7ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/module.h>
8ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/types.h>
9ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/delay.h>
10ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/init.h>
11ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/slab.h>
12ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/workqueue.h>
13ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/preempt.h>
14ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/hw_random.h>
15ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
16ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/of.h>
17ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <linux/of_device.h>
18ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
19ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include <asm/hypervisor.h>
20ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
21ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#include "n2rng.h"
22ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
23ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#define DRV_MODULE_NAME		"n2rng"
24ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#define PFX DRV_MODULE_NAME	": "
25ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#define DRV_MODULE_VERSION	"0.1"
26ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#define DRV_MODULE_RELDATE	"May 15, 2008"
27ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
28ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic char version[] __devinitdata =
29ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
30ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
31ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. MillerMODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
32ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. MillerMODULE_DESCRIPTION("Niagara2 RNG driver");
33ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. MillerMODULE_LICENSE("GPL");
34ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. MillerMODULE_VERSION(DRV_MODULE_VERSION);
35ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
36ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller/* The Niagara2 RNG provides a 64-bit read-only random number
37ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * register, plus a control register.  Access to the RNG is
38ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * virtualized through the hypervisor so that both guests and control
39ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * nodes can access the device.
40ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
41ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * The entropy source consists of raw entropy sources, each
42ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * constructed from a voltage controlled oscillator whose phase is
43ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * jittered by thermal noise sources.
44ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
45ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * The oscillator in each of the three raw entropy sources run at
46ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * different frequencies.  Normally, all three generator outputs are
47ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * gathered, xored together, and fed into a CRC circuit, the output of
48ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * which is the 64-bit read-only register.
49ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
50ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * Some time is necessary for all the necessary entropy to build up
51ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * such that a full 64-bits of entropy are available in the register.
52ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * In normal operating mode (RNG_CTL_LFSR is set), the chip implements
53ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * an interlock which blocks register reads until sufficient entropy
54ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * is available.
55ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
56ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * A control register is provided for adjusting various aspects of RNG
57ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * operation, and to enable diagnostic modes.  Each of the three raw
58ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * entropy sources has an enable bit (RNG_CTL_ES{1,2,3}).  Also
59ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * provided are fields for controlling the minimum time in cycles
60ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * between read accesses to the register (RNG_CTL_WAIT, this controls
61ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * the interlock described in the previous paragraph).
62ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
63ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * The standard setting is to have the mode bit (RNG_CTL_LFSR) set,
64ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * all three entropy sources enabled, and the interlock time set
65ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * appropriately.
66ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
67ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * The CRC polynomial used by the chip is:
68ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
69ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * P(X) = x64 + x61 + x57 + x56 + x52 + x51 + x50 + x48 + x47 + x46 +
70ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *        x43 + x42 + x41 + x39 + x38 + x37 + x35 + x32 + x28 + x25 +
71ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *        x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1
72ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
73ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * The RNG_CTL_VCO value of each noise cell must be programmed
74ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * seperately.  This is why 4 control register values must be provided
75ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * to the hypervisor.  During a write, the hypervisor writes them all,
76ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * one at a time, to the actual RNG_CTL register.  The first three
77ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * values are used to setup the desired RNG_CTL_VCO for each entropy
78ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * source, for example:
79ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
80ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *	control 0: (1 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES1
81ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *	control 1: (2 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES2
82ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *	control 2: (3 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES3
83ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
84ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * And then the fourth value sets the final chip state and enables
85ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * desired.
86ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller */
87ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
88ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_hv_err_trans(unsigned long hv_err)
89ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
90ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	switch (hv_err) {
91ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	case HV_EOK:
92ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return 0;
93ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	case HV_EWOULDBLOCK:
94ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return -EAGAIN;
95ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	case HV_ENOACCESS:
96ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return -EPERM;
97ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	case HV_EIO:
98ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return -EIO;
99ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	case HV_EBUSY:
100ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return -EBUSY;
101ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	case HV_EBADALIGN:
102ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	case HV_ENORADDR:
103ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return -EFAULT;
104ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	default:
105ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return -EINVAL;
106ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
107ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
108ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
109ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic unsigned long n2rng_generic_read_control_v2(unsigned long ra,
110ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller						   unsigned long unit)
111ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
112ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long hv_err, state, ticks, watchdog_delta, watchdog_status;
113ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int block = 0, busy = 0;
114ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
115ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	while (1) {
116ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		hv_err = sun4v_rng_ctl_read_v2(ra, unit, &state,
117ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					       &ticks,
118ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					       &watchdog_delta,
119ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					       &watchdog_status);
120ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (hv_err == HV_EOK)
121ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			break;
122ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
123ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (hv_err == HV_EBUSY) {
124ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			if (++busy >= N2RNG_BUSY_LIMIT)
125ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				break;
126ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
127ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			udelay(1);
128ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else if (hv_err == HV_EWOULDBLOCK) {
129ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			if (++block >= N2RNG_BLOCK_LIMIT)
130ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				break;
131ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
132ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			__delay(ticks);
133ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else
134ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			break;
135ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
136ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
137ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return hv_err;
138ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
139ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
140ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller/* In multi-socket situations, the hypervisor might need to
141ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * queue up the RNG control register write if it's for a unit
142ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * that is on a cpu socket other than the one we are executing on.
143ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller *
144ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * We poll here waiting for a successful read of that control
145ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * register to make sure the write has been actually performed.
146ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller */
147ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic unsigned long n2rng_control_settle_v2(struct n2rng *np, int unit)
148ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
149ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long ra = __pa(&np->scratch_control[0]);
150ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
151ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return n2rng_generic_read_control_v2(ra, unit);
152ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
153ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
154ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic unsigned long n2rng_write_ctl_one(struct n2rng *np, int unit,
155ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					 unsigned long state,
156ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					 unsigned long control_ra,
157ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					 unsigned long watchdog_timeout,
158ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					 unsigned long *ticks)
159ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
160ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long hv_err;
161ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
162ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (np->hvapi_major == 1) {
163ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		hv_err = sun4v_rng_ctl_write_v1(control_ra, state,
164ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller						watchdog_timeout, ticks);
165ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	} else {
166ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		hv_err = sun4v_rng_ctl_write_v2(control_ra, state,
167ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller						watchdog_timeout, unit);
168ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (hv_err == HV_EOK)
169ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			hv_err = n2rng_control_settle_v2(np, unit);
170ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		*ticks = N2RNG_ACCUM_CYCLES_DEFAULT;
171ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
172ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
173ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return hv_err;
174ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
175ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
176ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_generic_read_data(unsigned long data_ra)
177ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
178ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long ticks, hv_err;
179ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int block = 0, hcheck = 0;
180ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
181ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	while (1) {
182ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		hv_err = sun4v_rng_data_read(data_ra, &ticks);
183ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (hv_err == HV_EOK)
184ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return 0;
185ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
186ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (hv_err == HV_EWOULDBLOCK) {
187ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			if (++block >= N2RNG_BLOCK_LIMIT)
188ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				return -EWOULDBLOCK;
189ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			__delay(ticks);
190ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else if (hv_err == HV_ENOACCESS) {
191ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return -EPERM;
192ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else if (hv_err == HV_EIO) {
193ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			if (++hcheck >= N2RNG_HCHECK_LIMIT)
194ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				return -EIO;
195ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			udelay(10000);
196ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else
197ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return -ENODEV;
198ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
199ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
200ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
201ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic unsigned long n2rng_read_diag_data_one(struct n2rng *np,
202ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					      unsigned long unit,
203ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					      unsigned long data_ra,
204ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					      unsigned long data_len,
205ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					      unsigned long *ticks)
206ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
207ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long hv_err;
208ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
209ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (np->hvapi_major == 1) {
210ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		hv_err = sun4v_rng_data_read_diag_v1(data_ra, data_len, ticks);
211ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	} else {
212ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		hv_err = sun4v_rng_data_read_diag_v2(data_ra, data_len,
213ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller						     unit, ticks);
214ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (!*ticks)
215ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			*ticks = N2RNG_ACCUM_CYCLES_DEFAULT;
216ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
217ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return hv_err;
218ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
219ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
220ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_generic_read_diag_data(struct n2rng *np,
221ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					unsigned long unit,
222ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					unsigned long data_ra,
223ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					unsigned long data_len)
224ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
225ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long ticks, hv_err;
226ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int block = 0;
227ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
228ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	while (1) {
229ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		hv_err = n2rng_read_diag_data_one(np, unit,
230ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller						  data_ra, data_len,
231ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller						  &ticks);
232ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (hv_err == HV_EOK)
233ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return 0;
234ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
235ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (hv_err == HV_EWOULDBLOCK) {
236ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			if (++block >= N2RNG_BLOCK_LIMIT)
237ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				return -EWOULDBLOCK;
238ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			__delay(ticks);
239ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else if (hv_err == HV_ENOACCESS) {
240ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return -EPERM;
241ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else if (hv_err == HV_EIO) {
242ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return -EIO;
243ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else
244ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return -ENODEV;
245ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
246ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
247ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
248ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
249ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_generic_write_control(struct n2rng *np,
250ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				       unsigned long control_ra,
251ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				       unsigned long unit,
252ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				       unsigned long state)
253ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
254ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long hv_err, ticks;
255ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int block = 0, busy = 0;
256ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
257ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	while (1) {
258ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		hv_err = n2rng_write_ctl_one(np, unit, state, control_ra,
259ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					     np->wd_timeo, &ticks);
260ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (hv_err == HV_EOK)
261ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return 0;
262ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
263ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (hv_err == HV_EWOULDBLOCK) {
264ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			if (++block >= N2RNG_BLOCK_LIMIT)
265ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				return -EWOULDBLOCK;
266ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			__delay(ticks);
267ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else if (hv_err == HV_EBUSY) {
268ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			if (++busy >= N2RNG_BUSY_LIMIT)
269ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				return -EBUSY;
270ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			udelay(1);
271ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else
272ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return -ENODEV;
273ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
274ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
275ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
276ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller/* Just try to see if we can successfully access the control register
277ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * of the RNG on the domain on which we are currently executing.
278ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller */
279ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_try_read_ctl(struct n2rng *np)
280ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
281ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long hv_err;
282ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long x;
283ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
284ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (np->hvapi_major == 1) {
285ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		hv_err = sun4v_rng_get_diag_ctl();
286ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	} else {
287ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		/* We purposefully give invalid arguments, HV_NOACCESS
288ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 * is higher priority than the errors we'd get from
289ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 * these other cases, and that's the error we are
290ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 * truly interested in.
291ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 */
292ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		hv_err = sun4v_rng_ctl_read_v2(0UL, ~0UL, &x, &x, &x, &x);
293ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		switch (hv_err) {
294ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		case HV_EWOULDBLOCK:
295ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		case HV_ENOACCESS:
296ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			break;
297ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		default:
298ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			hv_err = HV_EOK;
299ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			break;
300ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		}
301ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
302ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
303ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return n2rng_hv_err_trans(hv_err);
304ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
305ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
306ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#define CONTROL_DEFAULT_BASE		\
307ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	((2 << RNG_CTL_ASEL_SHIFT) |	\
308ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 (N2RNG_ACCUM_CYCLES_DEFAULT << RNG_CTL_WAIT_SHIFT) |	\
309ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 RNG_CTL_LFSR)
310ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
311ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#define CONTROL_DEFAULT_0		\
312ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	(CONTROL_DEFAULT_BASE |		\
313ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 (1 << RNG_CTL_VCO_SHIFT) |	\
314ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 RNG_CTL_ES1)
315ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#define CONTROL_DEFAULT_1		\
316ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	(CONTROL_DEFAULT_BASE |		\
317ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 (2 << RNG_CTL_VCO_SHIFT) |	\
318ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 RNG_CTL_ES2)
319ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#define CONTROL_DEFAULT_2		\
320ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	(CONTROL_DEFAULT_BASE |		\
321ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 (3 << RNG_CTL_VCO_SHIFT) |	\
322ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 RNG_CTL_ES3)
323ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller#define CONTROL_DEFAULT_3		\
324ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	(CONTROL_DEFAULT_BASE |		\
325ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 RNG_CTL_ES1 | RNG_CTL_ES2 | RNG_CTL_ES3)
326ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
327ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic void n2rng_control_swstate_init(struct n2rng *np)
328ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
329ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int i;
330ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
331ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->flags |= N2RNG_FLAG_CONTROL;
332ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
333ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->health_check_sec = N2RNG_HEALTH_CHECK_SEC_DEFAULT;
334ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->accum_cycles = N2RNG_ACCUM_CYCLES_DEFAULT;
335ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->wd_timeo = N2RNG_WD_TIMEO_DEFAULT;
336ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
337ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	for (i = 0; i < np->num_units; i++) {
338ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		struct n2rng_unit *up = &np->units[i];
339ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
340ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		up->control[0] = CONTROL_DEFAULT_0;
341ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		up->control[1] = CONTROL_DEFAULT_1;
342ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		up->control[2] = CONTROL_DEFAULT_2;
343ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		up->control[3] = CONTROL_DEFAULT_3;
344ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
345ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
346ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->hv_state = HV_RNG_STATE_UNCONFIGURED;
347ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
348ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
349ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_grab_diag_control(struct n2rng *np)
350ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
351ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int i, busy_count, err = -ENODEV;
352ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
353ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	busy_count = 0;
354ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	for (i = 0; i < 100; i++) {
355ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		err = n2rng_try_read_ctl(np);
356ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (err != -EAGAIN)
357ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			break;
358ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
359ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (++busy_count > 100) {
360ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			dev_err(&np->op->dev,
361ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				"Grab diag control timeout.\n");
362ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return -ENODEV;
363ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		}
364ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
365ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		udelay(1);
366ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
367ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
368ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return err;
369ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
370ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
371ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_init_control(struct n2rng *np)
372ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
373ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int err = n2rng_grab_diag_control(np);
374ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
375ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	/* Not in the control domain, that's OK we are only a consumer
376ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 * of the RNG data, we don't setup and program it.
377ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	 */
378ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (err == -EPERM)
379ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return 0;
380ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (err)
381ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return err;
382ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
383ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	n2rng_control_swstate_init(np);
384ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
385ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return 0;
386ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
387ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
388ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_data_read(struct hwrng *rng, u32 *data)
389ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
390ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	struct n2rng *np = (struct n2rng *) rng->priv;
391ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long ra = __pa(&np->test_data);
392ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int len;
393ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
394ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (!(np->flags & N2RNG_FLAG_READY)) {
395ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		len = 0;
396ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	} else if (np->flags & N2RNG_FLAG_BUFFER_VALID) {
397ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		np->flags &= ~N2RNG_FLAG_BUFFER_VALID;
398ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		*data = np->buffer;
399ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		len = 4;
400ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	} else {
401ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		int err = n2rng_generic_read_data(ra);
402ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (!err) {
403ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			np->buffer = np->test_data >> 32;
404ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			*data = np->test_data & 0xffffffff;
405ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			len = 4;
406ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		} else {
407ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			dev_err(&np->op->dev, "RNG error, restesting\n");
408ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			np->flags &= ~N2RNG_FLAG_READY;
409ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			if (!(np->flags & N2RNG_FLAG_SHUTDOWN))
410ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				schedule_delayed_work(&np->work, 0);
411ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			len = 0;
412ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		}
413ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
414ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
415ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return len;
416ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
417ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
418ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller/* On a guest node, just make sure we can read random data properly.
419ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * If a control node reboots or reloads it's n2rng driver, this won't
420ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * work during that time.  So we have to keep probing until the device
421ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * becomes usable.
422ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller */
423ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_guest_check(struct n2rng *np)
424ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
425ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long ra = __pa(&np->test_data);
426ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
427ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return n2rng_generic_read_data(ra);
428ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
429ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
430ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_entropy_diag_read(struct n2rng *np, unsigned long unit,
431ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				   u64 *pre_control, u64 pre_state,
432ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				   u64 *buffer, unsigned long buf_len,
433ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				   u64 *post_control, u64 post_state)
434ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
435ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long post_ctl_ra = __pa(post_control);
436ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long pre_ctl_ra = __pa(pre_control);
437ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	unsigned long buffer_ra = __pa(buffer);
438ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int err;
439ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
440ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	err = n2rng_generic_write_control(np, pre_ctl_ra, unit, pre_state);
441ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (err)
442ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return err;
443ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
444ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	err = n2rng_generic_read_diag_data(np, unit,
445ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					   buffer_ra, buf_len);
446ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
447ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	(void) n2rng_generic_write_control(np, post_ctl_ra, unit,
448ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					   post_state);
449ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
450ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return err;
451ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
452ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
453ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic u64 advance_polynomial(u64 poly, u64 val, int count)
454ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
455ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int i;
456ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
457ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	for (i = 0; i < count; i++) {
458ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		int highbit_set = ((s64)val < 0);
459ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
460ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		val <<= 1;
461ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (highbit_set)
462ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			val ^= poly;
463ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
464ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
465ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return val;
466ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
467ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
468ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_test_buffer_find(struct n2rng *np, u64 val)
469ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
470ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int i, count = 0;
471ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
472ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	/* Purposefully skip over the first word.  */
473ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	for (i = 1; i < SELFTEST_BUFFER_WORDS; i++) {
474ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (np->test_buffer[i] == val)
475ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			count++;
476ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
477ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return count;
478ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
479ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
480ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic void n2rng_dump_test_buffer(struct n2rng *np)
481ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
482ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int i;
483ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
484ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	for (i = 0; i < SELFTEST_BUFFER_WORDS; i++)
4853f4528d6e91cffde49894f5252e6657d420d3d74Sam Ravnborg		dev_err(&np->op->dev, "Test buffer slot %d [0x%016llx]\n",
486ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			i, np->test_buffer[i]);
487ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
488ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
489ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_check_selftest_buffer(struct n2rng *np, unsigned long unit)
490ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
491ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	u64 val = SELFTEST_VAL;
492ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int err, matches, limit;
493ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
494ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	matches = 0;
495ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	for (limit = 0; limit < SELFTEST_LOOPS_MAX; limit++) {
496ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		matches += n2rng_test_buffer_find(np, val);
497ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (matches >= SELFTEST_MATCH_GOAL)
498ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			break;
499ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		val = advance_polynomial(SELFTEST_POLY, val, 1);
500ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
501ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
502ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	err = 0;
503ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (limit >= SELFTEST_LOOPS_MAX) {
504ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		err = -ENODEV;
505ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		dev_err(&np->op->dev, "Selftest failed on unit %lu\n", unit);
506ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		n2rng_dump_test_buffer(np);
507ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	} else
508ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		dev_info(&np->op->dev, "Selftest passed on unit %lu\n", unit);
509ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
510ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return err;
511ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
512ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
513ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_control_selftest(struct n2rng *np, unsigned long unit)
514ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
515ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int err;
516ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
517ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->test_control[0] = (0x2 << RNG_CTL_ASEL_SHIFT);
518ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->test_control[1] = (0x2 << RNG_CTL_ASEL_SHIFT);
519ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->test_control[2] = (0x2 << RNG_CTL_ASEL_SHIFT);
520ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->test_control[3] = ((0x2 << RNG_CTL_ASEL_SHIFT) |
521ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			       RNG_CTL_LFSR |
522ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			       ((SELFTEST_TICKS - 2) << RNG_CTL_WAIT_SHIFT));
523ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
524ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
525ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	err = n2rng_entropy_diag_read(np, unit, np->test_control,
526ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				      HV_RNG_STATE_HEALTHCHECK,
527ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				      np->test_buffer,
528ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				      sizeof(np->test_buffer),
529ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				      &np->units[unit].control[0],
530ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				      np->hv_state);
531ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (err)
532ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		return err;
533ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
534ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return n2rng_check_selftest_buffer(np, unit);
535ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
536ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
537ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_control_check(struct n2rng *np)
538ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
539ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int i;
540ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
541ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	for (i = 0; i < np->num_units; i++) {
542ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		int err = n2rng_control_selftest(np, i);
543ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (err)
544ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			return err;
545ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
546ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return 0;
547ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
548ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
549ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller/* The sanity checks passed, install the final configuration into the
550ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller * chip, it's ready to use.
551ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller */
552ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int n2rng_control_configure_units(struct n2rng *np)
553ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
554ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int unit, err;
555ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
556ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	err = 0;
557ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	for (unit = 0; unit < np->num_units; unit++) {
558ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		struct n2rng_unit *up = &np->units[unit];
559ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		unsigned long ctl_ra = __pa(&up->control[0]);
560ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		int esrc;
561ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		u64 base;
562ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
563ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		base = ((np->accum_cycles << RNG_CTL_WAIT_SHIFT) |
564ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			(2 << RNG_CTL_ASEL_SHIFT) |
565ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			RNG_CTL_LFSR);
566ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
567ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		/* XXX This isn't the best.  We should fetch a bunch
568ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 * XXX of words using each entropy source combined XXX
569ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 * with each VCO setting, and see which combinations
570ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 * XXX give the best random data.
571ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 */
572ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		for (esrc = 0; esrc < 3; esrc++)
573ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			up->control[esrc] = base |
574ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				(esrc << RNG_CTL_VCO_SHIFT) |
575ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				(RNG_CTL_ES1 << esrc);
576ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
577ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		up->control[3] = base |
578ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			(RNG_CTL_ES1 | RNG_CTL_ES2 | RNG_CTL_ES3);
579ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
580ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		err = n2rng_generic_write_control(np, ctl_ra, unit,
581ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller						  HV_RNG_STATE_CONFIGURED);
582ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (err)
583ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			break;
584ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
585ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
586ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return err;
587ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
588ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
589ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic void n2rng_work(struct work_struct *work)
590ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
591ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	struct n2rng *np = container_of(work, struct n2rng, work.work);
592ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int err = 0;
593ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
594ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (!(np->flags & N2RNG_FLAG_CONTROL)) {
595ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		err = n2rng_guest_check(np);
596ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	} else {
597ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		preempt_disable();
598ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		err = n2rng_control_check(np);
599ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		preempt_enable();
600ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
601ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (!err)
602ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			err = n2rng_control_configure_units(np);
603ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
604ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
605ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (!err) {
606ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		np->flags |= N2RNG_FLAG_READY;
607ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		dev_info(&np->op->dev, "RNG ready\n");
608ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
609ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
610ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (err && !(np->flags & N2RNG_FLAG_SHUTDOWN))
611ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		schedule_delayed_work(&np->work, HZ * 2);
612ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
613ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
614ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic void __devinit n2rng_driver_version(void)
615ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
616ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	static int n2rng_version_printed;
617ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
618ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (n2rng_version_printed++ == 0)
619ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		pr_info("%s", version);
620ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
621ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
622ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int __devinit n2rng_probe(struct of_device *op,
623ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				 const struct of_device_id *match)
624ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
625ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int victoria_falls = (match->data != NULL);
626ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	int err = -ENOMEM;
627ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	struct n2rng *np;
628ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
629ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	n2rng_driver_version();
630ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
631ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np = kzalloc(sizeof(*np), GFP_KERNEL);
632ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (!np)
633ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		goto out;
634ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->op = op;
635ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
636ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	INIT_DELAYED_WORK(&np->work, n2rng_work);
637ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
638ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (victoria_falls)
639ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		np->flags |= N2RNG_FLAG_VF;
640ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
641ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	err = -ENODEV;
642ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->hvapi_major = 2;
643ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (sun4v_hvapi_register(HV_GRP_RNG,
644ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				 np->hvapi_major,
645ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				 &np->hvapi_minor)) {
646ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		np->hvapi_major = 1;
647ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (sun4v_hvapi_register(HV_GRP_RNG,
648ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					 np->hvapi_major,
649ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller					 &np->hvapi_minor)) {
650ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			dev_err(&op->dev, "Cannot register suitable "
651ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				"HVAPI version.\n");
652ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			goto out_free;
653ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		}
654ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	}
655ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
656ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (np->flags & N2RNG_FLAG_VF) {
657ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (np->hvapi_major < 2) {
658ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			dev_err(&op->dev, "VF RNG requires HVAPI major "
659ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				"version 2 or later, got %lu\n",
660ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller				np->hvapi_major);
661ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			goto out_hvapi_unregister;
662ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		}
663ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		np->num_units = of_getintprop_default(op->node,
664ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller						      "rng-#units", 0);
665ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		if (!np->num_units) {
666ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			dev_err(&op->dev, "VF RNG lacks rng-#units property\n");
667ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			goto out_hvapi_unregister;
668ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		}
669ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	} else
670ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		np->num_units = 1;
671ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
672ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	dev_info(&op->dev, "Registered RNG HVAPI major %lu minor %lu\n",
673ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 np->hvapi_major, np->hvapi_minor);
674ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
675ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->units = kzalloc(sizeof(struct n2rng_unit) * np->num_units,
676ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller			    GFP_KERNEL);
677ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	err = -ENOMEM;
678ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (!np->units)
679ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		goto out_hvapi_unregister;
680ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
681ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	err = n2rng_init_control(np);
682ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (err)
683ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		goto out_free_units;
684ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
685ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	dev_info(&op->dev, "Found %s RNG, units: %d\n",
686ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 ((np->flags & N2RNG_FLAG_VF) ?
687ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		  "Victoria Falls" : "Niagara2"),
688ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		 np->num_units);
689ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
690ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->hwrng.name = "n2rng";
691ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->hwrng.data_read = n2rng_data_read;
692ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->hwrng.priv = (unsigned long) np;
693ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
694ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	err = hwrng_register(&np->hwrng);
695ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	if (err)
696ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		goto out_free_units;
697ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
698ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	dev_set_drvdata(&op->dev, np);
699ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
700ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	schedule_delayed_work(&np->work, 0);
701ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
702ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return 0;
703ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
704ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerout_free_units:
705ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	kfree(np->units);
706ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->units = NULL;
707ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
708ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerout_hvapi_unregister:
709ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	sun4v_hvapi_unregister(HV_GRP_RNG);
710ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
711ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerout_free:
712ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	kfree(np);
713ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerout:
714ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return err;
715ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
716ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
717ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int __devexit n2rng_remove(struct of_device *op)
718ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
719ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	struct n2rng *np = dev_get_drvdata(&op->dev);
720ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
721ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->flags |= N2RNG_FLAG_SHUTDOWN;
722ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
723ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	cancel_delayed_work_sync(&np->work);
724ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
725ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	hwrng_unregister(&np->hwrng);
726ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
727ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	sun4v_hvapi_unregister(HV_GRP_RNG);
728ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
729ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	kfree(np->units);
730ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	np->units = NULL;
731ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
732ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	kfree(np);
733ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
734ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	dev_set_drvdata(&op->dev, NULL);
735ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
736ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return 0;
737ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
738ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
739fd098316ef533e8441576f020ead4beab93154ceDavid S. Millerstatic const struct of_device_id n2rng_match[] = {
740ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	{
741ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		.name		= "random-number-generator",
742ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		.compatible	= "SUNW,n2-rng",
743ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	},
744ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	{
745ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		.name		= "random-number-generator",
746ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		.compatible	= "SUNW,vf-rng",
747ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller		.data		= (void *) 1,
748ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	},
749ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	{},
750ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller};
751ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. MillerMODULE_DEVICE_TABLE(of, n2rng_match);
752ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
753ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic struct of_platform_driver n2rng_driver = {
754ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	.name		= "n2rng",
755ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	.match_table	= n2rng_match,
756ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	.probe		= n2rng_probe,
757ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	.remove		= __devexit_p(n2rng_remove),
758ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller};
759ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
760ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic int __init n2rng_init(void)
761ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
762ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	return of_register_driver(&n2rng_driver, &of_bus_type);
763ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
764ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
765ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millerstatic void __exit n2rng_exit(void)
766ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller{
767ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller	of_unregister_driver(&n2rng_driver);
768ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller}
769ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Miller
770ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millermodule_init(n2rng_init);
771ce087150211412afd901a3fa16b1aab5b54d1bcbDavid S. Millermodule_exit(n2rng_exit);
772