2 * Driver for Mediatek Hardware Random Number Generator
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 #define MTK_RNG_DEV KBUILD_MODNAME
18 #include <linux/clk.h>
19 #include <linux/delay.h>
20 #include <linux/err.h>
21 #include <linux/hw_random.h>
23 #include <linux/iopoll.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
27 #include <linux/platform_device.h>
30 #define TIMEOUT_POLL 20
34 #define RNG_READY BIT(31)
38 #define to_mtk_rng(p) container_of(p, struct mtk_rng, rng)
46 static int mtk_rng_init(struct hwrng *rng)
48 struct mtk_rng *priv = to_mtk_rng(rng);
52 err = clk_prepare_enable(priv->clk);
56 val = readl(priv->base + RNG_CTRL);
58 writel(val, priv->base + RNG_CTRL);
63 static void mtk_rng_cleanup(struct hwrng *rng)
65 struct mtk_rng *priv = to_mtk_rng(rng);
68 val = readl(priv->base + RNG_CTRL);
70 writel(val, priv->base + RNG_CTRL);
72 clk_disable_unprepare(priv->clk);
75 static bool mtk_rng_wait_ready(struct hwrng *rng, bool wait)
77 struct mtk_rng *priv = to_mtk_rng(rng);
80 ready = readl(priv->base + RNG_CTRL) & RNG_READY;
82 readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready,
83 ready & RNG_READY, USEC_POLL,
88 static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
90 struct mtk_rng *priv = to_mtk_rng(rng);
93 while (max >= sizeof(u32)) {
94 if (!mtk_rng_wait_ready(rng, wait))
97 *(u32 *)buf = readl(priv->base + RNG_DATA);
98 retval += sizeof(u32);
103 return retval || !wait ? retval : -EIO;
106 static int mtk_rng_probe(struct platform_device *pdev)
108 struct resource *res;
110 struct mtk_rng *priv;
112 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
114 dev_err(&pdev->dev, "no iomem resource\n");
118 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
122 priv->rng.name = pdev->name;
123 priv->rng.init = mtk_rng_init;
124 priv->rng.cleanup = mtk_rng_cleanup;
125 priv->rng.read = mtk_rng_read;
127 priv->clk = devm_clk_get(&pdev->dev, "rng");
128 if (IS_ERR(priv->clk)) {
129 ret = PTR_ERR(priv->clk);
130 dev_err(&pdev->dev, "no clock for device: %d\n", ret);
134 priv->base = devm_ioremap_resource(&pdev->dev, res);
135 if (IS_ERR(priv->base))
136 return PTR_ERR(priv->base);
138 ret = devm_hwrng_register(&pdev->dev, &priv->rng);
140 dev_err(&pdev->dev, "failed to register rng device: %d\n",
145 dev_info(&pdev->dev, "registered RNG driver\n");
150 static const struct of_device_id mtk_rng_match[] = {
151 { .compatible = "mediatek,mt7623-rng" },
154 MODULE_DEVICE_TABLE(of, mtk_rng_match);
156 static struct platform_driver mtk_rng_driver = {
157 .probe = mtk_rng_probe,
160 .of_match_table = mtk_rng_match,
164 module_platform_driver(mtk_rng_driver);
166 MODULE_DESCRIPTION("Mediatek Random Number Generator Driver");
168 MODULE_LICENSE("GPL");