1 // SPDX-License-Identifier: GPL-2.0-only
3 * Random Number Generator driver for the Keystone SOC
5 * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com
7 * Authors: Sandeep Nair
11 #include <linux/hw_random.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/clk.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/err.h>
19 #include <linux/regmap.h>
20 #include <linux/mfd/syscon.h>
22 #include <linux/of_address.h>
23 #include <linux/delay.h>
25 #define SA_CMD_STATUS_OFS 0x8
27 /* TRNG enable control in SA System module*/
28 #define SA_CMD_STATUS_REG_TRNG_ENABLE BIT(3)
30 /* TRNG start control in TRNG module */
31 #define TRNG_CNTL_REG_TRNG_ENABLE BIT(10)
33 /* Data ready indicator in STATUS register */
34 #define TRNG_STATUS_REG_READY BIT(0)
36 /* Data ready clear control in INTACK register */
37 #define TRNG_INTACK_REG_READY BIT(0)
40 * Number of samples taken to gather entropy during startup.
41 * If value is 0, the number of samples is 2^24 else
42 * equals value times 2^8.
44 #define TRNG_DEF_STARTUP_CYCLES 0
45 #define TRNG_CNTL_REG_STARTUP_CYCLES_SHIFT 16
48 * Minimum number of samples taken to regenerate entropy
49 * If value is 0, the number of samples is 2^24 else
50 * equals value times 2^6.
52 #define TRNG_DEF_MIN_REFILL_CYCLES 1
53 #define TRNG_CFG_REG_MIN_REFILL_CYCLES_SHIFT 0
56 * Maximum number of samples taken to regenerate entropy
57 * If value is 0, the number of samples is 2^24 else
58 * equals value times 2^8.
60 #define TRNG_DEF_MAX_REFILL_CYCLES 0
61 #define TRNG_CFG_REG_MAX_REFILL_CYCLES_SHIFT 16
63 /* Number of CLK input cycles between samples */
64 #define TRNG_DEF_CLK_DIV_CYCLES 0
65 #define TRNG_CFG_REG_SAMPLE_DIV_SHIFT 8
67 /* Maximum retries to get rng data */
68 #define SA_MAX_RNG_DATA_RETRIES 5
69 /* Delay between retries (in usecs) */
70 #define SA_RNG_DATA_RETRY_DELAY 5
86 struct regmap *regmap_cfg;
87 struct trng_regs __iomem *reg_rng;
90 static int ks_sa_rng_init(struct hwrng *rng)
93 struct device *dev = (struct device *)rng->priv;
94 struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
96 /* Enable RNG module */
97 regmap_write_bits(ks_sa_rng->regmap_cfg, SA_CMD_STATUS_OFS,
98 SA_CMD_STATUS_REG_TRNG_ENABLE,
99 SA_CMD_STATUS_REG_TRNG_ENABLE);
101 /* Configure RNG module */
102 writel(0, &ks_sa_rng->reg_rng->control);
103 value = TRNG_DEF_STARTUP_CYCLES << TRNG_CNTL_REG_STARTUP_CYCLES_SHIFT;
104 writel(value, &ks_sa_rng->reg_rng->control);
106 value = (TRNG_DEF_MIN_REFILL_CYCLES <<
107 TRNG_CFG_REG_MIN_REFILL_CYCLES_SHIFT) |
108 (TRNG_DEF_MAX_REFILL_CYCLES <<
109 TRNG_CFG_REG_MAX_REFILL_CYCLES_SHIFT) |
110 (TRNG_DEF_CLK_DIV_CYCLES <<
111 TRNG_CFG_REG_SAMPLE_DIV_SHIFT);
113 writel(value, &ks_sa_rng->reg_rng->config);
115 /* Disable all interrupts from TRNG */
116 writel(0, &ks_sa_rng->reg_rng->intmask);
119 value = readl(&ks_sa_rng->reg_rng->control);
120 value |= TRNG_CNTL_REG_TRNG_ENABLE;
121 writel(value, &ks_sa_rng->reg_rng->control);
126 static void ks_sa_rng_cleanup(struct hwrng *rng)
128 struct device *dev = (struct device *)rng->priv;
129 struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
132 writel(0, &ks_sa_rng->reg_rng->control);
133 regmap_write_bits(ks_sa_rng->regmap_cfg, SA_CMD_STATUS_OFS,
134 SA_CMD_STATUS_REG_TRNG_ENABLE, 0);
137 static int ks_sa_rng_data_read(struct hwrng *rng, u32 *data)
139 struct device *dev = (struct device *)rng->priv;
140 struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
142 /* Read random data */
143 data[0] = readl(&ks_sa_rng->reg_rng->output_l);
144 data[1] = readl(&ks_sa_rng->reg_rng->output_h);
146 writel(TRNG_INTACK_REG_READY, &ks_sa_rng->reg_rng->intack);
148 return sizeof(u32) * 2;
151 static int ks_sa_rng_data_present(struct hwrng *rng, int wait)
153 struct device *dev = (struct device *)rng->priv;
154 struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
159 for (j = 0; j < SA_MAX_RNG_DATA_RETRIES; j++) {
160 ready = readl(&ks_sa_rng->reg_rng->status);
161 ready &= TRNG_STATUS_REG_READY;
166 udelay(SA_RNG_DATA_RETRY_DELAY);
172 static int ks_sa_rng_probe(struct platform_device *pdev)
174 struct ks_sa_rng *ks_sa_rng;
175 struct device *dev = &pdev->dev;
178 ks_sa_rng = devm_kzalloc(dev, sizeof(*ks_sa_rng), GFP_KERNEL);
182 ks_sa_rng->dev = dev;
183 ks_sa_rng->rng = (struct hwrng) {
184 .name = "ks_sa_hwrng",
185 .init = ks_sa_rng_init,
186 .data_read = ks_sa_rng_data_read,
187 .data_present = ks_sa_rng_data_present,
188 .cleanup = ks_sa_rng_cleanup,
190 ks_sa_rng->rng.priv = (unsigned long)dev;
192 ks_sa_rng->reg_rng = devm_platform_ioremap_resource(pdev, 0);
193 if (IS_ERR(ks_sa_rng->reg_rng))
194 return PTR_ERR(ks_sa_rng->reg_rng);
196 ks_sa_rng->regmap_cfg =
197 syscon_regmap_lookup_by_phandle(dev->of_node,
200 if (IS_ERR(ks_sa_rng->regmap_cfg)) {
201 dev_err(dev, "syscon_node_to_regmap failed\n");
205 pm_runtime_enable(dev);
206 ret = pm_runtime_get_sync(dev);
208 dev_err(dev, "Failed to enable SA power-domain\n");
209 pm_runtime_disable(dev);
213 platform_set_drvdata(pdev, ks_sa_rng);
215 return devm_hwrng_register(&pdev->dev, &ks_sa_rng->rng);
218 static int ks_sa_rng_remove(struct platform_device *pdev)
220 pm_runtime_put_sync(&pdev->dev);
221 pm_runtime_disable(&pdev->dev);
226 static const struct of_device_id ks_sa_rng_dt_match[] = {
228 .compatible = "ti,keystone-rng",
232 MODULE_DEVICE_TABLE(of, ks_sa_rng_dt_match);
234 static struct platform_driver ks_sa_rng_driver = {
237 .of_match_table = ks_sa_rng_dt_match,
239 .probe = ks_sa_rng_probe,
240 .remove = ks_sa_rng_remove,
243 module_platform_driver(ks_sa_rng_driver);
245 MODULE_DESCRIPTION("Keystone NETCP SA H/W Random Number Generator driver");
246 MODULE_AUTHOR("Vitaly Andrianov <vitalya@ti.com>");
247 MODULE_LICENSE("GPL");