1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Random Number Generator driver for the Keystone SOC |
4 | * |
5 | * Copyright (C) 2016 Texas Instruments Incorporated - https://www.ti.com |
6 | * |
7 | * Authors: Sandeep Nair |
8 | * Vitaly Andrianov |
9 | */ |
10 | |
11 | #include <linux/hw_random.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> |
14 | #include <linux/io.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> |
21 | #include <linux/of.h> |
22 | #include <linux/of_address.h> |
23 | #include <linux/delay.h> |
24 | #include <linux/timekeeping.h> |
25 | |
26 | #define SA_CMD_STATUS_OFS 0x8 |
27 | |
28 | /* TRNG enable control in SA System module*/ |
29 | #define SA_CMD_STATUS_REG_TRNG_ENABLE BIT(3) |
30 | |
31 | /* TRNG start control in TRNG module */ |
32 | #define TRNG_CNTL_REG_TRNG_ENABLE BIT(10) |
33 | |
34 | /* Data ready indicator in STATUS register */ |
35 | #define TRNG_STATUS_REG_READY BIT(0) |
36 | |
37 | /* Data ready clear control in INTACK register */ |
38 | #define TRNG_INTACK_REG_READY BIT(0) |
39 | |
40 | /* |
41 | * Number of samples taken to gather entropy during startup. |
42 | * If value is 0, the number of samples is 2^24 else |
43 | * equals value times 2^8. |
44 | */ |
45 | #define TRNG_DEF_STARTUP_CYCLES 0 |
46 | #define TRNG_CNTL_REG_STARTUP_CYCLES_SHIFT 16 |
47 | |
48 | /* |
49 | * Minimum number of samples taken to regenerate entropy |
50 | * If value is 0, the number of samples is 2^24 else |
51 | * equals value times 2^6. |
52 | */ |
53 | #define TRNG_DEF_MIN_REFILL_CYCLES 1 |
54 | #define TRNG_CFG_REG_MIN_REFILL_CYCLES_SHIFT 0 |
55 | |
56 | /* |
57 | * Maximum number of samples taken to regenerate entropy |
58 | * If value is 0, the number of samples is 2^24 else |
59 | * equals value times 2^8. |
60 | */ |
61 | #define TRNG_DEF_MAX_REFILL_CYCLES 0 |
62 | #define TRNG_CFG_REG_MAX_REFILL_CYCLES_SHIFT 16 |
63 | |
64 | /* Number of CLK input cycles between samples */ |
65 | #define TRNG_DEF_CLK_DIV_CYCLES 0 |
66 | #define TRNG_CFG_REG_SAMPLE_DIV_SHIFT 8 |
67 | |
68 | /* Maximum retries to get rng data */ |
69 | #define SA_MAX_RNG_DATA_RETRIES 5 |
70 | /* Delay between retries (in usecs) */ |
71 | #define SA_RNG_DATA_RETRY_DELAY 5 |
72 | |
73 | struct trng_regs { |
74 | u32 output_l; |
75 | u32 output_h; |
76 | u32 status; |
77 | u32 intmask; |
78 | u32 intack; |
79 | u32 control; |
80 | u32 config; |
81 | }; |
82 | |
83 | struct ks_sa_rng { |
84 | struct hwrng rng; |
85 | struct clk *clk; |
86 | struct regmap *regmap_cfg; |
87 | struct trng_regs __iomem *reg_rng; |
88 | u64 ready_ts; |
89 | unsigned int refill_delay_ns; |
90 | }; |
91 | |
92 | static unsigned int cycles_to_ns(unsigned long clk_rate, unsigned int cycles) |
93 | { |
94 | return DIV_ROUND_UP_ULL((TRNG_DEF_CLK_DIV_CYCLES + 1) * 1000000000ull * |
95 | cycles, clk_rate); |
96 | } |
97 | |
98 | static unsigned int startup_delay_ns(unsigned long clk_rate) |
99 | { |
100 | if (!TRNG_DEF_STARTUP_CYCLES) |
101 | return cycles_to_ns(clk_rate, BIT(24)); |
102 | return cycles_to_ns(clk_rate, cycles: 256 * TRNG_DEF_STARTUP_CYCLES); |
103 | } |
104 | |
105 | static unsigned int refill_delay_ns(unsigned long clk_rate) |
106 | { |
107 | if (!TRNG_DEF_MAX_REFILL_CYCLES) |
108 | return cycles_to_ns(clk_rate, BIT(24)); |
109 | return cycles_to_ns(clk_rate, cycles: 256 * TRNG_DEF_MAX_REFILL_CYCLES); |
110 | } |
111 | |
112 | static int ks_sa_rng_init(struct hwrng *rng) |
113 | { |
114 | u32 value; |
115 | struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng); |
116 | unsigned long clk_rate = clk_get_rate(clk: ks_sa_rng->clk); |
117 | |
118 | /* Enable RNG module */ |
119 | regmap_write_bits(map: ks_sa_rng->regmap_cfg, SA_CMD_STATUS_OFS, |
120 | SA_CMD_STATUS_REG_TRNG_ENABLE, |
121 | SA_CMD_STATUS_REG_TRNG_ENABLE); |
122 | |
123 | /* Configure RNG module */ |
124 | writel(val: 0, addr: &ks_sa_rng->reg_rng->control); |
125 | value = TRNG_DEF_STARTUP_CYCLES << TRNG_CNTL_REG_STARTUP_CYCLES_SHIFT; |
126 | writel(val: value, addr: &ks_sa_rng->reg_rng->control); |
127 | |
128 | value = (TRNG_DEF_MIN_REFILL_CYCLES << |
129 | TRNG_CFG_REG_MIN_REFILL_CYCLES_SHIFT) | |
130 | (TRNG_DEF_MAX_REFILL_CYCLES << |
131 | TRNG_CFG_REG_MAX_REFILL_CYCLES_SHIFT) | |
132 | (TRNG_DEF_CLK_DIV_CYCLES << |
133 | TRNG_CFG_REG_SAMPLE_DIV_SHIFT); |
134 | |
135 | writel(val: value, addr: &ks_sa_rng->reg_rng->config); |
136 | |
137 | /* Disable all interrupts from TRNG */ |
138 | writel(val: 0, addr: &ks_sa_rng->reg_rng->intmask); |
139 | |
140 | /* Enable RNG */ |
141 | value = readl(addr: &ks_sa_rng->reg_rng->control); |
142 | value |= TRNG_CNTL_REG_TRNG_ENABLE; |
143 | writel(val: value, addr: &ks_sa_rng->reg_rng->control); |
144 | |
145 | ks_sa_rng->refill_delay_ns = refill_delay_ns(clk_rate); |
146 | ks_sa_rng->ready_ts = ktime_get_ns() + |
147 | startup_delay_ns(clk_rate); |
148 | |
149 | return 0; |
150 | } |
151 | |
152 | static void ks_sa_rng_cleanup(struct hwrng *rng) |
153 | { |
154 | struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng); |
155 | |
156 | /* Disable RNG */ |
157 | writel(val: 0, addr: &ks_sa_rng->reg_rng->control); |
158 | regmap_write_bits(map: ks_sa_rng->regmap_cfg, SA_CMD_STATUS_OFS, |
159 | SA_CMD_STATUS_REG_TRNG_ENABLE, val: 0); |
160 | } |
161 | |
162 | static int ks_sa_rng_data_read(struct hwrng *rng, u32 *data) |
163 | { |
164 | struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng); |
165 | |
166 | /* Read random data */ |
167 | data[0] = readl(addr: &ks_sa_rng->reg_rng->output_l); |
168 | data[1] = readl(addr: &ks_sa_rng->reg_rng->output_h); |
169 | |
170 | writel(TRNG_INTACK_REG_READY, addr: &ks_sa_rng->reg_rng->intack); |
171 | ks_sa_rng->ready_ts = ktime_get_ns() + ks_sa_rng->refill_delay_ns; |
172 | |
173 | return sizeof(u32) * 2; |
174 | } |
175 | |
176 | static int ks_sa_rng_data_present(struct hwrng *rng, int wait) |
177 | { |
178 | struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng); |
179 | u64 now = ktime_get_ns(); |
180 | |
181 | u32 ready; |
182 | int j; |
183 | |
184 | if (wait && now < ks_sa_rng->ready_ts) { |
185 | /* Max delay expected here is 81920000 ns */ |
186 | unsigned long min_delay = |
187 | DIV_ROUND_UP((u32)(ks_sa_rng->ready_ts - now), 1000); |
188 | |
189 | usleep_range(min: min_delay, max: min_delay + SA_RNG_DATA_RETRY_DELAY); |
190 | } |
191 | |
192 | for (j = 0; j < SA_MAX_RNG_DATA_RETRIES; j++) { |
193 | ready = readl(addr: &ks_sa_rng->reg_rng->status); |
194 | ready &= TRNG_STATUS_REG_READY; |
195 | |
196 | if (ready || !wait) |
197 | break; |
198 | |
199 | udelay(SA_RNG_DATA_RETRY_DELAY); |
200 | } |
201 | |
202 | return ready; |
203 | } |
204 | |
205 | static int ks_sa_rng_probe(struct platform_device *pdev) |
206 | { |
207 | struct ks_sa_rng *ks_sa_rng; |
208 | struct device *dev = &pdev->dev; |
209 | int ret; |
210 | |
211 | ks_sa_rng = devm_kzalloc(dev, size: sizeof(*ks_sa_rng), GFP_KERNEL); |
212 | if (!ks_sa_rng) |
213 | return -ENOMEM; |
214 | |
215 | ks_sa_rng->rng = (struct hwrng) { |
216 | .name = "ks_sa_hwrng" , |
217 | .init = ks_sa_rng_init, |
218 | .data_read = ks_sa_rng_data_read, |
219 | .data_present = ks_sa_rng_data_present, |
220 | .cleanup = ks_sa_rng_cleanup, |
221 | }; |
222 | |
223 | ks_sa_rng->reg_rng = devm_platform_ioremap_resource(pdev, index: 0); |
224 | if (IS_ERR(ptr: ks_sa_rng->reg_rng)) |
225 | return PTR_ERR(ptr: ks_sa_rng->reg_rng); |
226 | |
227 | ks_sa_rng->regmap_cfg = |
228 | syscon_regmap_lookup_by_phandle(np: dev->of_node, |
229 | property: "ti,syscon-sa-cfg" ); |
230 | |
231 | if (IS_ERR(ptr: ks_sa_rng->regmap_cfg)) |
232 | return dev_err_probe(dev, err: -EINVAL, fmt: "syscon_node_to_regmap failed\n" ); |
233 | |
234 | pm_runtime_enable(dev); |
235 | ret = pm_runtime_resume_and_get(dev); |
236 | if (ret < 0) { |
237 | pm_runtime_disable(dev); |
238 | return dev_err_probe(dev, err: ret, fmt: "Failed to enable SA power-domain\n" ); |
239 | } |
240 | |
241 | return devm_hwrng_register(dev: &pdev->dev, rng: &ks_sa_rng->rng); |
242 | } |
243 | |
244 | static int ks_sa_rng_remove(struct platform_device *pdev) |
245 | { |
246 | pm_runtime_put_sync(dev: &pdev->dev); |
247 | pm_runtime_disable(dev: &pdev->dev); |
248 | |
249 | return 0; |
250 | } |
251 | |
252 | static const struct of_device_id ks_sa_rng_dt_match[] = { |
253 | { |
254 | .compatible = "ti,keystone-rng" , |
255 | }, |
256 | { }, |
257 | }; |
258 | MODULE_DEVICE_TABLE(of, ks_sa_rng_dt_match); |
259 | |
260 | static struct platform_driver ks_sa_rng_driver = { |
261 | .driver = { |
262 | .name = "ks-sa-rng" , |
263 | .of_match_table = ks_sa_rng_dt_match, |
264 | }, |
265 | .probe = ks_sa_rng_probe, |
266 | .remove = ks_sa_rng_remove, |
267 | }; |
268 | |
269 | module_platform_driver(ks_sa_rng_driver); |
270 | |
271 | MODULE_DESCRIPTION("Keystone NETCP SA H/W Random Number Generator driver" ); |
272 | MODULE_AUTHOR("Vitaly Andrianov <vitalya@ti.com>" ); |
273 | MODULE_LICENSE("GPL" ); |
274 | |