e429589897664e95e40040f67d864021cae2158b
[10.03/openwrt.git] / target / linux / ubicom32 / files / drivers / char / hw_random / ubicom32-rng.c
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
38 static 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
51 static int ubicom32_rng_data_read(struct hwrng *rng, u32 *data)
52 {
53         *data = *(int *)(TIMER_BASE + TIMER_TRN);
54         return 4;
55 }
56
57 static 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
64 static 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
70 static 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
79 static 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
93 static void __exit mod_exit(void)
94 {
95         printk(KERN_INFO "ubicom32 rng stopped\n");
96         hwrng_unregister(&ubicom32_rng);
97 }
98
99 module_init(mod_init);
100 module_exit(mod_exit);
101
102 MODULE_LICENSE("GPL");
103 MODULE_AUTHOR("Ubicom, Inc.");
104 MODULE_DESCRIPTION("H/W rng driver for ubicom32 processor");
105 MODULE_VERSION("1:1.0.a");