16cd225ccSŁukasz Stelmach // SPDX-License-Identifier: GPL-2.0
26cd225ccSŁukasz Stelmach /*
36cd225ccSŁukasz Stelmach * RNG driver for Exynos TRNGs
46cd225ccSŁukasz Stelmach *
56cd225ccSŁukasz Stelmach * Author: Łukasz Stelmach <l.stelmach@samsung.com>
66cd225ccSŁukasz Stelmach *
76cd225ccSŁukasz Stelmach * Copyright 2017 (c) Samsung Electronics Software, Inc.
86cd225ccSŁukasz Stelmach *
96cd225ccSŁukasz Stelmach * Based on the Exynos PRNG driver drivers/crypto/exynos-rng by
106cd225ccSŁukasz Stelmach * Krzysztof Kozłowski <krzk@kernel.org>
116cd225ccSŁukasz Stelmach */
126cd225ccSŁukasz Stelmach
1310bb6ac8SSam Protsenko #include <linux/arm-smccc.h>
146cd225ccSŁukasz Stelmach #include <linux/clk.h>
156cd225ccSŁukasz Stelmach #include <linux/crypto.h>
166cd225ccSŁukasz Stelmach #include <linux/delay.h>
176cd225ccSŁukasz Stelmach #include <linux/err.h>
186cd225ccSŁukasz Stelmach #include <linux/hw_random.h>
196cd225ccSŁukasz Stelmach #include <linux/io.h>
206cd225ccSŁukasz Stelmach #include <linux/iopoll.h>
216cd225ccSŁukasz Stelmach #include <linux/kernel.h>
226cd225ccSŁukasz Stelmach #include <linux/module.h>
23ac316725SRandy Dunlap #include <linux/mod_devicetable.h>
246cd225ccSŁukasz Stelmach #include <linux/platform_device.h>
256cd225ccSŁukasz Stelmach #include <linux/pm_runtime.h>
2610bb6ac8SSam Protsenko #include <linux/property.h>
276cd225ccSŁukasz Stelmach
2876536caaSSam Protsenko #define EXYNOS_TRNG_CLKDIV 0x0
296cd225ccSŁukasz Stelmach
3076536caaSSam Protsenko #define EXYNOS_TRNG_CTRL 0x20
316cd225ccSŁukasz Stelmach #define EXYNOS_TRNG_CTRL_RNGEN BIT(31)
326cd225ccSŁukasz Stelmach
3376536caaSSam Protsenko #define EXYNOS_TRNG_POST_CTRL 0x30
3476536caaSSam Protsenko #define EXYNOS_TRNG_ONLINE_CTRL 0x40
3576536caaSSam Protsenko #define EXYNOS_TRNG_ONLINE_STAT 0x44
3676536caaSSam Protsenko #define EXYNOS_TRNG_ONLINE_MAXCHI2 0x48
3776536caaSSam Protsenko #define EXYNOS_TRNG_FIFO_CTRL 0x50
3876536caaSSam Protsenko #define EXYNOS_TRNG_FIFO_0 0x80
3976536caaSSam Protsenko #define EXYNOS_TRNG_FIFO_1 0x84
4076536caaSSam Protsenko #define EXYNOS_TRNG_FIFO_2 0x88
4176536caaSSam Protsenko #define EXYNOS_TRNG_FIFO_3 0x8c
4276536caaSSam Protsenko #define EXYNOS_TRNG_FIFO_4 0x90
4376536caaSSam Protsenko #define EXYNOS_TRNG_FIFO_5 0x94
4476536caaSSam Protsenko #define EXYNOS_TRNG_FIFO_6 0x98
4576536caaSSam Protsenko #define EXYNOS_TRNG_FIFO_7 0x9c
4676536caaSSam Protsenko #define EXYNOS_TRNG_FIFO_LEN 8
4776536caaSSam Protsenko #define EXYNOS_TRNG_CLOCK_RATE 500000
486cd225ccSŁukasz Stelmach
4910bb6ac8SSam Protsenko /* Driver feature flags */
5010bb6ac8SSam Protsenko #define EXYNOS_SMC BIT(0)
5110bb6ac8SSam Protsenko
5210bb6ac8SSam Protsenko #define EXYNOS_SMC_CALL_VAL(func_num) \
5310bb6ac8SSam Protsenko ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
5410bb6ac8SSam Protsenko ARM_SMCCC_SMC_32, \
5510bb6ac8SSam Protsenko ARM_SMCCC_OWNER_SIP, \
5610bb6ac8SSam Protsenko func_num)
5710bb6ac8SSam Protsenko
5810bb6ac8SSam Protsenko /* SMC command for DTRNG access */
5910bb6ac8SSam Protsenko #define SMC_CMD_RANDOM EXYNOS_SMC_CALL_VAL(0x1012)
6010bb6ac8SSam Protsenko
6110bb6ac8SSam Protsenko /* SMC_CMD_RANDOM: arguments */
6210bb6ac8SSam Protsenko #define HWRNG_INIT 0x0
6310bb6ac8SSam Protsenko #define HWRNG_EXIT 0x1
6410bb6ac8SSam Protsenko #define HWRNG_GET_DATA 0x2
6510bb6ac8SSam Protsenko #define HWRNG_RESUME 0x3
6610bb6ac8SSam Protsenko
6710bb6ac8SSam Protsenko /* SMC_CMD_RANDOM: return values */
6810bb6ac8SSam Protsenko #define HWRNG_RET_OK 0x0
6910bb6ac8SSam Protsenko #define HWRNG_RET_RETRY_ERROR 0x2
7010bb6ac8SSam Protsenko
7110bb6ac8SSam Protsenko #define HWRNG_MAX_TRIES 100
7210bb6ac8SSam Protsenko
736cd225ccSŁukasz Stelmach struct exynos_trng_dev {
746cd225ccSŁukasz Stelmach struct device *dev;
756cd225ccSŁukasz Stelmach void __iomem *mem;
76e003d670SSam Protsenko struct clk *clk; /* operating clock */
77e003d670SSam Protsenko struct clk *pclk; /* bus clock */
786cd225ccSŁukasz Stelmach struct hwrng rng;
7910bb6ac8SSam Protsenko unsigned long flags;
806cd225ccSŁukasz Stelmach };
816cd225ccSŁukasz Stelmach
exynos_trng_do_read_reg(struct hwrng * rng,void * data,size_t max,bool wait)8210bb6ac8SSam Protsenko static int exynos_trng_do_read_reg(struct hwrng *rng, void *data, size_t max,
836cd225ccSŁukasz Stelmach bool wait)
846cd225ccSŁukasz Stelmach {
8576536caaSSam Protsenko struct exynos_trng_dev *trng = (struct exynos_trng_dev *)rng->priv;
86a8bc71d4SDan Carpenter int val;
876cd225ccSŁukasz Stelmach
886cd225ccSŁukasz Stelmach max = min_t(size_t, max, (EXYNOS_TRNG_FIFO_LEN * 4));
896cd225ccSŁukasz Stelmach writel_relaxed(max * 8, trng->mem + EXYNOS_TRNG_FIFO_CTRL);
906cd225ccSŁukasz Stelmach val = readl_poll_timeout(trng->mem + EXYNOS_TRNG_FIFO_CTRL, val,
916cd225ccSŁukasz Stelmach val == 0, 200, 1000000);
926cd225ccSŁukasz Stelmach if (val < 0)
936cd225ccSŁukasz Stelmach return val;
946cd225ccSŁukasz Stelmach
956cd225ccSŁukasz Stelmach memcpy_fromio(data, trng->mem + EXYNOS_TRNG_FIFO_0, max);
966cd225ccSŁukasz Stelmach
976cd225ccSŁukasz Stelmach return max;
986cd225ccSŁukasz Stelmach }
996cd225ccSŁukasz Stelmach
exynos_trng_do_read_smc(struct hwrng * rng,void * data,size_t max,bool wait)10010bb6ac8SSam Protsenko static int exynos_trng_do_read_smc(struct hwrng *rng, void *data, size_t max,
10110bb6ac8SSam Protsenko bool wait)
10210bb6ac8SSam Protsenko {
10310bb6ac8SSam Protsenko struct arm_smccc_res res;
10410bb6ac8SSam Protsenko unsigned int copied = 0;
10510bb6ac8SSam Protsenko u32 *buf = data;
10610bb6ac8SSam Protsenko int tries = 0;
10710bb6ac8SSam Protsenko
10810bb6ac8SSam Protsenko while (copied < max) {
10910bb6ac8SSam Protsenko arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_GET_DATA, 0, 0, 0, 0, 0, 0,
11010bb6ac8SSam Protsenko &res);
11110bb6ac8SSam Protsenko switch (res.a0) {
11210bb6ac8SSam Protsenko case HWRNG_RET_OK:
11310bb6ac8SSam Protsenko *buf++ = res.a2;
11410bb6ac8SSam Protsenko *buf++ = res.a3;
11510bb6ac8SSam Protsenko copied += 8;
11610bb6ac8SSam Protsenko tries = 0;
11710bb6ac8SSam Protsenko break;
11810bb6ac8SSam Protsenko case HWRNG_RET_RETRY_ERROR:
11910bb6ac8SSam Protsenko if (!wait)
12010bb6ac8SSam Protsenko return copied;
12110bb6ac8SSam Protsenko if (++tries >= HWRNG_MAX_TRIES)
12210bb6ac8SSam Protsenko return copied;
12310bb6ac8SSam Protsenko cond_resched();
12410bb6ac8SSam Protsenko break;
12510bb6ac8SSam Protsenko default:
12610bb6ac8SSam Protsenko return -EIO;
12710bb6ac8SSam Protsenko }
12810bb6ac8SSam Protsenko }
12910bb6ac8SSam Protsenko
13010bb6ac8SSam Protsenko return copied;
13110bb6ac8SSam Protsenko }
13210bb6ac8SSam Protsenko
exynos_trng_init_reg(struct hwrng * rng)13310bb6ac8SSam Protsenko static int exynos_trng_init_reg(struct hwrng *rng)
1346cd225ccSŁukasz Stelmach {
1356cd225ccSŁukasz Stelmach struct exynos_trng_dev *trng = (struct exynos_trng_dev *)rng->priv;
1366cd225ccSŁukasz Stelmach unsigned long sss_rate;
1376cd225ccSŁukasz Stelmach u32 val;
1386cd225ccSŁukasz Stelmach
1396cd225ccSŁukasz Stelmach sss_rate = clk_get_rate(trng->clk);
1406cd225ccSŁukasz Stelmach
1416cd225ccSŁukasz Stelmach /*
1426cd225ccSŁukasz Stelmach * For most TRNG circuits the clock frequency of under 500 kHz
1436cd225ccSŁukasz Stelmach * is safe.
1446cd225ccSŁukasz Stelmach */
1456cd225ccSŁukasz Stelmach val = sss_rate / (EXYNOS_TRNG_CLOCK_RATE * 2);
1466cd225ccSŁukasz Stelmach if (val > 0x7fff) {
14776536caaSSam Protsenko dev_err(trng->dev, "clock divider too large: %d\n", val);
1486cd225ccSŁukasz Stelmach return -ERANGE;
1496cd225ccSŁukasz Stelmach }
1506cd225ccSŁukasz Stelmach val = val << 1;
1516cd225ccSŁukasz Stelmach writel_relaxed(val, trng->mem + EXYNOS_TRNG_CLKDIV);
1526cd225ccSŁukasz Stelmach
1536cd225ccSŁukasz Stelmach /* Enable the generator. */
1546cd225ccSŁukasz Stelmach val = EXYNOS_TRNG_CTRL_RNGEN;
1556cd225ccSŁukasz Stelmach writel_relaxed(val, trng->mem + EXYNOS_TRNG_CTRL);
1566cd225ccSŁukasz Stelmach
1576cd225ccSŁukasz Stelmach /*
1586cd225ccSŁukasz Stelmach * Disable post-processing. /dev/hwrng is supposed to deliver
1596cd225ccSŁukasz Stelmach * unprocessed data.
1606cd225ccSŁukasz Stelmach */
1616cd225ccSŁukasz Stelmach writel_relaxed(0, trng->mem + EXYNOS_TRNG_POST_CTRL);
1626cd225ccSŁukasz Stelmach
1636cd225ccSŁukasz Stelmach return 0;
1646cd225ccSŁukasz Stelmach }
1656cd225ccSŁukasz Stelmach
exynos_trng_init_smc(struct hwrng * rng)16610bb6ac8SSam Protsenko static int exynos_trng_init_smc(struct hwrng *rng)
16710bb6ac8SSam Protsenko {
16810bb6ac8SSam Protsenko struct exynos_trng_dev *trng = (struct exynos_trng_dev *)rng->priv;
16910bb6ac8SSam Protsenko struct arm_smccc_res res;
17010bb6ac8SSam Protsenko int ret = 0;
17110bb6ac8SSam Protsenko
17210bb6ac8SSam Protsenko arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_INIT, 0, 0, 0, 0, 0, 0, &res);
17310bb6ac8SSam Protsenko if (res.a0 != HWRNG_RET_OK) {
17410bb6ac8SSam Protsenko dev_err(trng->dev, "SMC command for TRNG init failed (%d)\n",
17510bb6ac8SSam Protsenko (int)res.a0);
17610bb6ac8SSam Protsenko ret = -EIO;
17710bb6ac8SSam Protsenko }
17810bb6ac8SSam Protsenko if ((int)res.a0 == -1)
17910bb6ac8SSam Protsenko dev_info(trng->dev, "Make sure LDFW is loaded by your BL\n");
18010bb6ac8SSam Protsenko
18110bb6ac8SSam Protsenko return ret;
18210bb6ac8SSam Protsenko }
18310bb6ac8SSam Protsenko
exynos_trng_probe(struct platform_device * pdev)1846cd225ccSŁukasz Stelmach static int exynos_trng_probe(struct platform_device *pdev)
1856cd225ccSŁukasz Stelmach {
1866cd225ccSŁukasz Stelmach struct exynos_trng_dev *trng;
1876cd225ccSŁukasz Stelmach int ret = -ENOMEM;
1886cd225ccSŁukasz Stelmach
1896cd225ccSŁukasz Stelmach trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
1906cd225ccSŁukasz Stelmach if (!trng)
1916cd225ccSŁukasz Stelmach return ret;
1926cd225ccSŁukasz Stelmach
19310bb6ac8SSam Protsenko platform_set_drvdata(pdev, trng);
19410bb6ac8SSam Protsenko trng->dev = &pdev->dev;
19510bb6ac8SSam Protsenko
19610bb6ac8SSam Protsenko trng->flags = (unsigned long)device_get_match_data(&pdev->dev);
19710bb6ac8SSam Protsenko
1986cd225ccSŁukasz Stelmach trng->rng.name = devm_kstrdup(&pdev->dev, dev_name(&pdev->dev),
1996cd225ccSŁukasz Stelmach GFP_KERNEL);
2006cd225ccSŁukasz Stelmach if (!trng->rng.name)
2016cd225ccSŁukasz Stelmach return ret;
2026cd225ccSŁukasz Stelmach
2036cd225ccSŁukasz Stelmach trng->rng.priv = (unsigned long)trng;
2046cd225ccSŁukasz Stelmach
20510bb6ac8SSam Protsenko if (trng->flags & EXYNOS_SMC) {
20610bb6ac8SSam Protsenko trng->rng.init = exynos_trng_init_smc;
20710bb6ac8SSam Protsenko trng->rng.read = exynos_trng_do_read_smc;
20810bb6ac8SSam Protsenko } else {
20910bb6ac8SSam Protsenko trng->rng.init = exynos_trng_init_reg;
21010bb6ac8SSam Protsenko trng->rng.read = exynos_trng_do_read_reg;
2116cd225ccSŁukasz Stelmach
2123e3c97c6SYueHaibing trng->mem = devm_platform_ioremap_resource(pdev, 0);
2132273f42dSweiyongjun \(A\) if (IS_ERR(trng->mem))
2146cd225ccSŁukasz Stelmach return PTR_ERR(trng->mem);
21510bb6ac8SSam Protsenko }
2166cd225ccSŁukasz Stelmach
2176cd225ccSŁukasz Stelmach pm_runtime_enable(&pdev->dev);
2180cdbabf8SŁukasz Stelmach ret = pm_runtime_resume_and_get(&pdev->dev);
2196cd225ccSŁukasz Stelmach if (ret < 0) {
2206cd225ccSŁukasz Stelmach dev_err(&pdev->dev, "Could not get runtime PM.\n");
2216cd225ccSŁukasz Stelmach goto err_pm_get;
2226cd225ccSŁukasz Stelmach }
2236cd225ccSŁukasz Stelmach
22481da8056SSam Protsenko trng->clk = devm_clk_get_enabled(&pdev->dev, "secss");
2256cd225ccSŁukasz Stelmach if (IS_ERR(trng->clk)) {
22681da8056SSam Protsenko ret = dev_err_probe(&pdev->dev, PTR_ERR(trng->clk),
22781da8056SSam Protsenko "Could not get clock\n");
2286cd225ccSŁukasz Stelmach goto err_clock;
2296cd225ccSŁukasz Stelmach }
2306cd225ccSŁukasz Stelmach
231e003d670SSam Protsenko trng->pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk");
232e003d670SSam Protsenko if (IS_ERR(trng->pclk)) {
233e003d670SSam Protsenko ret = dev_err_probe(&pdev->dev, PTR_ERR(trng->pclk),
234e003d670SSam Protsenko "Could not get pclk\n");
235e003d670SSam Protsenko goto err_clock;
236e003d670SSam Protsenko }
237e003d670SSam Protsenko
2383e75241bSChuhong Yuan ret = devm_hwrng_register(&pdev->dev, &trng->rng);
2396cd225ccSŁukasz Stelmach if (ret) {
2406cd225ccSŁukasz Stelmach dev_err(&pdev->dev, "Could not register hwrng device.\n");
24181da8056SSam Protsenko goto err_clock;
2426cd225ccSŁukasz Stelmach }
2436cd225ccSŁukasz Stelmach
2446cd225ccSŁukasz Stelmach dev_info(&pdev->dev, "Exynos True Random Number Generator.\n");
2456cd225ccSŁukasz Stelmach
2466cd225ccSŁukasz Stelmach return 0;
2476cd225ccSŁukasz Stelmach
2486cd225ccSŁukasz Stelmach err_clock:
2490cdbabf8SŁukasz Stelmach pm_runtime_put_noidle(&pdev->dev);
2506cd225ccSŁukasz Stelmach
2516cd225ccSŁukasz Stelmach err_pm_get:
2526cd225ccSŁukasz Stelmach pm_runtime_disable(&pdev->dev);
2536cd225ccSŁukasz Stelmach
2546cd225ccSŁukasz Stelmach return ret;
2556cd225ccSŁukasz Stelmach }
2566cd225ccSŁukasz Stelmach
exynos_trng_remove(struct platform_device * pdev)2579daec3cbSUwe Kleine-König static void exynos_trng_remove(struct platform_device *pdev)
2586cd225ccSŁukasz Stelmach {
25910bb6ac8SSam Protsenko struct exynos_trng_dev *trng = platform_get_drvdata(pdev);
26010bb6ac8SSam Protsenko
26110bb6ac8SSam Protsenko if (trng->flags & EXYNOS_SMC) {
26210bb6ac8SSam Protsenko struct arm_smccc_res res;
26310bb6ac8SSam Protsenko
26410bb6ac8SSam Protsenko arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_EXIT, 0, 0, 0, 0, 0, 0,
26510bb6ac8SSam Protsenko &res);
26610bb6ac8SSam Protsenko }
26710bb6ac8SSam Protsenko
2686cd225ccSŁukasz Stelmach pm_runtime_put_sync(&pdev->dev);
2696cd225ccSŁukasz Stelmach pm_runtime_disable(&pdev->dev);
2706cd225ccSŁukasz Stelmach }
2716cd225ccSŁukasz Stelmach
exynos_trng_suspend(struct device * dev)272b4198a9aSMartin Kaiser static int exynos_trng_suspend(struct device *dev)
2736cd225ccSŁukasz Stelmach {
27410bb6ac8SSam Protsenko struct exynos_trng_dev *trng = dev_get_drvdata(dev);
27510bb6ac8SSam Protsenko struct arm_smccc_res res;
27610bb6ac8SSam Protsenko
27710bb6ac8SSam Protsenko if (trng->flags & EXYNOS_SMC) {
27810bb6ac8SSam Protsenko arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_EXIT, 0, 0, 0, 0, 0, 0,
27910bb6ac8SSam Protsenko &res);
28010bb6ac8SSam Protsenko if (res.a0 != HWRNG_RET_OK)
28110bb6ac8SSam Protsenko return -EIO;
28210bb6ac8SSam Protsenko }
28310bb6ac8SSam Protsenko
2846cd225ccSŁukasz Stelmach pm_runtime_put_sync(dev);
2856cd225ccSŁukasz Stelmach
2866cd225ccSŁukasz Stelmach return 0;
2876cd225ccSŁukasz Stelmach }
2886cd225ccSŁukasz Stelmach
exynos_trng_resume(struct device * dev)289b4198a9aSMartin Kaiser static int exynos_trng_resume(struct device *dev)
2906cd225ccSŁukasz Stelmach {
29110bb6ac8SSam Protsenko struct exynos_trng_dev *trng = dev_get_drvdata(dev);
2926cd225ccSŁukasz Stelmach int ret;
2936cd225ccSŁukasz Stelmach
2945d0421d6STian Tao ret = pm_runtime_resume_and_get(dev);
2956cd225ccSŁukasz Stelmach if (ret < 0) {
2966cd225ccSŁukasz Stelmach dev_err(dev, "Could not get runtime PM.\n");
2976cd225ccSŁukasz Stelmach return ret;
2986cd225ccSŁukasz Stelmach }
2996cd225ccSŁukasz Stelmach
30010bb6ac8SSam Protsenko if (trng->flags & EXYNOS_SMC) {
30110bb6ac8SSam Protsenko struct arm_smccc_res res;
30210bb6ac8SSam Protsenko
30310bb6ac8SSam Protsenko arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_RESUME, 0, 0, 0, 0, 0, 0,
30410bb6ac8SSam Protsenko &res);
30510bb6ac8SSam Protsenko if (res.a0 != HWRNG_RET_OK)
30610bb6ac8SSam Protsenko return -EIO;
30710bb6ac8SSam Protsenko
30810bb6ac8SSam Protsenko arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_INIT, 0, 0, 0, 0, 0, 0,
30910bb6ac8SSam Protsenko &res);
31010bb6ac8SSam Protsenko if (res.a0 != HWRNG_RET_OK)
31110bb6ac8SSam Protsenko return -EIO;
31210bb6ac8SSam Protsenko }
31310bb6ac8SSam Protsenko
3146cd225ccSŁukasz Stelmach return 0;
3156cd225ccSŁukasz Stelmach }
3166cd225ccSŁukasz Stelmach
317b4198a9aSMartin Kaiser static DEFINE_SIMPLE_DEV_PM_OPS(exynos_trng_pm_ops, exynos_trng_suspend,
3186cd225ccSŁukasz Stelmach exynos_trng_resume);
3196cd225ccSŁukasz Stelmach
3206cd225ccSŁukasz Stelmach static const struct of_device_id exynos_trng_dt_match[] = {
3216cd225ccSŁukasz Stelmach {
3226cd225ccSŁukasz Stelmach .compatible = "samsung,exynos5250-trng",
323*b0c2036dSSam Protsenko }, {
324*b0c2036dSSam Protsenko .compatible = "samsung,exynos850-trng",
325*b0c2036dSSam Protsenko .data = (void *)EXYNOS_SMC,
3266cd225ccSŁukasz Stelmach },
3276cd225ccSŁukasz Stelmach { },
3286cd225ccSŁukasz Stelmach };
3296cd225ccSŁukasz Stelmach MODULE_DEVICE_TABLE(of, exynos_trng_dt_match);
3306cd225ccSŁukasz Stelmach
3316cd225ccSŁukasz Stelmach static struct platform_driver exynos_trng_driver = {
3326cd225ccSŁukasz Stelmach .driver = {
3336cd225ccSŁukasz Stelmach .name = "exynos-trng",
334b4198a9aSMartin Kaiser .pm = pm_sleep_ptr(&exynos_trng_pm_ops),
3356cd225ccSŁukasz Stelmach .of_match_table = exynos_trng_dt_match,
3366cd225ccSŁukasz Stelmach },
3376cd225ccSŁukasz Stelmach .probe = exynos_trng_probe,
3389daec3cbSUwe Kleine-König .remove_new = exynos_trng_remove,
3396cd225ccSŁukasz Stelmach };
3406cd225ccSŁukasz Stelmach
3416cd225ccSŁukasz Stelmach module_platform_driver(exynos_trng_driver);
34276536caaSSam Protsenko
3436cd225ccSŁukasz Stelmach MODULE_AUTHOR("Łukasz Stelmach");
3446cd225ccSŁukasz Stelmach MODULE_DESCRIPTION("H/W TRNG driver for Exynos chips");
3456cd225ccSŁukasz Stelmach MODULE_LICENSE("GPL v2");
346