tx4939-rng.c revision 5a0e3ad6af8660be21ca98a971cd00f331318c05
1049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto/*
2049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto * RNG driver for TX4939 Random Number Generators (RNG)
3049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto *
4049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto * Copyright (C) 2009 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
5049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto *
6049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto * This file is subject to the terms and conditions of the GNU General Public
7049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto * License.  See the file "COPYING" in the main directory of this archive
8049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto * for more details.
9049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto */
10049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/module.h>
11049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/kernel.h>
12049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/init.h>
13049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/delay.h>
14049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/io.h>
15049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/platform_device.h>
16049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/hw_random.h>
175a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h>
18049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
19049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_RCSR		0x00000000
20049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_ROR(n)	(0x00000018 + (n) * 8)
21049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
22049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_RCSR_INTE	0x00000008
23049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_RCSR_RST	0x00000004
24049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_RCSR_FIN	0x00000002
25049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_RCSR_ST	0x00000001
26049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
27049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostruct tx4939_rng {
28049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct hwrng rng;
29049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	void __iomem *base;
30049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	u64 databuf[3];
31049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	unsigned int data_avail;
32049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto};
33049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
34049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic void rng_io_start(void)
35049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
36049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#ifndef CONFIG_64BIT
37049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	/*
38049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * readq is reading a 64-bit register using a 64-bit load.  On
39049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * a 32-bit kernel however interrupts or any other processor
40049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * exception would clobber the upper 32-bit of the processor
41049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * register so interrupts need to be disabled.
42049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 */
43049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	local_irq_disable();
44049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#endif
45049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
46049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
47049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic void rng_io_end(void)
48049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
49049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#ifndef CONFIG_64BIT
50049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	local_irq_enable();
51049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#endif
52049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
53049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
54049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic u64 read_rng(void __iomem *base, unsigned int offset)
55049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
56049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return ____raw_readq(base + offset);
57049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
58049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
59049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic void write_rng(u64 val, void __iomem *base, unsigned int offset)
60049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
61049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return ____raw_writeq(val, base + offset);
62049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
63049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
64049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic int tx4939_rng_data_present(struct hwrng *rng, int wait)
65049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
66049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct tx4939_rng *rngdev = container_of(rng, struct tx4939_rng, rng);
67049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	int i;
68049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
69049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	if (rngdev->data_avail)
70049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		return rngdev->data_avail;
71049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	for (i = 0; i < 20; i++) {
72049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		rng_io_start();
73049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		if (!(read_rng(rngdev->base, TX4939_RNG_RCSR)
74049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		      & TX4939_RNG_RCSR_ST)) {
75049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			rngdev->databuf[0] =
76049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				read_rng(rngdev->base, TX4939_RNG_ROR(0));
77049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			rngdev->databuf[1] =
78049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				read_rng(rngdev->base, TX4939_RNG_ROR(1));
79049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			rngdev->databuf[2] =
80049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				read_rng(rngdev->base, TX4939_RNG_ROR(2));
81049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			rngdev->data_avail =
82049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				sizeof(rngdev->databuf) / sizeof(u32);
83049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			/* Start RNG */
84049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			write_rng(TX4939_RNG_RCSR_ST,
85049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				  rngdev->base, TX4939_RNG_RCSR);
86049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			wait = 0;
87049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		}
88049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		rng_io_end();
89049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		if (!wait)
90049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			break;
91049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		/* 90 bus clock cycles by default for generation */
92049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		ndelay(90 * 5);
93049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	}
94049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return rngdev->data_avail;
95049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
96049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
97049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic int tx4939_rng_data_read(struct hwrng *rng, u32 *buffer)
98049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
99049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct tx4939_rng *rngdev = container_of(rng, struct tx4939_rng, rng);
100049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
101049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev->data_avail--;
102049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	*buffer = *((u32 *)&rngdev->databuf + rngdev->data_avail);
103049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return sizeof(u32);
104049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
105049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
106049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic int __init tx4939_rng_probe(struct platform_device *dev)
107049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
108049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct tx4939_rng *rngdev;
109049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct resource *r;
110049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	int i;
111049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
112049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
113049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	if (!r)
114049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		return -EBUSY;
115049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev = devm_kzalloc(&dev->dev, sizeof(*rngdev), GFP_KERNEL);
116049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	if (!rngdev)
117049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		return -ENOMEM;
118049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	if (!devm_request_mem_region(&dev->dev, r->start, resource_size(r),
119049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				     dev_name(&dev->dev)))
120049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		return -EBUSY;
121049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev->base = devm_ioremap(&dev->dev, r->start, resource_size(r));
122049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	if (!rngdev->base)
123049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		return -EBUSY;
124049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
125049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev->rng.name = dev_name(&dev->dev);
126049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev->rng.data_present = tx4939_rng_data_present;
127049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev->rng.data_read = tx4939_rng_data_read;
128049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
129049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rng_io_start();
130049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	/* Reset RNG */
131049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	write_rng(TX4939_RNG_RCSR_RST, rngdev->base, TX4939_RNG_RCSR);
132049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	write_rng(0, rngdev->base, TX4939_RNG_RCSR);
133049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	/* Start RNG */
134049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	write_rng(TX4939_RNG_RCSR_ST, rngdev->base, TX4939_RNG_RCSR);
135049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rng_io_end();
136049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	/*
137049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * Drop first two results.  From the datasheet:
138049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * The quality of the random numbers generated immediately
139049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * after reset can be insufficient.  Therefore, do not use
140049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * random numbers obtained from the first and second
141049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * generations; use the ones from the third or subsequent
142049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * generation.
143049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 */
144049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	for (i = 0; i < 2; i++) {
145049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		rngdev->data_avail = 0;
146049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		if (!tx4939_rng_data_present(&rngdev->rng, 1))
147049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			return -EIO;
148049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	}
149049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
150049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	platform_set_drvdata(dev, rngdev);
151049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return hwrng_register(&rngdev->rng);
152049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
153049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
154049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic int __exit tx4939_rng_remove(struct platform_device *dev)
155049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
156049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct tx4939_rng *rngdev = platform_get_drvdata(dev);
157049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
158049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	hwrng_unregister(&rngdev->rng);
159049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	platform_set_drvdata(dev, NULL);
160049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return 0;
161049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
162049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
163049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic struct platform_driver tx4939_rng_driver = {
164049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	.driver		= {
165049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		.name	= "tx4939-rng",
166049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		.owner	= THIS_MODULE,
167049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	},
168049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	.remove = tx4939_rng_remove,
169049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto};
170049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
171049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic int __init tx4939rng_init(void)
172049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
173049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return platform_driver_probe(&tx4939_rng_driver, tx4939_rng_probe);
174049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
175049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
176049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic void __exit tx4939rng_exit(void)
177049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
178049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	platform_driver_unregister(&tx4939_rng_driver);
179049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
180049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
181049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotomodule_init(tx4939rng_init);
182049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotomodule_exit(tx4939rng_exit);
183049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
184049a947c611a19523eaaf193f698b897a62d0593Atsushi NemotoMODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for TX4939");
185049a947c611a19523eaaf193f698b897a62d0593Atsushi NemotoMODULE_LICENSE("GPL");
186