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