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 */
10c7c9e1c372452688f0ef2af794789bbd00f9fa51Thierry Reding#include <linux/err.h>
11049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/module.h>
12049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/kernel.h>
13049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/init.h>
14049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/delay.h>
15049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/io.h>
16049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/platform_device.h>
17049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#include <linux/hw_random.h>
185a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h>
19049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
20049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_RCSR		0x00000000
21049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_ROR(n)	(0x00000018 + (n) * 8)
22049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
23049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_RCSR_INTE	0x00000008
24049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_RCSR_RST	0x00000004
25049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_RCSR_FIN	0x00000002
26049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#define TX4939_RNG_RCSR_ST	0x00000001
27049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
28049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostruct tx4939_rng {
29049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct hwrng rng;
30049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	void __iomem *base;
31049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	u64 databuf[3];
32049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	unsigned int data_avail;
33049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto};
34049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
35049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic void rng_io_start(void)
36049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
37049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#ifndef CONFIG_64BIT
38049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	/*
39049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * readq is reading a 64-bit register using a 64-bit load.  On
40049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * a 32-bit kernel however interrupts or any other processor
41049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * exception would clobber the upper 32-bit of the processor
42049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * register so interrupts need to be disabled.
43049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 */
44049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	local_irq_disable();
45049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#endif
46049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
47049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
48049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic void rng_io_end(void)
49049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
50049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#ifndef CONFIG_64BIT
51049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	local_irq_enable();
52049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto#endif
53049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
54049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
55049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic u64 read_rng(void __iomem *base, unsigned int offset)
56049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
57049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return ____raw_readq(base + offset);
58049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
59049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
60049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic void write_rng(u64 val, void __iomem *base, unsigned int offset)
61049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
62049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return ____raw_writeq(val, base + offset);
63049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
64049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
65049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic int tx4939_rng_data_present(struct hwrng *rng, int wait)
66049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
67049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct tx4939_rng *rngdev = container_of(rng, struct tx4939_rng, rng);
68049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	int i;
69049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
70049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	if (rngdev->data_avail)
71049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		return rngdev->data_avail;
72049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	for (i = 0; i < 20; i++) {
73049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		rng_io_start();
74049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		if (!(read_rng(rngdev->base, TX4939_RNG_RCSR)
75049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		      & TX4939_RNG_RCSR_ST)) {
76049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			rngdev->databuf[0] =
77049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				read_rng(rngdev->base, TX4939_RNG_ROR(0));
78049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			rngdev->databuf[1] =
79049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				read_rng(rngdev->base, TX4939_RNG_ROR(1));
80049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			rngdev->databuf[2] =
81049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				read_rng(rngdev->base, TX4939_RNG_ROR(2));
82049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			rngdev->data_avail =
83049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				sizeof(rngdev->databuf) / sizeof(u32);
84049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			/* Start RNG */
85049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			write_rng(TX4939_RNG_RCSR_ST,
86049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto				  rngdev->base, TX4939_RNG_RCSR);
87049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			wait = 0;
88049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		}
89049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		rng_io_end();
90049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		if (!wait)
91049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			break;
92049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		/* 90 bus clock cycles by default for generation */
93049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		ndelay(90 * 5);
94049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	}
95049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return rngdev->data_avail;
96049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
97049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
98049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic int tx4939_rng_data_read(struct hwrng *rng, u32 *buffer)
99049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
100049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct tx4939_rng *rngdev = container_of(rng, struct tx4939_rng, rng);
101049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
102049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev->data_avail--;
103049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	*buffer = *((u32 *)&rngdev->databuf + rngdev->data_avail);
104049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return sizeof(u32);
105049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
106049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
107049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic int __init tx4939_rng_probe(struct platform_device *dev)
108049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
109049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct tx4939_rng *rngdev;
110049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct resource *r;
111049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	int i;
112049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
113049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev = devm_kzalloc(&dev->dev, sizeof(*rngdev), GFP_KERNEL);
114049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	if (!rngdev)
115049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		return -ENOMEM;
1169dc48034596f3ef47ec5eb820f4dde4129d83a56Julia Lawall	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
117c7c9e1c372452688f0ef2af794789bbd00f9fa51Thierry Reding	rngdev->base = devm_ioremap_resource(&dev->dev, r);
118c7c9e1c372452688f0ef2af794789bbd00f9fa51Thierry Reding	if (IS_ERR(rngdev->base))
119c7c9e1c372452688f0ef2af794789bbd00f9fa51Thierry Reding		return PTR_ERR(rngdev->base);
120049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
121049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev->rng.name = dev_name(&dev->dev);
122049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev->rng.data_present = tx4939_rng_data_present;
123049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rngdev->rng.data_read = tx4939_rng_data_read;
124049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
125049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rng_io_start();
126049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	/* Reset RNG */
127049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	write_rng(TX4939_RNG_RCSR_RST, rngdev->base, TX4939_RNG_RCSR);
128049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	write_rng(0, rngdev->base, TX4939_RNG_RCSR);
129049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	/* Start RNG */
130049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	write_rng(TX4939_RNG_RCSR_ST, rngdev->base, TX4939_RNG_RCSR);
131049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	rng_io_end();
132049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	/*
133049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * Drop first two results.  From the datasheet:
134049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * The quality of the random numbers generated immediately
135049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * after reset can be insufficient.  Therefore, do not use
136049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * random numbers obtained from the first and second
137049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * generations; use the ones from the third or subsequent
138049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 * generation.
139049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	 */
140049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	for (i = 0; i < 2; i++) {
141049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		rngdev->data_avail = 0;
142049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		if (!tx4939_rng_data_present(&rngdev->rng, 1))
143049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto			return -EIO;
144049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	}
145049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
146049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	platform_set_drvdata(dev, rngdev);
147049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return hwrng_register(&rngdev->rng);
148049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
149049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
150049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic int __exit tx4939_rng_remove(struct platform_device *dev)
151049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto{
152049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	struct tx4939_rng *rngdev = platform_get_drvdata(dev);
153049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
154049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	hwrng_unregister(&rngdev->rng);
155049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	return 0;
156049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto}
157049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
158049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemotostatic struct platform_driver tx4939_rng_driver = {
159049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	.driver		= {
160049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		.name	= "tx4939-rng",
161049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto		.owner	= THIS_MODULE,
162049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	},
163049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto	.remove = tx4939_rng_remove,
164049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto};
165049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
166e7c2199ff300fcf88673a1cf6d7229e6c3da09deFabio Porceddamodule_platform_driver_probe(tx4939_rng_driver, tx4939_rng_probe);
167049a947c611a19523eaaf193f698b897a62d0593Atsushi Nemoto
168049a947c611a19523eaaf193f698b897a62d0593Atsushi NemotoMODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for TX4939");
169049a947c611a19523eaaf193f698b897a62d0593Atsushi NemotoMODULE_LICENSE("GPL");
170