2 * Generic PowerPC 44x RNG driver
4 * Copyright 2011 IBM Corporation
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; version 2 of the License.
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/interrupt.h>
14 #include <linux/platform_device.h>
15 #include <linux/hw_random.h>
16 #include <linux/delay.h>
17 #include <linux/of_address.h>
18 #include <linux/of_platform.h>
21 #include "crypto4xx_core.h"
22 #include "crypto4xx_trng.h"
23 #include "crypto4xx_reg_def.h"
25 #define PPC4XX_TRNG_CTRL 0x0008
26 #define PPC4XX_TRNG_CTRL_DALM 0x20
27 #define PPC4XX_TRNG_STAT 0x0004
28 #define PPC4XX_TRNG_STAT_B 0x1
29 #define PPC4XX_TRNG_DATA 0x0000
31 static int ppc4xx_trng_data_present(struct hwrng
*rng
, int wait
)
33 struct crypto4xx_device
*dev
= (void *)rng
->priv
;
34 int busy
, i
, present
= 0;
36 for (i
= 0; i
< 20; i
++) {
37 busy
= (in_le32(dev
->trng_base
+ PPC4XX_TRNG_STAT
) &
48 static int ppc4xx_trng_data_read(struct hwrng
*rng
, u32
*data
)
50 struct crypto4xx_device
*dev
= (void *)rng
->priv
;
51 *data
= in_le32(dev
->trng_base
+ PPC4XX_TRNG_DATA
);
55 static void ppc4xx_trng_enable(struct crypto4xx_device
*dev
, bool enable
)
59 device_ctrl
= readl(dev
->ce_base
+ CRYPTO4XX_DEVICE_CTRL
);
61 device_ctrl
|= PPC4XX_TRNG_EN
;
63 device_ctrl
&= ~PPC4XX_TRNG_EN
;
64 writel(device_ctrl
, dev
->ce_base
+ CRYPTO4XX_DEVICE_CTRL
);
67 static const struct of_device_id ppc4xx_trng_match
[] = {
68 { .compatible
= "ppc4xx-rng", },
69 { .compatible
= "amcc,ppc460ex-rng", },
70 { .compatible
= "amcc,ppc440epx-rng", },
74 void ppc4xx_trng_probe(struct crypto4xx_core_device
*core_dev
)
76 struct crypto4xx_device
*dev
= core_dev
->dev
;
77 struct device_node
*trng
= NULL
;
78 struct hwrng
*rng
= NULL
;
81 /* Find the TRNG device node and map it */
82 trng
= of_find_matching_node(NULL
, ppc4xx_trng_match
);
83 if (!trng
|| !of_device_is_available(trng
))
86 dev
->trng_base
= of_iomap(trng
, 0);
91 rng
= kzalloc(sizeof(*rng
), GFP_KERNEL
);
95 rng
->name
= MODULE_NAME
;
96 rng
->data_present
= ppc4xx_trng_data_present
;
97 rng
->data_read
= ppc4xx_trng_data_read
;
98 rng
->priv
= (unsigned long) dev
;
100 ppc4xx_trng_enable(dev
, true);
101 out_le32(dev
->trng_base
+ PPC4XX_TRNG_CTRL
, PPC4XX_TRNG_CTRL_DALM
);
102 err
= devm_hwrng_register(core_dev
->device
, core_dev
->trng
);
104 ppc4xx_trng_enable(dev
, false);
105 dev_err(core_dev
->device
, "failed to register hwrng (%d).\n",
113 iounmap(dev
->trng_base
);
115 dev
->trng_base
= NULL
;
116 core_dev
->trng
= NULL
;
119 void ppc4xx_trng_remove(struct crypto4xx_core_device
*core_dev
)
121 if (core_dev
&& core_dev
->trng
) {
122 struct crypto4xx_device
*dev
= core_dev
->dev
;
124 devm_hwrng_unregister(core_dev
->device
, core_dev
->trng
);
125 ppc4xx_trng_enable(dev
, false);
126 iounmap(dev
->trng_base
);
127 kfree(core_dev
->trng
);
131 MODULE_ALIAS("ppc4xx_rng");