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