1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * TRNG driver for the StarFive JH7110 SoC 4 * 5 * Copyright (C) 2022 StarFive Technology Co. 6 */ 7 8 #include <linux/clk.h> 9 #include <linux/completion.h> 10 #include <linux/delay.h> 11 #include <linux/err.h> 12 #include <linux/hw_random.h> 13 #include <linux/interrupt.h> 14 #include <linux/io.h> 15 #include <linux/iopoll.h> 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/of.h> 19 #include <linux/platform_device.h> 20 #include <linux/pm_runtime.h> 21 #include <linux/random.h> 22 #include <linux/reset.h> 23 24 /* trng register offset */ 25 #define STARFIVE_CTRL 0x00 26 #define STARFIVE_STAT 0x04 27 #define STARFIVE_MODE 0x08 28 #define STARFIVE_SMODE 0x0C 29 #define STARFIVE_IE 0x10 30 #define STARFIVE_ISTAT 0x14 31 #define STARFIVE_RAND0 0x20 32 #define STARFIVE_RAND1 0x24 33 #define STARFIVE_RAND2 0x28 34 #define STARFIVE_RAND3 0x2C 35 #define STARFIVE_RAND4 0x30 36 #define STARFIVE_RAND5 0x34 37 #define STARFIVE_RAND6 0x38 38 #define STARFIVE_RAND7 0x3C 39 #define STARFIVE_AUTO_RQSTS 0x60 40 #define STARFIVE_AUTO_AGE 0x64 41 42 /* CTRL CMD */ 43 #define STARFIVE_CTRL_EXEC_NOP 0x0 44 #define STARFIVE_CTRL_GENE_RANDNUM 0x1 45 #define STARFIVE_CTRL_EXEC_RANDRESEED 0x2 46 47 /* STAT */ 48 #define STARFIVE_STAT_NONCE_MODE BIT(2) 49 #define STARFIVE_STAT_R256 BIT(3) 50 #define STARFIVE_STAT_MISSION_MODE BIT(8) 51 #define STARFIVE_STAT_SEEDED BIT(9) 52 #define STARFIVE_STAT_LAST_RESEED(x) ((x) << 16) 53 #define STARFIVE_STAT_SRVC_RQST BIT(27) 54 #define STARFIVE_STAT_RAND_GENERATING BIT(30) 55 #define STARFIVE_STAT_RAND_SEEDING BIT(31) 56 57 /* MODE */ 58 #define STARFIVE_MODE_R256 BIT(3) 59 60 /* SMODE */ 61 #define STARFIVE_SMODE_NONCE_MODE BIT(2) 62 #define STARFIVE_SMODE_MISSION_MODE BIT(8) 63 #define STARFIVE_SMODE_MAX_REJECTS(x) ((x) << 16) 64 65 /* IE */ 66 #define STARFIVE_IE_RAND_RDY_EN BIT(0) 67 #define STARFIVE_IE_SEED_DONE_EN BIT(1) 68 #define STARFIVE_IE_LFSR_LOCKUP_EN BIT(4) 69 #define STARFIVE_IE_GLBL_EN BIT(31) 70 71 #define STARFIVE_IE_ALL (STARFIVE_IE_GLBL_EN | \ 72 STARFIVE_IE_RAND_RDY_EN | \ 73 STARFIVE_IE_SEED_DONE_EN | \ 74 STARFIVE_IE_LFSR_LOCKUP_EN) 75 76 /* ISTAT */ 77 #define STARFIVE_ISTAT_RAND_RDY BIT(0) 78 #define STARFIVE_ISTAT_SEED_DONE BIT(1) 79 #define STARFIVE_ISTAT_LFSR_LOCKUP BIT(4) 80 81 #define STARFIVE_RAND_LEN sizeof(u32) 82 83 #define to_trng(p) container_of(p, struct starfive_trng, rng) 84 85 enum reseed { 86 RANDOM_RESEED, 87 NONCE_RESEED, 88 }; 89 90 enum mode { 91 PRNG_128BIT, 92 PRNG_256BIT, 93 }; 94 95 struct starfive_trng { 96 struct device *dev; 97 void __iomem *base; 98 struct clk *hclk; 99 struct clk *ahb; 100 struct reset_control *rst; 101 struct hwrng rng; 102 struct completion random_done; 103 struct completion reseed_done; 104 u32 mode; 105 u32 mission; 106 u32 reseed; 107 /* protects against concurrent write to ctrl register */ 108 spinlock_t write_lock; 109 }; 110 111 static u16 autoreq; 112 module_param(autoreq, ushort, 0); 113 MODULE_PARM_DESC(autoreq, "Auto-reseeding after random number requests by host reaches specified counter:\n" 114 " 0 - disable counter\n" 115 " other - reload value for internal counter"); 116 117 static u16 autoage; 118 module_param(autoage, ushort, 0); 119 MODULE_PARM_DESC(autoage, "Auto-reseeding after specified timer countdowns to 0:\n" 120 " 0 - disable timer\n" 121 " other - reload value for internal timer"); 122 123 static inline int starfive_trng_wait_idle(struct starfive_trng *trng) 124 { 125 u32 stat; 126 127 return readl_relaxed_poll_timeout(trng->base + STARFIVE_STAT, stat, 128 !(stat & (STARFIVE_STAT_RAND_GENERATING | 129 STARFIVE_STAT_RAND_SEEDING)), 130 10, 100000); 131 } 132 133 static inline void starfive_trng_irq_mask_clear(struct starfive_trng *trng) 134 { 135 /* clear register: ISTAT */ 136 u32 data = readl(trng->base + STARFIVE_ISTAT); 137 138 writel(data, trng->base + STARFIVE_ISTAT); 139 } 140 141 static int starfive_trng_cmd(struct starfive_trng *trng, u32 cmd, bool wait) 142 { 143 int wait_time = 1000; 144 145 /* allow up to 40 us for wait == 0 */ 146 if (!wait) 147 wait_time = 40; 148 149 switch (cmd) { 150 case STARFIVE_CTRL_GENE_RANDNUM: 151 reinit_completion(&trng->random_done); 152 spin_lock_irq(&trng->write_lock); 153 writel(cmd, trng->base + STARFIVE_CTRL); 154 spin_unlock_irq(&trng->write_lock); 155 if (!wait_for_completion_timeout(&trng->random_done, usecs_to_jiffies(wait_time))) 156 return -ETIMEDOUT; 157 break; 158 case STARFIVE_CTRL_EXEC_RANDRESEED: 159 reinit_completion(&trng->reseed_done); 160 spin_lock_irq(&trng->write_lock); 161 writel(cmd, trng->base + STARFIVE_CTRL); 162 spin_unlock_irq(&trng->write_lock); 163 if (!wait_for_completion_timeout(&trng->reseed_done, usecs_to_jiffies(wait_time))) 164 return -ETIMEDOUT; 165 break; 166 default: 167 return -EINVAL; 168 } 169 170 return 0; 171 } 172 173 static int starfive_trng_init(struct hwrng *rng) 174 { 175 struct starfive_trng *trng = to_trng(rng); 176 u32 mode, intr = 0; 177 178 /* setup Auto Request/Age register */ 179 writel(autoage, trng->base + STARFIVE_AUTO_AGE); 180 writel(autoreq, trng->base + STARFIVE_AUTO_RQSTS); 181 182 /* clear register: ISTAT */ 183 starfive_trng_irq_mask_clear(trng); 184 185 intr |= STARFIVE_IE_ALL; 186 writel(intr, trng->base + STARFIVE_IE); 187 188 mode = readl(trng->base + STARFIVE_MODE); 189 190 switch (trng->mode) { 191 case PRNG_128BIT: 192 mode &= ~STARFIVE_MODE_R256; 193 break; 194 case PRNG_256BIT: 195 mode |= STARFIVE_MODE_R256; 196 break; 197 default: 198 mode |= STARFIVE_MODE_R256; 199 break; 200 } 201 202 writel(mode, trng->base + STARFIVE_MODE); 203 204 return starfive_trng_cmd(trng, STARFIVE_CTRL_EXEC_RANDRESEED, 1); 205 } 206 207 static irqreturn_t starfive_trng_irq(int irq, void *priv) 208 { 209 u32 status; 210 struct starfive_trng *trng = (struct starfive_trng *)priv; 211 212 status = readl(trng->base + STARFIVE_ISTAT); 213 if (status & STARFIVE_ISTAT_RAND_RDY) { 214 writel(STARFIVE_ISTAT_RAND_RDY, trng->base + STARFIVE_ISTAT); 215 complete(&trng->random_done); 216 } 217 218 if (status & STARFIVE_ISTAT_SEED_DONE) { 219 writel(STARFIVE_ISTAT_SEED_DONE, trng->base + STARFIVE_ISTAT); 220 complete(&trng->reseed_done); 221 } 222 223 if (status & STARFIVE_ISTAT_LFSR_LOCKUP) { 224 writel(STARFIVE_ISTAT_LFSR_LOCKUP, trng->base + STARFIVE_ISTAT); 225 /* SEU occurred, reseeding required*/ 226 spin_lock(&trng->write_lock); 227 writel(STARFIVE_CTRL_EXEC_RANDRESEED, trng->base + STARFIVE_CTRL); 228 spin_unlock(&trng->write_lock); 229 } 230 231 return IRQ_HANDLED; 232 } 233 234 static void starfive_trng_cleanup(struct hwrng *rng) 235 { 236 struct starfive_trng *trng = to_trng(rng); 237 238 writel(0, trng->base + STARFIVE_CTRL); 239 240 reset_control_assert(trng->rst); 241 clk_disable_unprepare(trng->hclk); 242 clk_disable_unprepare(trng->ahb); 243 } 244 245 static int starfive_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait) 246 { 247 struct starfive_trng *trng = to_trng(rng); 248 int ret; 249 250 pm_runtime_get_sync(trng->dev); 251 252 if (trng->mode == PRNG_256BIT) 253 max = min_t(size_t, max, (STARFIVE_RAND_LEN * 8)); 254 else 255 max = min_t(size_t, max, (STARFIVE_RAND_LEN * 4)); 256 257 if (wait) { 258 ret = starfive_trng_wait_idle(trng); 259 if (ret) 260 return -ETIMEDOUT; 261 } 262 263 ret = starfive_trng_cmd(trng, STARFIVE_CTRL_GENE_RANDNUM, wait); 264 if (ret) 265 return ret; 266 267 memcpy_fromio(buf, trng->base + STARFIVE_RAND0, max); 268 269 pm_runtime_put_sync_autosuspend(trng->dev); 270 271 return max; 272 } 273 274 static int starfive_trng_probe(struct platform_device *pdev) 275 { 276 int ret; 277 int irq; 278 struct starfive_trng *trng; 279 280 trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); 281 if (!trng) 282 return -ENOMEM; 283 284 platform_set_drvdata(pdev, trng); 285 trng->dev = &pdev->dev; 286 287 trng->base = devm_platform_ioremap_resource(pdev, 0); 288 if (IS_ERR(trng->base)) 289 return dev_err_probe(&pdev->dev, PTR_ERR(trng->base), 290 "Error remapping memory for platform device.\n"); 291 292 irq = platform_get_irq(pdev, 0); 293 if (irq < 0) 294 return irq; 295 296 init_completion(&trng->random_done); 297 init_completion(&trng->reseed_done); 298 spin_lock_init(&trng->write_lock); 299 300 ret = devm_request_irq(&pdev->dev, irq, starfive_trng_irq, 0, pdev->name, 301 (void *)trng); 302 if (ret) 303 return dev_err_probe(&pdev->dev, ret, 304 "Failed to register interrupt handler\n"); 305 306 trng->hclk = devm_clk_get(&pdev->dev, "hclk"); 307 if (IS_ERR(trng->hclk)) 308 return dev_err_probe(&pdev->dev, PTR_ERR(trng->hclk), 309 "Error getting hardware reference clock\n"); 310 311 trng->ahb = devm_clk_get(&pdev->dev, "ahb"); 312 if (IS_ERR(trng->ahb)) 313 return dev_err_probe(&pdev->dev, PTR_ERR(trng->ahb), 314 "Error getting ahb reference clock\n"); 315 316 trng->rst = devm_reset_control_get_shared(&pdev->dev, NULL); 317 if (IS_ERR(trng->rst)) 318 return dev_err_probe(&pdev->dev, PTR_ERR(trng->rst), 319 "Error getting hardware reset line\n"); 320 321 clk_prepare_enable(trng->hclk); 322 clk_prepare_enable(trng->ahb); 323 reset_control_deassert(trng->rst); 324 325 trng->rng.name = dev_driver_string(&pdev->dev); 326 trng->rng.init = starfive_trng_init; 327 trng->rng.cleanup = starfive_trng_cleanup; 328 trng->rng.read = starfive_trng_read; 329 330 trng->mode = PRNG_256BIT; 331 trng->mission = 1; 332 trng->reseed = RANDOM_RESEED; 333 334 pm_runtime_use_autosuspend(&pdev->dev); 335 pm_runtime_set_autosuspend_delay(&pdev->dev, 100); 336 pm_runtime_enable(&pdev->dev); 337 338 ret = devm_hwrng_register(&pdev->dev, &trng->rng); 339 if (ret) { 340 pm_runtime_disable(&pdev->dev); 341 342 reset_control_assert(trng->rst); 343 clk_disable_unprepare(trng->ahb); 344 clk_disable_unprepare(trng->hclk); 345 346 return dev_err_probe(&pdev->dev, ret, "Failed to register hwrng\n"); 347 } 348 349 return 0; 350 } 351 352 static int __maybe_unused starfive_trng_suspend(struct device *dev) 353 { 354 struct starfive_trng *trng = dev_get_drvdata(dev); 355 356 clk_disable_unprepare(trng->hclk); 357 clk_disable_unprepare(trng->ahb); 358 359 return 0; 360 } 361 362 static int __maybe_unused starfive_trng_resume(struct device *dev) 363 { 364 struct starfive_trng *trng = dev_get_drvdata(dev); 365 366 clk_prepare_enable(trng->hclk); 367 clk_prepare_enable(trng->ahb); 368 369 return 0; 370 } 371 372 static DEFINE_SIMPLE_DEV_PM_OPS(starfive_trng_pm_ops, starfive_trng_suspend, 373 starfive_trng_resume); 374 375 static const struct of_device_id trng_dt_ids[] __maybe_unused = { 376 { .compatible = "starfive,jh7110-trng" }, 377 { } 378 }; 379 MODULE_DEVICE_TABLE(of, trng_dt_ids); 380 381 static struct platform_driver starfive_trng_driver = { 382 .probe = starfive_trng_probe, 383 .driver = { 384 .name = "jh7110-trng", 385 .pm = &starfive_trng_pm_ops, 386 .of_match_table = of_match_ptr(trng_dt_ids), 387 }, 388 }; 389 390 module_platform_driver(starfive_trng_driver); 391 392 MODULE_LICENSE("GPL"); 393 MODULE_DESCRIPTION("StarFive True Random Number Generator"); 394