1/*
2 * drivers/net/ubi32-eth.c
3 *   Ubicom32 hardware random number generator driver.
4 *
5 * (C) Copyright 2009, Ubicom, Inc.
6 *
7 * This file is part of the Ubicom32 Linux Kernel Port.
8 *
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port.  If not,
21 * see <http://www.gnu.org/licenses/>.
22 *
23 * Ubicom32 implementation derived from (with many thanks):
24 *   arch/m68knommu
25 *   arch/blackfin
26 *   arch/parisc
27 */
28
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/hw_random.h>
32#include <linux/delay.h>
33#include <asm/io.h>
34#include <asm/ip5000.h>
35
36#define MODULE_NAME "ubicom32_rng"
37
38static int ubicom32_rng_data_present(struct hwrng *rng, int wait)
39{
40	int data, i;
41
42	for (i = 0; i < 20; i++) {
43		data = *(int *)(TIMER_BASE + TIMER_TRN);
44		if (data || !wait)
45			break;
46		udelay(10);
47	}
48	return data;
49}
50
51static int ubicom32_rng_data_read(struct hwrng *rng, u32 *data)
52{
53	*data = *(int *)(TIMER_BASE + TIMER_TRN);
54	return 4;
55}
56
57static int ubicom32_rng_init(struct hwrng *rng)
58{
59	printk(KERN_INFO "ubicom32 rng init\n");
60	*(int *)(TIMER_BASE + TIMER_TRN_CFG) = TIMER_TRN_CFG_ENABLE_OSC;
61	return 0;
62}
63
64static void ubicom32_rng_cleanup(struct hwrng *rng)
65{
66	printk(KERN_INFO "ubicom32 rng cleanup\n");
67	*(int *)(TIMER_BASE + TIMER_TRN_CFG) = 0;
68}
69
70static struct hwrng ubicom32_rng = {
71	.name		= MODULE_NAME,
72	.init		= ubicom32_rng_init,
73	.cleanup	= ubicom32_rng_cleanup,
74	.data_present	= ubicom32_rng_data_present,
75	.data_read	= ubicom32_rng_data_read,
76	.priv		= 0,
77};
78
79static int __init mod_init(void)
80{
81	int err;
82
83	printk(KERN_INFO "ubicom32 rng started\n");
84	err = hwrng_register(&ubicom32_rng);
85	if (err) {
86		printk(KERN_ERR "ubicom32 rng register failed (%d)\n",
87			err);
88	}
89
90	return err;
91}
92
93static void __exit mod_exit(void)
94{
95	printk(KERN_INFO "ubicom32 rng stopped\n");
96	hwrng_unregister(&ubicom32_rng);
97}
98
99module_init(mod_init);
100module_exit(mod_exit);
101
102MODULE_LICENSE("GPL");
103MODULE_AUTHOR("Ubicom, Inc.");
104MODULE_DESCRIPTION("H/W rng driver for ubicom32 processor");
105MODULE_VERSION("1:1.0.a");
106